-include .check.cmd comma := , quote := " squote := ' empty := space := $(empty) $(empty) space_escape := _-_SPACE_-_ pound := \# quiet_cmd_a = A cmd_a = echo "doing a" quiet_cmd_b = B cmd_b = echo "doing b" ### # Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o dot-target = $(dir $@).$(notdir $@) ### # Escape single quote for use in echo statements escsq = $(subst $(squote),'\$(squote)',$1) ifneq ($(KBUILD_NOCMDDEP),1) # Check if both arguments are the same including their order. Result is empty # string if equal. User may override this check using make KBUILD_NOCMDDEP=1 arg-check = $(filter-out $(subst $(space),$(space_escape),$(strip $(cmd_$@))), \ $(subst $(space),$(space_escape),$(strip $(cmd_$1)))) else arg-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 $^),$^) quiet = quiet_ # 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)';) cmd = @$(echo-cmd) $(cmd_$(1)) # Execute command if command has changed or prerequisite(s) are updated. if_changed = $(if $(filter-out undefined,$(origin if_changed_cnt)), \ @set -e; \ echo "Warning: $@: multiple use of if_changed!" >&2; , \ @set -e $(eval $@: if_changed_cnt := 1) ; ) \ $(if $(strip $(any-prereq) $(arg-check)), \ $(echo-cmd) $(cmd_$(1)); \ printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, :) PHONY += FORCE FORCE: a.o: Makefile @printf 'if_change_cnt: -%s-\n' '$(origin if_change_cnt)' @touch a.o check: a.o FORCE $(call if_changed,a) $(call if_changed,b) @touch check