如何阻止 make -n 多次回显相同的命令
how to stop make -n from echoing same command multiple times
我正在使用 GNU make 并有一个 Makefile
看起来像这样:
AB = A.txt B.txt
${AB}: makeAB.py
python makeAB.py
C.txt: ${AB} makeC.py
python makeC.py
当我键入 make -n C.txt
时,假设 makeAB.py
需要 运行,我得到输出:
python makeAB.py
python makeAB.py
python makeC.py
有没有什么办法可以写Makefile
使得python makeAB.py
行不重复?这只是一个玩具示例,但在我的实际应用程序中 AB
包含许多文件,因此我可能会得到一整屏不必要的输出。
p.s。在没有 -n
的情况下调用时,make
(明智地)仅 运行s python makeAB.py
一次。所以我的问题只是 make -n
.
双重输出的出现是因为配方被安排为 运行 两次,一次用于构建 A.txt
,另一次用于构建 B.txt
。这是 make
的正常行为。特别是一条规则,例如您的(扩展后的)...
A.txt B.txt: makeAB.py
python makeAB.py
... 意味着这两个目标中的 each 可以通过关联的配方构建,而不是单次执行配方构建两者(无论单个 运行 确实构建了两者)。它 100% 等同于:
A.txt: makeAB.py
python makeAB.py
B.txt: makeAB.py
python makeAB.py
When called without -n
, make
(sensibly) only runs python makeAB.py
once. So my problem is just with make -n
.
当你运行和-n
时,make
不执行配方,所以它无法评估这样做是否更新(比如)A.txt
也可能更新B.txt
。它所知道的是两个目标都已过时,因此它输出将执行以更新每个目标的配方。这完全是明智的。
当你 运行 make
没有 -n
时,它有机会观察到更新 A.txt
和 B.txt
之一后,另一个已是最新。它甚至可能很自然地没有注意到对方最初已经过时了。观察到这一点后,它当然不会再次执行配方。如果配方执行表示正在构建哪个目标,输出将更清楚地说明发生了什么。例如,试试这个规则的变体,它更像是 multiple-target 规则通常的写法。
A.txt B.txt: makeAB.py
python makeAB.py $@
因此,两个 make
输出都以自己的方式正确。然而,可以说,makefile 是错误的,因为它没有捕捉到 运行 将配方一次生成两个输出的期望和事实。这是 makefile 语言传统上难以表达的情况,您会在 SO 和其他地方找到与此相关的其他问题。
如果您使用的是足够新的 GNU Make 版本,那么您可以利用它的 "grouped target" rules 概念,它正好解决了这个问题。通过在规则的第一行使用 &:
作为分隔符,您可以传达(仅针对最新版本的 GNU Make)规则的一次执行会创建所有指定的目标。示例:
A.txt B.txt &: makeAB.py
python makeAB.py
传统的 make
s 和旧的 GNU Make 只会将 &
解释为另一个目标名称。这意味着那些 make
s 将接受这样的 makefile,但行为与最近的 GNU make 不同。除此之外,这意味着如果要求构建目标 &
,他们会尝试这样做,由于 &
对 shell 的特殊意义,很可能会产生令人惊讶的效果。
我正在使用 GNU make 并有一个 Makefile
看起来像这样:
AB = A.txt B.txt
${AB}: makeAB.py
python makeAB.py
C.txt: ${AB} makeC.py
python makeC.py
当我键入 make -n C.txt
时,假设 makeAB.py
需要 运行,我得到输出:
python makeAB.py
python makeAB.py
python makeC.py
有没有什么办法可以写Makefile
使得python makeAB.py
行不重复?这只是一个玩具示例,但在我的实际应用程序中 AB
包含许多文件,因此我可能会得到一整屏不必要的输出。
p.s。在没有 -n
的情况下调用时,make
(明智地)仅 运行s python makeAB.py
一次。所以我的问题只是 make -n
.
双重输出的出现是因为配方被安排为 运行 两次,一次用于构建 A.txt
,另一次用于构建 B.txt
。这是 make
的正常行为。特别是一条规则,例如您的(扩展后的)...
A.txt B.txt: makeAB.py
python makeAB.py
... 意味着这两个目标中的 each 可以通过关联的配方构建,而不是单次执行配方构建两者(无论单个 运行 确实构建了两者)。它 100% 等同于:
A.txt: makeAB.py
python makeAB.py
B.txt: makeAB.py
python makeAB.py
When called without
-n
,make
(sensibly) only runspython makeAB.py
once. So my problem is just withmake -n
.
当你运行和-n
时,make
不执行配方,所以它无法评估这样做是否更新(比如)A.txt
也可能更新B.txt
。它所知道的是两个目标都已过时,因此它输出将执行以更新每个目标的配方。这完全是明智的。
当你 运行 make
没有 -n
时,它有机会观察到更新 A.txt
和 B.txt
之一后,另一个已是最新。它甚至可能很自然地没有注意到对方最初已经过时了。观察到这一点后,它当然不会再次执行配方。如果配方执行表示正在构建哪个目标,输出将更清楚地说明发生了什么。例如,试试这个规则的变体,它更像是 multiple-target 规则通常的写法。
A.txt B.txt: makeAB.py
python makeAB.py $@
因此,两个 make
输出都以自己的方式正确。然而,可以说,makefile 是错误的,因为它没有捕捉到 运行 将配方一次生成两个输出的期望和事实。这是 makefile 语言传统上难以表达的情况,您会在 SO 和其他地方找到与此相关的其他问题。
如果您使用的是足够新的 GNU Make 版本,那么您可以利用它的 "grouped target" rules 概念,它正好解决了这个问题。通过在规则的第一行使用 &:
作为分隔符,您可以传达(仅针对最新版本的 GNU Make)规则的一次执行会创建所有指定的目标。示例:
A.txt B.txt &: makeAB.py
python makeAB.py
传统的 make
s 和旧的 GNU Make 只会将 &
解释为另一个目标名称。这意味着那些 make
s 将接受这样的 makefile,但行为与最近的 GNU make 不同。除此之外,这意味着如果要求构建目标 &
,他们会尝试这样做,由于 &
对 shell 的特殊意义,很可能会产生令人惊讶的效果。