diff --git a/.editorconfig b/.editorconfig index 87dbf152d..55dea7113 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,6 +7,10 @@ root = true indent_style = tab indent_size = 8 +[Makefile] +indent_style = tab +indent_size = 8 + [*] end_of_line = lf charset = utf-8 diff --git a/.gitignore b/.gitignore index 22871b60f..1d334feed 100644 --- a/.gitignore +++ b/.gitignore @@ -20,5 +20,7 @@ Module.symvers modules.order compile_commands.json -.cache/ -output/ +/.cache/ + +/include/ +/output/ diff --git a/03-Bus/01-Platform/01-osdev/Makefile b/03-Bus/01-Platform/01-osdev/Makefile index 770d965f6..2bb75eccc 100644 --- a/03-Bus/01-Platform/01-osdev/Makefile +++ b/03-Bus/01-Platform/01-osdev/Makefile @@ -10,6 +10,8 @@ # Path information #******************************************************************************* LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) + +DRIVER_DIR := $(realpath $(LOCAL_DIR)/../../..) KERNEL_DIR ?= /home/gaoyang3513/Source/06-SG20x/02-Projects/SDK_SG200x_V2/linux_5.10/build/sg2000_milkv_duos_glibc_arm64_sd #KERNEL_DIR ?= $(HOME)/Source/06-SG20x/02-Projects/SDK_SG200x_V2/linux_5.10/build/sg2000_milkv_duos_glibc_arm64_sd/ @@ -47,9 +49,17 @@ export ARCH CROSS_COMPILE #******************************************************************************* # Targets #******************************************************************************* +# Read auto.conf if it exists, otherwise ignore +-include $(DRIVER_DIR)/include/config/auto.conf + .PHONY: all install clean -ifeq ($(KERNELRELEASE),) +ifeq ($(CONFIG_DRIVER_BUS_PLATFORM_OSDEV),) +all: + $(Q)echo -n "" +install: + $(Q)echo "[SKIP] OSAL_osdev" +else ifeq ($(KERNELRELEASE),) all: init @$(MAKE) modules -C $(KERNEL_DIR) M=$(LOCAL_DIR) -j$(MULTI_CORES) # @$(MAKE) modules_install -C $(KERNEL_DIR) M=$(LOCAL_DIR) INSTALL_MOD_PATH=$(KERNEL_DIR)/_install_modules INSTALL_MOD_DIR=private diff --git a/03-Bus/01-Platform/01-osdev/OSAL_osdev.c.bak b/03-Bus/01-Platform/01-osdev/OSAL_osdev.c.bak new file mode 100644 index 000000000..6a3817cf6 --- /dev/null +++ b/03-Bus/01-Platform/01-osdev/OSAL_osdev.c.bak @@ -0,0 +1,185 @@ +/******************************************************************************* + * HangZhou Hikvision Digital Technology Co., Ltd. All Right Reserved. + * Author : + * Version : V1.0.0 2024.11.15 + * Description : + * Note : anonymity@hikvision.com.cn Modified 2024.11.15 + ******************************************************************************/ +#include +#include +#include +#include +#include +#include // MKDEV + +#include "OSAL_osdev.h" + +struct device osal_bus = { + .init_name = "osal", +}; + +struct bus_type osal_bus_type = { + .name = "osal", +}; + +struct osdev_device { // Object + struct device dev; + char name[]; +}; + +struct osdev_driver { + struct device_driver drv; +}; + +static void osadev_device_release(struct device *dev) +{ + struct osdev_device *osdev_obj = container_of(dev, struct osdev_device, dev); + + kfree(osdev_obj); +} + +OSAL_osdev *OSAL_osdevAlloc(const char *name, int id) +{ + struct device *dev = NULL; + struct osdev *osdev = NULL; + struct osdev_device *osdev_obj = NULL; + + osdev_obj = kzalloc(sizeof(struct osdev_device) + strlen(name) + 1, GFP_KERNEL); + if (!osdev_obj) { + pr_err("ErrNo(%ld), alloc memory for OSAL_sysDevice failed.", PTR_ERR(dev)); + return ERR_PTR(-ENOMEM); + } + osdev = &(osdev_obj->osdev); + dev = &(osdev_obj->dev); + + strcpy(osdev_obj->name, name); + osdev->name = osdev_obj->name; + osdev->id = id; + device_initialize(dev); + dev->release = osadev_device_release; + + osdev->obj = osdev; + + return (OSAL_osdev *)osdev; +} +EXPORT_SYMBOL(OSAL_osdevAlloc); + +int OSAL_osdevRegister(OSAL_osdev *osdev) +{ + int ret = 0; + struct device *dev = NULL; + struct osdev *osdev_tmp = NULL; + struct osdev_device *osdev_obj = NULL; + struct osdev_device *osdev_parent = NULL; + + if (osdev == NULL) { + pr_err("Error, null pointer exception."); + return -EINVAL; + } + + if (!osdev->obj) { + osdev_tmp = OSAL_osdevAlloc(osdev->name, osdev->id); + osdev->obj = osdev_tmp; + } + else { + osdev_tmp = osdev->obj; + osdev_parent = container_of(osdev_tmp, struct osdev_device, osdev); + } + osdev_obj = container_of(osdev_tmp->obj, struct osdev_device, osdev); + dev = &(osdev_obj->dev); + + dev_set_name(dev, "%s.%d", osdev->name, osdev->id); + dev_set_drvdata(dev, osdev_obj); + dev->bus = &osal_bus_type; + dev->devt = MKDEV(0, 0); + dev->parent = osdev_parent ? &osdev_parent->dev : &osal_bus; + + ret = device_add(dev); + if (ret) { + pr_err("ErrNo(%d), add device failed.", ret); + put_device(dev); + return ret; + } + + return ret; +} +EXPORT_SYMBOL(OSAL_osdevRegister); + +void OSAL_osdevUnregister(OSAL_osdev *osdev) +{ + struct osdev_device *osdev_obj = NULL; + + if (osdev == NULL || osdev->obj == NULL) { + pr_err("Error, null pointer exception."); + return; + } + + osdev_obj = container_of(osdev->obj, struct osdev_device, osdev); + + device_del(&osdev_obj->dev); + put_device(&osdev_obj->dev); +} +EXPORT_SYMBOL(OSAL_osdevUnregister); + +inline void *OSAL_osdevGetDrvdata(const OSAL_osdev *osdev) +{ + struct osdev_device *osdev_obj = NULL; + + if (osdev == NULL || osdev->obj == NULL) { + pr_err("Error, null pointer exception."); + return ERR_PTR(-EINVAL); + } + + osdev_obj = container_of(osdev->obj, struct osdev_device, osdev); + + return dev_get_drvdata(&osdev_obj->dev); +} +EXPORT_SYMBOL(OSAL_osdevGetDrvdata); + +inline void OSAL_osdevSetDrvdata(OSAL_osdev *osdev, void *data) +{ + struct osdev_device *osdev_obj = NULL; + + if (osdev == NULL || osdev->obj == NULL) { + pr_err("Error, null pointer exception."); + return; + } + + osdev_obj = container_of(osdev->obj, struct osdev_device, osdev); + + dev_set_drvdata(&osdev_obj->dev, data); +} +EXPORT_SYMBOL(OSAL_osdevSetDrvdata); + +int __init OSAL_osdevInit(void) +{ + int ret = 0; + + ret = device_register(&osal_bus); + if (ret) { + pr_err("ErrNo(%d), register bus Device[osal] failed.", ret); + put_device(&osal_bus); + goto out; + } + + ret = bus_register(&osal_bus_type); + if (ret) { + pr_err("ErrNo(%d), register bus Type[osal] failed.", ret); + goto out_unregister_bus; + } + + pr_info("OSAL_osdev initialize completed."); + + return ret; + +out_unregister_bus: + device_unregister(&osal_bus); +out: + return ret; +} + +void __exit OSAL_osdevExit(void) +{ + bus_unregister(&osal_bus_type); + device_unregister(&osal_bus); +} diff --git a/03-Bus/01-Platform/01-osdev/OSAL_osdev.h.bak b/03-Bus/01-Platform/01-osdev/OSAL_osdev.h.bak new file mode 100644 index 000000000..e02ae2953 --- /dev/null +++ b/03-Bus/01-Platform/01-osdev/OSAL_osdev.h.bak @@ -0,0 +1,28 @@ +/******************************************************************************* + * HangZhou Hikvision Digital Technology Co., Ltd. All Right Reserved. + * Author : + * Version : V1.0.0 2024.11.15 + * Description : + * Note : anonymity@hikvision.com.cn Modified 2024.11.15 + ******************************************************************************/ +#ifndef INCLUDE_WIDGET_OSAL_OSDEV_H_ +#define INCLUDE_WIDGET_OSAL_OSDEV_H_ + +typedef struct osdev { + int id; + const char *name; + void *obj; +} OSAL_osdev; + +typedef struct osdrv { + int (*probe)(struct osdev *); + int (*remove)(struct osdev *); + void *obj; +} OSAL_osdrv; + +int OSAL_osdevRegister(OSAL_osdev *osdev); +void OSAL_osdevUnregister(OSAL_osdev *osdev); +void *OSAL_osdevGetDrvdata(const OSAL_osdev *osdev); +void OSAL_osdevSetDrvdata(OSAL_osdev *osdev, void *data); + +#endif /* INCLUDE_WIDGET_OSAL_OSDEV_H_ */ diff --git a/Makefile b/Makefile index 21205fd45..b8e9a5d0b 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,18 @@ -#******************************************************************************* -# HangZhou Hikvision Digital Technology Co., Ltd. All Right Reserved. +# ---------------------------------------------------------------------------- # +# All Right Reserved. # Author : # Version : V1.0.0 202x.01.01 # Description : -# Note : gaoyang@.com.cn Modified 2020.10.21 -#******************************************************************************* +# Note : gaoyang3513@163.com.cn Modified 202x.01.01 +# ---------------------------------------------------------------------------- # +# That's our default target when none is given on the command line +PHONY := all +all: -#******************************************************************************* +# ---------------------------------------------------------------------------- # # Path information -#******************************************************************************* -LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) +# ---------------------------------------------------------------------------- # +LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) # SDK directories SDK_TOP ?= $(HOME)/Source/15-SG200x/01-MilkDuo/02-Project/SDK_SG200x_V2.0.0 @@ -17,26 +20,53 @@ KERNEL_DIR ?= $(SDK_TOP)/linux_5.10/build/sg2000_milkv_duos_glibc_arm64_sd TOOLCHAIN_DIR ?= $(SDK_TOP)/host-tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin # Subdirectory - -OUTPUT_DIR := $(LOCAL_DIR)/output -INSTALL_DIR ?= $(LOCAL_DIR)/__install -#$(info Output directoty : $(OUTPUT_DIR)) -#$(info Install directoty: $(INSTALL_DIR)) +OUTPUT_DIR := $(LOCAL_DIR)/output +INSTALL_DIR ?= $(LOCAL_DIR)/__install export KERNEL_DIR -#******************************************************************************* +# ---------------------------------------------------------------------------- # +# Functions +# ---------------------------------------------------------------------------- # +define filechk_version.h + echo \#define LINUX_VERSION_CODE $(shell \ + expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \ + echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' +endef + +# ---------------------------------------------------------------------------- # # Variables -#******************************************************************************* -MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo) +# ---------------------------------------------------------------------------- # +VERSION = 1 +PATCHLEVEL = 1 +SUBLEVEL = 0 +EXTRAVERSION = +NAME = Kleptomaniac Octopus -SUB_DIRS := \ - 04-Debug \ - 03-Bus/01-Platform/01-osdev \ +version_h := include/generated/version.h -#******************************************************************************* +MAKEFLAGS += --no-print-directory + +MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo) + +ifeq ("$(origin V)", "command line") + KBUILD_VERBOSE = $(V) +endif +ifndef KBUILD_VERBOSE + KBUILD_VERBOSE = 0 +endif + +ifeq ($(KBUILD_VERBOSE),1) + quiet = + Q = +else + quiet = quiet_ + Q = @ +endif + +export Q quiet +# ---------------------------------------------------------------------------- # # Compile configure -#******************************************************************************* -#ARCH ?= riscv +# ---------------------------------------------------------------------------- # #CROSS_COMPILE ?= riscv64-unknown-linux-musl- ARCH ?= arm64 CROSS_COMPILE ?= aarch64-linux-gnu- @@ -49,47 +79,57 @@ STRIP := $(CROSS_COMPILE)strip PATH := $(TOOLCHAIN_DIR):$(PATH) export ARCH CROSS_COMPILE PATH -#******************************************************************************* -# Targets -#******************************************************************************* -.PHONY: init all clean distclean install menuconfig -ifeq ($(KERNELRELEASE),) +# ---------------------------------------------------------------------------- # +# Objects +# ---------------------------------------------------------------------------- # +SUB_DIRS := 03-Bus/01-Platform/01-osdev +#$(warning "SUB_DIRS: $(SUB_DIRS)") + +# ---------------------------------------------------------------------------- # +# Targets +# ---------------------------------------------------------------------------- # +.PHONY += init all clean distclean install menuconfig oldconfig $(version_h) + +include scripts/Kbuild.include + all: init - @for sub in $(SUB_DIRS); do \ + $(Q)for sub in $(SUB_DIRS); do \ $(MAKE) -C $$sub; \ $(MAKE) install INSTALL_DIR=$(OUTPUT_DIR) -C $$sub || exit "$$?"; \ done; clean: - @for sub in $(SUB_DIRS); do \ + $(Q)for sub in $(SUB_DIRS); do \ $(MAKE) clean -C $$sub || exit "$$?"; \ done; # Directory - @if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi; - @if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi; + $(Q)if [ -d $(LOCAL_DIR)/include/config ]; then rm -rf $(LOCAL_DIR)/include/config; fi; + $(Q)if [ -d $(LOCAL_DIR)/include/generated ]; then rm -rf $(LOCAL_DIR)/include/generated; fi; + $(Q)if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi; + $(Q)if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi; install: - @mkdir -p $(INSTALL_DIR) - @cp -arf $(OUTPUT_DIR)/. $(INSTALL_DIR) + $(Q)mkdir -p $(INSTALL_DIR) + $(Q)cp -arf $(OUTPUT_DIR)/. $(INSTALL_DIR) -init: - @mkdir -p $(OUTPUT_DIR); +init: $(version_h) + $(Q)mkdir -p $(OUTPUT_DIR); + $(Q)mkdir -p include/config include/generated + $(Q)$(LOCAL_DIR)/scripts/kconfig/Kconfiglib/genconfig.py --sync-dep include/config --header-path include/generated/autoconf.h + +oldconfig: + $(Q)$(LOCAL_DIR)/scripts/kconfig/Kconfiglib/oldconfig.py %_defconfig: - $(LOCAL_DIR)/scripts/kconfig/Kconfiglib/defconfig.py --kconfig Kconfig configs/$@ + $(Q)$(LOCAL_DIR)/scripts/kconfig/Kconfiglib/defconfig.py --kconfig Kconfig configs/$@ menuconfig: - $(LOCAL_DIR)/scripts/kconfig/Kconfiglib/menuconfig.py Kconfig + $(Q)mkdir -p include/config include/generated + $(Q)$(LOCAL_DIR)/scripts/kconfig/Kconfiglib/menuconfig.py Kconfig savedefconfig: - $(LOCAL_DIR)/scripts/kconfig/Kconfiglib/savedefconfig.py --kconfig Kconfig --out defconfig + $(Q)$(LOCAL_DIR)/scripts/kconfig/Kconfiglib/savedefconfig.py --kconfig Kconfig --out defconfig -else -# called from kernel build system: just declare what our modules are -obj-y += $(SUB_DIRS) - -#INC_DIRS := $(INCLUDE_DIR)/generated -#subdir-ccflags-y += $(addprefix -I, $(INC_DIRS)) - -endif # ifeq ($(KERNELRELEASE),) +$(version_h): + $(Q)$(call filechk,version.h) diff --git a/config.h b/config.h new file mode 100644 index 000000000..c13752cc1 --- /dev/null +++ b/config.h @@ -0,0 +1,9 @@ +#define CONFIG_MODULE_BUS 1 +#define CONFIG_DRIVER_BUS_PLATFORM 1 +#define CONFIG_DRIVER_BUS_PLATFORM_OSDEV 1 +#define CONFIG_BOOL 1 +#define CONFIG_STRING "foo" +#define CONFIG_INT 747 +#define CONFIG_HEX 0xABC +#define CONFIG_BOOL_CHOICE_SYM_1 1 +#define CONFIG_TRI_CHOICE_SYM_1 1 diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include new file mode 100644 index 000000000..08e011175 --- /dev/null +++ b/scripts/Kbuild.include @@ -0,0 +1,323 @@ +# SPDX-License-Identifier: GPL-2.0 +#### +# kbuild: Generic definitions + +# Convenient variables +comma := , +quote := " +squote := ' +empty := +space := $(empty) $(empty) +space_escape := _-_SPACE_-_ +pound := \# + +### +# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o +dot-target = $(dir $@).$(notdir $@) + +### +# The temporary file to save gcc -MMD generated dependencies must not +# contain a comma +depfile = $(subst $(comma),_,$(dot-target).d) + +### +# filename of target with directory and extension stripped +basetarget = $(basename $(notdir $@)) + +### +# real prerequisites without phony targets +real-prereqs = $(filter-out $(PHONY), $^) + +### +# Escape single quote for use in echo statements +escsq = $(subst $(squote),'\$(squote)',$1) + +### +# Quote a string to pass it to C files. foo => '"foo"' +stringify = $(squote)$(quote)$1$(quote)$(squote) + +### +# Easy method for doing a status message + kecho := : + quiet_kecho := echo +silent_kecho := : +kecho := $($(quiet)kecho) + +### +# filechk is used to check if the content of a generated file is updated. +# Sample usage: +# +# filechk_sample = echo $(KERNELRELEASE) +# version.h: FORCE +# $(call filechk,sample) +# +# The rule defined shall write to stdout the content of the new file. +# The existing file will be compared with the new one. +# - If no file exist it is created +# - If the content differ the new file is used +# - If they are equal no change, and no timestamp update +define filechk + $(Q)set -e; \ + mkdir -p $(dir $@); \ + trap "rm -f $(dot-target).tmp" EXIT; \ + { $(filechk_$(1)); } > $(dot-target).tmp; \ + if [ ! -r $@ ] || ! cmp -s $@ $(dot-target).tmp; then \ + $(kecho) ' UPD $@'; \ + mv -f $(dot-target).tmp $@; \ + fi +endef + +###### +# gcc support functions +# See documentation in Documentation/kbuild/makefiles.rst + +# cc-cross-prefix +# Usage: CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu- m68k-linux-) +# Return first where a gcc is found in PATH. +# If no gcc found in PATH with listed prefixes return nothing +# +# Note: '2>/dev/null' is here to force Make to invoke a shell. Otherwise, it +# would try to directly execute the shell builtin 'command'. This workaround +# should be kept for a long time since this issue was fixed only after the +# GNU Make 4.2.1 release. +cc-cross-prefix = $(firstword $(foreach c, $(1), \ + $(if $(shell command -v -- $(c)gcc 2>/dev/null), $(c)))) + +# output directory for tests below +TMPOUT = $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_$$$$ + +# try-run +# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise) +# Exit code chooses option. "$$TMP" serves as a temporary file and is +# automatically cleaned up. +try-run = $(shell set -e; \ + TMP=$(TMPOUT)/tmp; \ + TMPO=$(TMPOUT)/tmp.o; \ + mkdir -p $(TMPOUT); \ + trap "rm -rf $(TMPOUT)" EXIT; \ + if ($(1)) >/dev/null 2>&1; \ + then echo "$(2)"; \ + else echo "$(3)"; \ + fi) + +# as-option +# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) + +as-option = $(call try-run,\ + $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2)) + +# as-instr +# Usage: cflags-y += $(call as-instr,instr,option1,option2) + +as-instr = $(call try-run,\ + printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3)) + +# __cc-option +# Usage: MY_CFLAGS += $(call __cc-option,$(CC),$(MY_CFLAGS),-march=winchip-c6,-march=i586) +__cc-option = $(call try-run,\ + $(1) -Werror $(2) $(3) -c -x c /dev/null -o "$$TMP",$(3),$(4)) + +# cc-option +# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) + +cc-option = $(call __cc-option, $(CC),\ + $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS),$(1),$(2)) + +# cc-option-yn +# Usage: flag := $(call cc-option-yn,-march=winchip-c6) +cc-option-yn = $(call try-run,\ + $(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n) + +# cc-disable-warning +# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) +cc-disable-warning = $(call try-run,\ + $(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1))) + +# cc-ifversion +# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1) +cc-ifversion = $(shell [ $(CONFIG_GCC_VERSION)0 $(1) $(2)000 ] && echo $(3) || echo $(4)) + +# ld-option +# Usage: KBUILD_LDFLAGS += $(call ld-option, -X, -Y) +ld-option = $(call try-run, $(LD) $(KBUILD_LDFLAGS) $(1) -v,$(1),$(2),$(3)) + +# ld-version +# Note this is mainly for HJ Lu's 3 number binutil versions +ld-version = $(shell $(LD) --version | $(srctree)/scripts/ld-version.sh) + +# ld-ifversion +# Usage: $(call ld-ifversion, -ge, 22252, y) +ld-ifversion = $(shell [ $(ld-version) $(1) $(2) ] && echo $(3) || echo $(4)) + +###### + +### +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= +# Usage: +# $(Q)$(MAKE) $(build)=dir +build := -f $(srctree)/scripts/Makefile.build obj + +### +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.dtbinst obj= +# Usage: +# $(Q)$(MAKE) $(dtbinst)=dir +dtbinst := -f $(srctree)/scripts/Makefile.dtbinst obj + +### +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj= +# Usage: +# $(Q)$(MAKE) $(clean)=dir +clean := -f $(srctree)/scripts/Makefile.clean obj + +# echo command. +# Short version is used, if $(quiet) equals `quiet_', otherwise full one. +echo-cmd = $(if $($(quiet)cmd_$(1)),\ + echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';) + +# printing commands +cmd = @set -e; $(echo-cmd) $(cmd_$(1)) + +### +# if_changed - execute command if any prerequisite is newer than +# target, or command line has changed +# if_changed_dep - as if_changed, but uses fixdep to reveal dependencies +# including used config symbols +# if_changed_rule - as if_changed but execute rule instead +# See Documentation/kbuild/makefiles.rst for more info + +ifneq ($(KBUILD_NOCMDDEP),1) +# Check if both commands are the same including their order. Result is empty +# string if equal. User may override this check using make KBUILD_NOCMDDEP=1 +cmd-check = $(filter-out $(subst $(space),$(space_escape),$(strip $(cmd_$@))), \ + $(subst $(space),$(space_escape),$(strip $(cmd_$1)))) +else +cmd-check = $(if $(strip $(cmd_$@)),,1) +endif + +# Replace >$< with >$$< to preserve $ when reloading the .cmd file +# (needed for make) +# Replace >#< with >$(pound)< to avoid starting a comment in the .cmd file +# (needed for make) +# Replace >'< with >'\''< to be able to enclose the whole string in '...' +# (needed for the shell) +make-cmd = $(call escsq,$(subst $(pound),$$(pound),$(subst $$,$$$$,$(cmd_$(1))))) + +# Find any prerequisites that are newer than target or that do not exist. +# (This is not true for now; $? should contain any non-existent prerequisites, +# but it does not work as expected when .SECONDARY is present. This seems a bug +# of GNU Make.) +# PHONY targets skipped in both cases. +newer-prereqs = $(filter-out $(PHONY),$?) + +# Execute command if command has changed or prerequisite(s) are updated. +if_changed = $(if $(newer-prereqs)$(cmd-check), \ + $(cmd); \ + printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:) + +# Execute the command and also postprocess generated .d dependencies file. +if_changed_dep = $(if $(newer-prereqs)$(cmd-check),$(cmd_and_fixdep),@:) + +cmd_and_fixdep = \ + $(cmd); \ + scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).cmd;\ + rm -f $(depfile) + +# Usage: $(call if_changed_rule,foo) +# Will check if $(cmd_foo) or any of the prerequisites changed, +# and if so will execute $(rule_foo). +if_changed_rule = $(if $(newer-prereqs)$(cmd-check),$(rule_$(1)),@:) + +### +# why - tell why a target got built +# enabled by make V=2 +# Output (listed in the order they are checked): +# (1) - due to target is PHONY +# (2) - due to target missing +# (3) - due to: file1.h file2.h +# (4) - due to command line change +# (5) - due to missing .cmd file +# (6) - due to target not in $(targets) +# (1) PHONY targets are always build +# (2) No target, so we better build it +# (3) Prerequisite is newer than target +# (4) The command line stored in the file named dir/.target.cmd +# differed from actual command line. This happens when compiler +# options changes +# (5) No dir/.target.cmd file (used to store command line) +# (6) No dir/.target.cmd file and target not listed in $(targets) +# This is a good hint that there is a bug in the kbuild file +ifeq ($(KBUILD_VERBOSE),2) +why = \ + $(if $(filter $@, $(PHONY)),- due to target is PHONY, \ + $(if $(wildcard $@), \ + $(if $(newer-prereqs),- due to: $(newer-prereqs), \ + $(if $(cmd-check), \ + $(if $(cmd_$@),- due to command line change, \ + $(if $(filter $@, $(targets)), \ + - due to missing .cmd file, \ + - due to $(notdir $@) not in $$(targets) \ + ) \ + ) \ + ) \ + ), \ + - due to target missing \ + ) \ + ) + +echo-why = $(call escsq, $(strip $(why))) +endif + +############################################################################### +# +# When a Kconfig string contains a filename, it is suitable for +# passing to shell commands. It is surrounded by double-quotes, and +# any double-quotes or backslashes within it are escaped by +# backslashes. +# +# This is no use for dependencies or $(wildcard). We need to strip the +# surrounding quotes and the escaping from quotes and backslashes, and +# we *do* need to escape any spaces in the string. So, for example: +# +# Usage: $(eval $(call config_filename,FOO)) +# +# Defines FOO_FILENAME based on the contents of the CONFIG_FOO option, +# transformed as described above to be suitable for use within the +# makefile. +# +# Also, if the filename is a relative filename and exists in the source +# tree but not the build tree, define FOO_SRCPREFIX as $(srctree)/ to +# be prefixed to *both* command invocation and dependencies. +# +# Note: We also print the filenames in the quiet_cmd_foo text, and +# perhaps ought to have a version specially escaped for that purpose. +# But it's only cosmetic, and $(patsubst "%",%,$(CONFIG_FOO)) is good +# enough. It'll strip the quotes in the common case where there's no +# space and it's a simple filename, and it'll retain the quotes when +# there's a space. There are some esoteric cases in which it'll print +# the wrong thing, but we don't really care. The actual dependencies +# and commands *do* get it right, with various combinations of single +# and double quotes, backslashes and spaces in the filenames. +# +############################################################################### +# +define config_filename +ifneq ($$(CONFIG_$(1)),"") +$(1)_FILENAME := $$(subst \\,\,$$(subst \$$(quote),$$(quote),$$(subst $$(space_escape),\$$(space),$$(patsubst "%",%,$$(subst $$(space),$$(space_escape),$$(CONFIG_$(1))))))) +ifneq ($$(patsubst /%,%,$$(firstword $$($(1)_FILENAME))),$$(firstword $$($(1)_FILENAME))) +else +ifeq ($$(wildcard $$($(1)_FILENAME)),) +ifneq ($$(wildcard $$(srctree)/$$($(1)_FILENAME)),) +$(1)_SRCPREFIX := $(srctree)/ +endif +endif +endif +endif +endef +# +############################################################################### + +# delete partially updated (i.e. corrupted) files on error +.DELETE_ON_ERROR: + +# do not delete intermediate files automatically +.SECONDARY: diff --git a/scripts/Makefile.build b/scripts/Makefile.build new file mode 100644 index 000000000..4c058f12d --- /dev/null +++ b/scripts/Makefile.build @@ -0,0 +1,526 @@ +# SPDX-License-Identifier: GPL-2.0 +# ========================================================================== +# Building +# ========================================================================== + +src := $(obj) + +PHONY := __build +__build: + +# Init all relevant variables used in kbuild files so +# 1) they have correct type +# 2) they do not inherit any value from the environment +obj-y := +obj-m := +lib-y := +lib-m := +always := +always-y := +always-m := +targets := +subdir-y := +subdir-m := +EXTRA_AFLAGS := +EXTRA_CFLAGS := +EXTRA_CPPFLAGS := +EXTRA_LDFLAGS := +asflags-y := +ccflags-y := +cppflags-y := +ldflags-y := + +subdir-asflags-y := +subdir-ccflags-y := + +# Read auto.conf if it exists, otherwise ignore +-include include/config/auto.conf + +include scripts/Kbuild.include + +# The filename Kbuild has precedence over Makefile +kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) +kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) +include $(kbuild-file) + +include scripts/Makefile.lib + +# Do not include hostprogs rules unless needed. +# $(sort ...) is used here to remove duplicated words and excessive spaces. +hostprogs := $(sort $(hostprogs)) +ifneq ($(hostprogs),) +include scripts/Makefile.host +endif + +# Do not include userprogs rules unless needed. +# $(sort ...) is used here to remove duplicated words and excessive spaces. +userprogs := $(sort $(userprogs)) +ifneq ($(userprogs),) +include scripts/Makefile.userprogs +endif + +ifndef obj +$(warning kbuild: Makefile.build is included improperly) +endif + +ifeq ($(need-modorder),) +ifneq ($(obj-m),) +$(warning $(patsubst %.o,'%.ko',$(obj-m)) will not be built even though obj-m is specified.) +$(warning You cannot use subdir-y/m to visit a module Makefile. Use obj-y/m instead.) +endif +endif + +# =========================================================================== + +# subdir-builtin and subdir-modorder may contain duplications. Use $(sort ...) +subdir-builtin := $(sort $(filter %/built-in.a, $(real-obj-y))) +subdir-modorder := $(sort $(filter %/modules.order, $(obj-m))) + +targets-for-builtin := $(extra-y) + +ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),) +targets-for-builtin += $(obj)/lib.a +endif + +ifdef need-builtin +targets-for-builtin += $(obj)/built-in.a +endif + +targets-for-modules := $(patsubst %.o, %.mod, $(filter %.o, $(obj-m))) + +ifdef need-modorder +targets-for-modules += $(obj)/modules.order +endif + +targets += $(targets-for-builtin) $(targets-for-modules) + +# Linus' kernel sanity checking tool +ifeq ($(KBUILD_CHECKSRC),1) + quiet_cmd_checksrc = CHECK $< + cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< +else ifeq ($(KBUILD_CHECKSRC),2) + quiet_cmd_force_checksrc = CHECK $< + cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< +endif + +ifneq ($(KBUILD_EXTRA_WARN),) + cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $< +endif + +# Compile C sources (.c) +# --------------------------------------------------------------------------- + +quiet_cmd_cc_s_c = CC $(quiet_modtag) $@ + cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS), $(c_flags)) -fverbose-asm -S -o $@ $< + +$(obj)/%.s: $(src)/%.c FORCE + $(call if_changed_dep,cc_s_c) + +quiet_cmd_cpp_i_c = CPP $(quiet_modtag) $@ +cmd_cpp_i_c = $(CPP) $(c_flags) -o $@ $< + +$(obj)/%.i: $(src)/%.c FORCE + $(call if_changed_dep,cpp_i_c) + +# These mirror gensymtypes_S and co below, keep them in synch. +cmd_gensymtypes_c = \ + $(CPP) -D__GENKSYMS__ $(c_flags) $< | \ + scripts/genksyms/genksyms $(if $(1), -T $(2)) \ + $(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \ + $(if $(KBUILD_PRESERVE),-p) \ + -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null)) + +quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ +cmd_cc_symtypes_c = \ + $(call cmd_gensymtypes_c,true,$@) >/dev/null; \ + test -s $@ || rm -f $@ + +$(obj)/%.symtypes : $(src)/%.c FORCE + $(call cmd,cc_symtypes_c) + +# LLVM assembly +# Generate .ll files from .c +quiet_cmd_cc_ll_c = CC $(quiet_modtag) $@ + cmd_cc_ll_c = $(CC) $(c_flags) -emit-llvm -S -o $@ $< + +$(obj)/%.ll: $(src)/%.c FORCE + $(call if_changed_dep,cc_ll_c) + +# C (.c) files +# The C file is compiled and updated dependency information is generated. +# (See cmd_cc_o_c + relevant part of rule_cc_o_c) + +quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ + cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< + +ifdef CONFIG_MODVERSIONS +# When module versioning is enabled the following steps are executed: +# o compile a .o from .c +# o if .o doesn't contain a __ksymtab version, i.e. does +# not export symbols, it's done. +# o otherwise, we calculate symbol versions using the good old +# genksyms on the preprocessed source and postprocess them in a way +# that they are usable as a linker script +# o generate .tmp_.o from .o using the linker to +# replace the unresolved symbols __crc_exported_symbol with +# the actual value of the checksum generated by genksyms +# o remove .tmp_.o to .o + +cmd_modversions_c = \ + if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \ + $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ + > $(@D)/.tmp_$(@F:.o=.ver); \ + \ + $(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \ + -T $(@D)/.tmp_$(@F:.o=.ver); \ + mv -f $(@D)/.tmp_$(@F) $@; \ + rm -f $(@D)/.tmp_$(@F:.o=.ver); \ + fi +endif + +ifdef CONFIG_FTRACE_MCOUNT_RECORD +ifndef CC_USING_RECORD_MCOUNT +# compiler will not generate __mcount_loc use recordmcount or recordmcount.pl +ifdef BUILD_C_RECORDMCOUNT +ifeq ("$(origin RECORDMCOUNT_WARN)", "command line") + RECORDMCOUNT_FLAGS = -w +endif +# Due to recursion, we must skip empty.o. +# The empty.o file is created in the make process in order to determine +# the target endianness and word size. It is made before all other C +# files, including recordmcount. +sub_cmd_record_mcount = \ + if [ $(@) != "scripts/mod/empty.o" ]; then \ + $(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)"; \ + fi; +recordmcount_source := $(srctree)/scripts/recordmcount.c \ + $(srctree)/scripts/recordmcount.h +else +sub_cmd_record_mcount = perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \ + "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \ + "$(if $(CONFIG_64BIT),64,32)" \ + "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)" \ + "$(LD) $(KBUILD_LDFLAGS)" "$(NM)" "$(RM)" "$(MV)" \ + "$(if $(part-of-module),1,0)" "$(@)"; +recordmcount_source := $(srctree)/scripts/recordmcount.pl +endif # BUILD_C_RECORDMCOUNT +cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), \ + $(sub_cmd_record_mcount)) +endif # CC_USING_RECORD_MCOUNT +endif # CONFIG_FTRACE_MCOUNT_RECORD + +ifdef CONFIG_STACK_VALIDATION +ifneq ($(SKIP_STACK_VALIDATION),1) + +__objtool_obj := $(objtree)/tools/objtool/objtool + +objtool_args = $(if $(CONFIG_UNWINDER_ORC),orc generate,check) + +objtool_args += $(if $(part-of-module), --module,) + +ifndef CONFIG_FRAME_POINTER +objtool_args += --no-fp +endif +ifdef CONFIG_GCOV_KERNEL +objtool_args += --no-unreachable +endif +ifdef CONFIG_RETPOLINE + objtool_args += --retpoline +endif +ifdef CONFIG_X86_SMAP + objtool_args += --uaccess +endif + +# 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory +# 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file +# 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file +cmd_objtool = $(if $(patsubst y%,, \ + $(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \ + $(__objtool_obj) $(objtool_args) $@) +objtool_obj = $(if $(patsubst y%,, \ + $(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \ + $(__objtool_obj)) + +endif # SKIP_STACK_VALIDATION +endif # CONFIG_STACK_VALIDATION + +# Rebuild all objects when objtool changes, or is enabled/disabled. +objtool_dep = $(objtool_obj) \ + $(wildcard include/config/orc/unwinder.h \ + include/config/stack/validation.h) + +ifdef CONFIG_TRIM_UNUSED_KSYMS +cmd_gen_ksymdeps = \ + $(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd + +# List module undefined symbols +undefined_syms = $(NM) $< | $(AWK) '$$1 == "U" { printf("%s%s", x++ ? " " : "", $$2) }'; +endif + +define rule_cc_o_c + $(call cmd_and_fixdep,cc_o_c) + $(call cmd,gen_ksymdeps) + $(call cmd,checksrc) + $(call cmd,checkdoc) + $(call cmd,objtool) + $(call cmd,modversions_c) + $(call cmd,record_mcount) +endef + +define rule_as_o_S + $(call cmd_and_fixdep,as_o_S) + $(call cmd,gen_ksymdeps) + $(call cmd,objtool) + $(call cmd,modversions_S) +endef + +# Built-in and composite module parts +$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE + $(call if_changed_rule,cc_o_c) + $(call cmd,force_checksrc) + +cmd_mod = { \ + echo $(if $($*-objs)$($*-y)$($*-m), $(addprefix $(obj)/, $($*-objs) $($*-y) $($*-m)), $(@:.mod=.o)); \ + $(undefined_syms) echo; \ + } > $@ + +$(obj)/%.mod: $(obj)/%.o FORCE + $(call if_changed,mod) + +quiet_cmd_cc_lst_c = MKLST $@ + cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \ + $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \ + System.map $(OBJDUMP) > $@ + +$(obj)/%.lst: $(src)/%.c FORCE + $(call if_changed_dep,cc_lst_c) + +# Compile assembler sources (.S) +# --------------------------------------------------------------------------- + +# .S file exports must have their C prototypes defined in asm/asm-prototypes.h +# or a file that it includes, in order to get versioned symbols. We build a +# dummy C file that includes asm-prototypes and the EXPORT_SYMBOL lines from +# the .S file (with trailing ';'), and run genksyms on that, to extract vers. +# +# This is convoluted. The .S file must first be preprocessed to run guards and +# expand names, then the resulting exports must be constructed into plain +# EXPORT_SYMBOL(symbol); to build our dummy C file, and that gets preprocessed +# to make the genksyms input. +# +# These mirror gensymtypes_c and co above, keep them in synch. +cmd_gensymtypes_S = \ + { echo "\#include " ; \ + echo "\#include " ; \ + $(CPP) $(a_flags) $< | \ + grep "\<___EXPORT_SYMBOL\>" | \ + sed 's/.*___EXPORT_SYMBOL[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*,.*/EXPORT_SYMBOL(\1);/' ; } | \ + $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | \ + scripts/genksyms/genksyms $(if $(1), -T $(2)) \ + $(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \ + $(if $(KBUILD_PRESERVE),-p) \ + -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null)) + +quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@ +cmd_cc_symtypes_S = \ + $(call cmd_gensymtypes_S,true,$@) >/dev/null; \ + test -s $@ || rm -f $@ + +$(obj)/%.symtypes : $(src)/%.S FORCE + $(call cmd,cc_symtypes_S) + + +quiet_cmd_cpp_s_S = CPP $(quiet_modtag) $@ +cmd_cpp_s_S = $(CPP) $(a_flags) -o $@ $< + +$(obj)/%.s: $(src)/%.S FORCE + $(call if_changed_dep,cpp_s_S) + +quiet_cmd_as_o_S = AS $(quiet_modtag) $@ + cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< + +ifdef CONFIG_ASM_MODVERSIONS + +# versioning matches the C process described above, with difference that +# we parse asm-prototypes.h C header to get function definitions. + +cmd_modversions_S = \ + if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \ + $(call cmd_gensymtypes_S,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ + > $(@D)/.tmp_$(@F:.o=.ver); \ + \ + $(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \ + -T $(@D)/.tmp_$(@F:.o=.ver); \ + mv -f $(@D)/.tmp_$(@F) $@; \ + rm -f $(@D)/.tmp_$(@F:.o=.ver); \ + fi +endif + +$(obj)/%.o: $(src)/%.S $(objtool_dep) FORCE + $(call if_changed_rule,as_o_S) + +targets += $(filter-out $(subdir-builtin), $(real-obj-y)) +targets += $(filter-out $(subdir-modorder), $(real-obj-m)) +targets += $(lib-y) $(always-y) $(MAKECMDGOALS) + +# Linker scripts preprocessor (.lds.S -> .lds) +# --------------------------------------------------------------------------- +quiet_cmd_cpp_lds_S = LDS $@ + cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -U$(ARCH) \ + -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $< + +$(obj)/%.lds: $(src)/%.lds.S FORCE + $(call if_changed_dep,cpp_lds_S) + +# ASN.1 grammar +# --------------------------------------------------------------------------- +quiet_cmd_asn1_compiler = ASN.1 $(basename $@).[ch] + cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \ + $(basename $@).c $(basename $@).h + +$(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler + $(call cmd,asn1_compiler) + +# Build the compiled-in targets +# --------------------------------------------------------------------------- + +# To build objects in subdirs, we need to descend into the directories +$(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ; +$(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ; + +# +# Rule to compile a set of .o files into one .a file (without symbol table) +# + +quiet_cmd_ar_builtin = AR $@ + cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs) + +$(obj)/built-in.a: $(real-obj-y) FORCE + $(call if_changed,ar_builtin) + +# +# Rule to create modules.order file +# +# Create commands to either record .ko file or cat modules.order from +# a subdirectory +# Add $(obj-m) as the prerequisite to avoid updating the timestamp of +# modules.order unless contained modules are updated. + +cmd_modules_order = { $(foreach m, $(real-prereqs), \ + $(if $(filter %/modules.order, $m), cat $m, echo $(patsubst %.o,%.ko,$m));) :; } \ + | $(AWK) '!x[$$0]++' - > $@ + +$(obj)/modules.order: $(obj-m) FORCE + $(call if_changed,modules_order) + +# +# Rule to compile a set of .o files into one .a file (with symbol table) +# +$(obj)/lib.a: $(lib-y) FORCE + $(call if_changed,ar) + +# NOTE: +# Do not replace $(filter %.o,^) with $(real-prereqs). When a single object +# module is turned into a multi object module, $^ will contain header file +# dependencies recorded in the .*.cmd file. +quiet_cmd_link_multi-m = LD [M] $@ + cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(filter %.o,$^) + +$(multi-used-m): FORCE + $(call if_changed,link_multi-m) +$(call multi_depend, $(multi-used-m), .o, -objs -y -m) + +targets += $(multi-used-m) +targets := $(filter-out $(PHONY), $(targets)) + +# Add intermediate targets: +# When building objects with specific suffix patterns, add intermediate +# targets that the final targets are derived from. +intermediate_targets = $(foreach sfx, $(2), \ + $(patsubst %$(strip $(1)),%$(sfx), \ + $(filter %$(strip $(1)), $(targets)))) +# %.asn1.o <- %.asn1.[ch] <- %.asn1 +# %.dtb.o <- %.dtb.S <- %.dtb <- %.dts +# %.lex.o <- %.lex.c <- %.l +# %.tab.o <- %.tab.[ch] <- %.y +targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \ + $(call intermediate_targets, .dtb.o, .dtb.S .dtb) \ + $(call intermediate_targets, .lex.o, .lex.c) \ + $(call intermediate_targets, .tab.o, .tab.c .tab.h) + +# Build +# --------------------------------------------------------------------------- + +ifdef single-build + +KBUILD_SINGLE_TARGETS := $(filter $(obj)/%, $(KBUILD_SINGLE_TARGETS)) + +curdir-single := $(sort $(foreach x, $(KBUILD_SINGLE_TARGETS), \ + $(if $(filter $(x) $(basename $(x)).o, $(targets)), $(x)))) + +# Handle single targets without any rule: show "Nothing to be done for ..." or +# "No rule to make target ..." depending on whether the target exists. +unknown-single := $(filter-out $(addsuffix /%, $(subdir-ym)), \ + $(filter-out $(curdir-single), $(KBUILD_SINGLE_TARGETS))) + +single-subdirs := $(foreach d, $(subdir-ym), \ + $(if $(filter $(d)/%, $(KBUILD_SINGLE_TARGETS)), $(d))) + +__build: $(curdir-single) $(single-subdirs) +ifneq ($(unknown-single),) + $(Q)$(MAKE) -f /dev/null $(unknown-single) +endif + @: + +ifeq ($(curdir-single),) +# Nothing to do in this directory. Do not include any .*.cmd file for speed-up +targets := +else +targets += $(curdir-single) +endif + +else + +__build: $(if $(KBUILD_BUILTIN), $(targets-for-builtin)) \ + $(if $(KBUILD_MODULES), $(targets-for-modules)) \ + $(subdir-ym) $(always-y) + @: + +endif + +# Descending +# --------------------------------------------------------------------------- + +PHONY += $(subdir-ym) +$(subdir-ym): + $(Q)$(MAKE) $(build)=$@ \ + $(if $(filter $@/, $(KBUILD_SINGLE_TARGETS)),single-build=) \ + need-builtin=$(if $(filter $@/built-in.a, $(subdir-builtin)),1) \ + need-modorder=$(if $(filter $@/modules.order, $(subdir-modorder)),1) + +# Add FORCE to the prequisites of a target to force it to be always rebuilt. +# --------------------------------------------------------------------------- + +PHONY += FORCE + +FORCE: + +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. + +existing-targets := $(wildcard $(sort $(targets))) + +-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd) + +# Create directories for object files if they do not exist +obj-dirs := $(sort $(patsubst %/,%, $(dir $(targets)))) +# If targets exist, their directories apparently exist. Skip mkdir. +existing-dirs := $(sort $(patsubst %/,%, $(dir $(existing-targets)))) +obj-dirs := $(strip $(filter-out $(existing-dirs), $(obj-dirs))) +ifneq ($(obj-dirs),) +$(shell mkdir -p $(obj-dirs)) +endif + +.PHONY: $(PHONY) diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean new file mode 100644 index 000000000..d9e0ceace --- /dev/null +++ b/scripts/Makefile.clean @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: GPL-2.0 +# ========================================================================== +# Cleaning up +# ========================================================================== + +src := $(obj) + +PHONY := __clean +__clean: + +include scripts/Kbuild.include + +# The filename Kbuild has precedence over Makefile +kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) +include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) + +# Figure out what we need to build from the various variables +# ========================================================================== + +subdir-ymn := $(sort $(subdir-y) $(subdir-m) $(subdir-) \ + $(patsubst %/,%, $(filter %/, $(obj-y) $(obj-m) $(obj-)))) + +# Add subdir path + +subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn)) + +# build a list of files to remove, usually relative to the current +# directory + +__clean-files := \ + $(clean-files) $(targets) $(hostprogs) $(userprogs) \ + $(extra-y) $(extra-m) $(extra-) \ + $(always-y) $(always-m) $(always-) \ + $(hostprogs-always-y) $(hostprogs-always-m) $(hostprogs-always-) \ + $(userprogs-always-y) $(userprogs-always-m) $(userprogs-always-) + +# deprecated +__clean-files += $(always) $(hostprogs-y) $(hostprogs-m) $(hostprogs-) + +__clean-files := $(filter-out $(no-clean-files), $(__clean-files)) + +# clean-files is given relative to the current directory, unless it +# starts with $(objtree)/ (which means "./", so do not add "./" unless +# you want to delete a file from the toplevel object directory). + +__clean-files := $(wildcard \ + $(addprefix $(obj)/, $(filter-out $(objtree)/%, $(__clean-files))) \ + $(filter $(objtree)/%, $(__clean-files))) + +# ========================================================================== + +quiet_cmd_clean = CLEAN $(obj) + cmd_clean = rm -rf $(__clean-files) + +__clean: $(subdir-ymn) +ifneq ($(strip $(__clean-files)),) + $(call cmd,clean) +endif + @: + + +# =========================================================================== +# Generic stuff +# =========================================================================== + +# Descending +# --------------------------------------------------------------------------- + +PHONY += $(subdir-ymn) +$(subdir-ymn): + $(Q)$(MAKE) $(clean)=$@ + +.PHONY: $(PHONY)