# SPDX-License-Identifier: GPL-2.0 #### # kbuild: Generic definitions # Convenient variables 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 = $(@D)/.$(@F) ### # dependencies depfile = $(dot-target).d ### # real prerequisites without phony targets real-prereqs = $(filter-out $(PHONY), $^) ### # Escape single quote for use in echo statements escsq = $(subst $(squote),'\$(squote)',$1) ### # 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 # as-insn: Check whether assembler supports an instruction. # Usage: cflags-y += $(call as-insn,CC FLAGS,"insn",option-yes,option-no) as-insn = $(if $(shell echo 'void _(void) { asm volatile ( $(2) ); }' \ | $(filter-out -M% %.d -include %/include/xen/config.h,$(1)) \ -c -x c -o /dev/null - 2>&1),$(4),$(3)) # as-option-add: Conditionally add options to flags # Usage: $(call as-option-add,CFLAGS,CC,"insn",option-yes,option-no) as-option-add = $(eval $(call as-option-add-closure,$(1),$(2),$(3),$(4),$(5))) define as-option-add-closure ifeq ($$(call as-insn,$$($(2)) $$($(1)),$$(3),y,n),y) $(1) += $(4) else $(1) += $(5) endif endef # $(call if-success,,,) # Return if exits with 0, otherwise. if-success = $(shell { $(1); } >/dev/null 2>&1 && echo "$(2)" || echo "$(3)") # $(call success,) # Return y if exits with 0, n otherwise success = $(call if-success,$(1),y,n) # $(call ld-option,) # Return y if the linker supports , n otherwise ld-option = $(call success,$(LD) -v $(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)) clang-ifversion = $(shell [ $(CONFIG_CLANG_VERSION)0 $(1) $(2)000 ] && echo $(3) || echo $(4)) ### # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= # Usage: # $(Q)$(MAKE) $(build)=dir build := -f $(srctree)/Rules.mk obj # Shorthand for $(MAKE) clean # 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 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 is newer than target or that does not exist. # PHONY targets skipped in both cases. any-prereq = $(filter-out $(PHONY),$?)$(filter-out $(PHONY) $(wildcard $^),$^) # Execute command if command has changed or prerequisite(s) are updated. if_changed = $(if $(any-prereq)$(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 $(any-prereq)$(cmd-check),$(cmd_and_fixdep),@:) cmd_and_fixdep = \ $(cmd); \ tools/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 $(any-prereq)$(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 $(any-prereq),- due to: $(any-prereq), \ $(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 # Useful for describing the dependency of composite objects # Usage: # $(call multi-depend, multi-used-targets, suffix-to-remove, suffix-to-add) define multi-depend $(foreach m, $(notdir $1), \ $(eval $(obj)/$(m): \ $(addprefix $(obj)/, $(foreach s, $3, $($(m:%$(strip $2)=%$(s))))))) endef