在规则执行时定义 make 变量
在我的 GNUmakefile 中,我希望有一个使用临时目录的规则。例如:
out.tar: TMP := $(shell mktemp -d)
echo hi $(TMP)/hi.txt
tar -C $(TMP) cf $@ .
rm -rf $(TMP)
如所写,上述规则在规则被解析时创建临时目录。这意味着,即使我不总是创建 out.tar,也会创建许多临时目录。我想避免我的 /tmp 到处都是未使用的临时目录。
有没有办法使变量仅在规则触发时定义,而不是在定义时定义?
我的主要想法是将 mktemp 和 tar 转储到 shell 脚本中,但这看起来有点难看。
In my GNUmakefile, I would like to have a rule that uses a temporary directory. For example:
out.tar: TMP := $(shell mktemp -d)
echo hi $(TMP)/hi.txt
tar -C $(TMP) cf $@ .
rm -rf $(TMP)
As written, the above rule creates the temporary directory at the time that the rule is parsed. This means that, even I don't make out.tar all the time, many temporary directories get created. I would like to avoid my /tmp being littered with unused temporary directories.
Is there a way to cause the variable to only be defined when the rule is fired, as opposed to whenever it is defined?
My main thought is to dump the mktemp and tar into a shell script but that seems somewhat unsightly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在您的示例中,每当评估
out.tar
的规则时,都会设置TMP
变量(并创建临时目录)。为了仅在实际触发out.tar
时创建目录,您需要将目录创建移至以下步骤:eval 函数计算字符串,就好像它是手动输入到 makefile 中一样。在本例中,它将
TMP
变量设置为shell
函数调用的结果。编辑(响应评论):
要创建一个唯一的变量,您可以执行以下操作:
这会将目标名称(在本例中为 out.tar)添加到变量中,生成一个名为
out.tar_TMP
的变量。希望这足以防止冲突。In your example, the
TMP
variable is set (and the temporary directory created) whenever the rules forout.tar
are evaluated. In order to create the directory only whenout.tar
is actually fired, you need to move the directory creation down into the steps:The eval function evaluates a string as if it had been typed into the makefile manually. In this case, it sets the
TMP
variable to the result of theshell
function call.edit (in response to comments):
To create a unique variable, you could do the following:
This would prepend the name of the target (out.tar, in this case) to the variable, producing a variable with the name
out.tar_TMP
. Hopefully, that is enough to prevent conflicts.一种相对简单的方法是将整个序列编写为 shell 脚本。
我在这里整合了一些相关提示:Makefile 中的多行 bash 命令
A relatively easy way of doing this is to write the entire sequence as a shell script.
I have consolidated some related tips here: Multi-line bash commands in makefile
另一种可能性是在规则触发时使用单独的行来设置 Make 变量。
例如,这是一个包含两条规则的 makefile。如果规则触发,它会创建一个临时目录并将 TMP 设置为临时目录名称。
运行代码会产生预期的结果:
Another possibility is to use separate lines to set up Make variables when a rule fires.
For example, here is a makefile with two rules. If a rule fires, it creates a temp dir and sets TMP to the temp dir name.
Running the code produces the expected result:
我不喜欢“不”的答案,但是……不。
make
的变量是全局的,应该在 makefile 的“解析”阶段而不是执行阶段进行评估。在这种情况下,只要该变量是单个目标的本地变量,请按照 @nobar 的答案 并将其设为 shell 变量。
其他 make 实现也认为特定于目标的变量是有害的: kati、Mozilla pymake。因此,目标可以以不同的方式构建,具体取决于它是独立构建还是作为具有特定于目标的变量的父目标的依赖项。 而且你不会知道它是哪条路,因为你不知道已经构建了什么。
I dislike "Don't" answers, but... don't.
make
's variables are global and are supposed to be evaluated during makefile's "parsing" stage, not during execution stage.In this case, as long as the variable local to a single target, follow @nobar's answer and make it a shell variable.
Target-specific variables, too, are considered harmful by other make implementations: kati, Mozilla pymake. Because of them, a target can be built differently depending on if it's built standalone, or as a dependency of a parent target with a target-specific variable. And you won't know which way it was, because you don't know what is already built.