我的makefile中有以下内容。它是GNUmakefile
,因此支持其他制作功能:
# Undefined Behavior Sanitzier (Clang and G++)
ifeq ($(findstring ubsan,$(MAKECMDGOALS)),ubsan)
CXXFLAGS += -fsanitize=undefined
MAKECMDGOALS := $(subst ubsan,,$(MAKECMDGOALS))
endif # UBsan
运行它会导致:
make ubsan
make: *** No rule to make target 'ubsan'. Stop.
我知道正在执行代码路径(通过在块中引入错误)。如何从命令目标中删除目标?
答案 0 :(得分:5)
据我所知,你不能在这里做你想做的事。
您可以修改变量值,如果您自己检查值,则会看到更改,但修改MAKECMDGOALS
的值不会以任何方式影响make。
如果你看一下GNU Make Manual中的Appendix A Quick Reference,你会看到它说:
MAKECMDGOALS
在命令行上指定的目标。设置此变量对make的操作没有影响。
我认为,你最接近你想要做的就是手动重新执行Makefile
(或其他)的make。
有人说这种事情可能更好地作为变量而不是目标。
$ cat Makefile
$(info $(origin UBSAN))
$ make
undefined
$ make UBSAN=
command line
就像这样。
# Undefined Behavior Sanitzier (Clang and G++)
ifneq (undefined,$(origin UBSAN))
CXXFLAGS += -fsanitize=undefined
endif # UBsan
答案 1 :(得分:1)
我使用以下模式传递参数,它有其局限性(只有[a-z,0-9]字符),但可以变得非常方便:
ifeq (console,$(firstword $(MAKECMDGOALS)))
CONSOLE_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS))
$(eval $(CONSOLE_ARGS):;@:)
endif
console::
run-some-command $(CONSOLE_ARGS)
对于您的情况,以下工作:
# Undefined Behavior Sanitzier (Clang and G++)
ifeq (ubsan,$(firstword $(MAKECMDGOALS)))
CXXFLAGS += -fsanitize=undefined
$(eval $(CONSOLE_ARGS):;@:)
endif # UBsan
答案 2 :(得分:1)
是的,可以。根据我最近对另一个问题Force Makefile to execute script after building any target (just before exiting)的回答,很容易做到自己想要的事情。
这只是一个缺点,您将丢失直接传递为make all --silent
的所有命令行参数。但是,您可以调查以下问题:How to detect if the makefile `--silent/--quiet` command line option was set?,然后重新捕获要传递给make -f ${MAKEFILE_JUSTNAME} ${MAKECMDGOALS}
上的第二个make call命令的命令行参数。
ECHOCMD:=/bin/echo -e
SHELL := /bin/bash
ifeq (${IS_MAKEFILE_RUNNING_TARGETS},)
MAKEFILE_JUSTNAME := $(firstword ${MAKEFILE_LIST})
# UBsan
ifeq ($(findstring ubsan,${MAKECMDGOALS}),ubsan)
MAKECMDGOALS := $(subst ubsan,,${MAKECMDGOALS})
USELESS := $(eval export IS_UBSAN_CXXFLAGS_SET=1)
endif
define DEFAULTTARGET :=
printf 'Calling "%s" "%s"\n\n' "${MAKEFILE_JUSTNAME}" "${MAKECMDGOALS}"
make -f ${MAKEFILE_JUSTNAME} ${MAKECMDGOALS}
printf '\n'
printf 'Running something after all rules finished\n'
endef
%:
@:
# printf 'IS_MAKEFILE_RUNNING_TARGETS="%s"\n' "${IS_MAKEFILE_RUNNING_TARGETS}"
$(if ${IS_MAKEFILE_RUNNING_TARGETS},,${DEFAULTTARGET})
$(eval export IS_MAKEFILE_RUNNING_TARGETS=1)
all:
@:
# printf 'IS_MAKEFILE_RUNNING_TARGETS="%s"\n' "${IS_MAKEFILE_RUNNING_TARGETS}"
$(if ${IS_MAKEFILE_RUNNING_TARGETS},,${DEFAULTTARGET})
$(eval export IS_MAKEFILE_RUNNING_TARGETS=1)
else
# UBsan
ifneq (${IS_UBSAN_CXXFLAGS_SET},)
CXXFLAGS += -fsanitize=undefined
endif
all:
printf 'Calling my all rule, CXXFLAGS="%s"\n' "${CXXFLAGS}"
foo:
printf 'Calling my foo rule, CXXFLAGS="%s"\n' "${CXXFLAGS}"
bar:
printf 'Calling my bar rule, CXXFLAGS="%s"\n' "${CXXFLAGS}"
xyzzy:
printf 'Calling my xyzzy rule, CXXFLAGS="%s"\n' "${CXXFLAGS}"
endif
用法示例:
make
printf 'Calling "%s" "%s"\n\n' "Makefile" ""
Calling "Makefile" ""
make -f Makefile
make[1]: Entering directory '/cygdrive/d/User/Downloads'
printf 'Calling my all rule, CXXFLAGS="%s"\n' ""
Calling my all rule, CXXFLAGS=""
make[1]: Leaving directory '/cygdrive/d/User/Downloads'
printf '\n'
printf 'Running something after all rules finished\n'
Running something after all rules finished
make foo bar
printf 'Calling "%s" "%s"\n\n' "Makefile" "foo bar"
Calling "Makefile" "foo bar"
make -f Makefile foo bar
make[1]: Entering directory '/cygdrive/d/User/Downloads'
printf 'Calling my foo rule, CXXFLAGS="%s"\n' ""
Calling my foo rule, CXXFLAGS=""
printf 'Calling my bar rule, CXXFLAGS="%s"\n' ""
Calling my bar rule, CXXFLAGS=""
make[1]: Leaving directory '/cygdrive/d/User/Downloads'
printf '\n'
printf 'Running something after all rules finished\n'
Running something after all rules finished
make foo bar ubsan
printf 'Calling "%s" "%s"\n\n' "Makefile" "foo bar "
Calling "Makefile" "foo bar "
make -f Makefile foo bar
make[1]: Entering directory '/cygdrive/d/User/Downloads'
printf 'Calling my foo rule, CXXFLAGS="%s"\n' "-fsanitize=undefined"
Calling my foo rule, CXXFLAGS="-fsanitize=undefined"
printf 'Calling my bar rule, CXXFLAGS="%s"\n' "-fsanitize=undefined"
Calling my bar rule, CXXFLAGS="-fsanitize=undefined"
make[1]: Leaving directory '/cygdrive/d/User/Downloads'
printf '\n'
printf 'Running something after all rules finished\n'
Running something after all rules finished