我知道你可以传递参数,例如make foo=bar
。我想知道我是否可以只用一个参数来做到这一点,而不用变量。例如,这就是我想要做的:
hello:
echo "Hello, $1!"
在 Bash 中,$1 是通过函数传递的第一个参数。如果我运行make hello 'world'
,那么它应该输出Hello, world!
。这可能吗?
答案1
我完全同意 DWD 和 Thomas 的观点。但是,如果出于某种原因,您被迫使用make
和 a Makefile
,请记住,make
将把所有既不是定义也不是执行标志的参数视为目标。它将尝试按顺序一次更新所有参数。所以:
make hello VAR=value how are -d you --debug=n
将把-d
和--debug=n
视为执行标志(或选项)和VAR=value
变量 的定义VAR
。所有其他参数将被视为目标。
如果您使用的是 GNU make
,则可以从某些特殊变量中受益,例如MAKECMDGOALS
包含要更新的目标的完整列表。借助firstword
、wordlist
和等函数words
,我们可以将第一个目标与其余目标隔离开来:
# Takes the first target as command
Command := $(firstword $(MAKECMDGOALS))
# Skips the first word
Arguments := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
规则hello
非常简单:
hello:
@echo "Hello, "$(Arguments)"!";
如果您运行make hello 'world'
,您将获得所期望的结果,但 make 还将尝试将其world
作为目标进行构建,并且对于您在 hello 之后传递的任何其他字符串也是如此。
解决方案将随最后一个资源规则一起提供:%::
。当没有其他规则可以应用时,将对其进行评估。为了保持安静(无输出,无错误),配方可以是@true
:
%::
@true
总而言之,最终结果Makefile
如下:
Command := $(firstword $(MAKECMDGOALS))
Arguments := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
hello:
@echo "Hello, "$(Arguments)"!";
%::
@true
这有很多限制。第一个限制是,如果你将指令集扩展到简单的 之外hello
,那么除了被 回显之外,这些新目标还会被评估hello
。另一个限制与无效命令处理有关。你必须使用函数filter
来确定目标是行中的第一个(实际命令)还是命令的参数。