Make 变量通常是全局变量,您通常不会在配方中设置 make 变量。配方只是要由 shell 执行的命令列表,因此在配方中看起来像变量赋值的是 shell 变量赋值。
但是,make 配方中的每一行都在其自己的 shell 子进程中运行。因此,在一行中设置的变量在另一行中将不可见;他们并不执着。这使得在配方中设置 shell 变量不太有用。 [注1]
但是您可以使用行尾的反斜杠转义符将配方的多行组合成单个 shell 命令,并记住用分号终止各个命令(或者,最好将它们与 && 链接),因为反斜杠转义的换行符不会传递给 shell。另外,不要忘记转义 $ 字符,以便将它们传递给 shell,而不是被 make 解释。
因此您可以执行以下操作:
radio:
@BASE_MOD_TIME="$$( expr $$(date +%s) - $$(date +%s -r src/radio_interface/profile_init.c) )"; \
echo "$$BASE_MOD_TIME"; \
# More commands in the same subprocess
但是,如果有多个命令,那会变得很尴尬,更好的解决方案通常是编写一个 shell 脚本并从配方中调用它(尽管这意味着 Makefile 不再是独立的。)
Gnu make 提供了两种方法来设置配方中的 make 变量:
1。目标特定变量。
您可以通过添加如下行来创建特定于目标的变量(不完全是目标的本地变量):
target: var := value
要从 shell 命令设置变量,请使用 shell 函数:
target: var := $(shell ....)
此变量将在目标配方中可用以及由目标触发的所有依赖项。请注意,依赖项只评估一次,因此如果它可以由不同的目标触发,则特定于目标的变量可能在依赖项中可用,也可能不可用,具体取决于 make 解析依赖项的顺序。
2。使用eval函数
由于配方的扩展总是被延迟,您可以在配方中使用eval 函数来延迟make 变量的分配。 eval 函数可以很好地放置在配方中的任何位置,因为它的值是空字符串。但是,evaling 变量赋值使变量赋值成为全局的;它将在整个 makefile 中可见,但它在其他配方中的值将再次取决于 make 评估配方的顺序,这不一定是可预测的。
例如:
radio:
$(eval var = $(shell ...))
注意事项:
- 您可以使用
.ONESHELL: 伪目标更改此行为,但这将应用于整个 Makefile;无法将单个配方标记为在单个子进程中执行。由于更改行为可能会以意想不到的方式破坏配方,因此我通常不推荐此功能。