在 a 中makefile,我试图检查 fileA 的修改时间是否比 fileB 更新的时间长。使用之前的一些帖子(this和this)作为参考,我想出了这个来尝试将自上次文件修改以来的时间存储为变量:
(我宁愿这是在make配方之外的函数中,但一次一个。)
.PHONY: all clean
all : (stuff happens here)
radio :
BASE_MOD_TIME="$( expr $(date +%s) - $(date +%s -r src/radio_interface/profile_init.c) )"
@echo "$(BASE_MOD_TIME)"
Run Code Online (Sandbox Code Playgroud)
我以为我会将expr命令的输出分配给一个变量BASE_MOD_TIME,但输出是:
bash-4.1$
BASE_MOD_TIME=""
echo ""
Run Code Online (Sandbox Code Playgroud)
我在这里做错了什么?保存输出的简单尝试ls -l也没有像这样工作。
Make 变量通常是全局的,您通常不会在配方中设置 make 变量。配方只是要由外壳程序执行的命令列表,因此配方中的变量赋值看起来是外壳变量赋值。
但是,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
Run Code Online (Sandbox Code Playgroud)
但是如果有多个命令,这会变得很尴尬,更好的解决方案通常是编写一个 shell 脚本并从配方中调用它(尽管这意味着 Makefile 不再是自包含的。)
Gnu make 提供了两种方法来设置配方中的 make 变量:
您可以通过添加如下一行来创建一个特定于目标的变量(它不完全是目标本地的):
target: var := value
Run Code Online (Sandbox Code Playgroud)
要从 shell 命令设置变量,请使用以下shell函数:
target: var := $(shell ....)
Run Code Online (Sandbox Code Playgroud)
此变量将在目标配方和由目标触发的所有依赖项中可用。请注意,依赖项仅评估一次,因此如果它可以由不同的目标触发,则特定于目标的变量可能会或可能不会在依赖项中可用,具体取决于make解析依赖项的顺序。
eval功能由于配方的扩展总是延迟的,您可以使用eval配方中的函数来延迟 make 变量的分配。该eval函数可以很好地放置在配方中的任何位置,因为它的值是空字符串。但是,eval对变量赋值会使变量赋值成为全局的;它在整个 makefile 中都是可见的,但它在其他配方中的价值将再次取决于 make 评估配方的顺序,这不一定是可预测的。
例如:
radio:
$(eval var = $(shell ...))
Run Code Online (Sandbox Code Playgroud)
.ONESHELL:伪目标更改此行为,但这将适用于整个 Makefile;无法将单个配方标记为在单个子流程中执行。由于更改行为可能会以意想不到的方式破坏配方,因此我通常不推荐此功能。| 归档时间: |
|
| 查看次数: |
15381 次 |
| 最近记录: |