在Makefiles中编写可重用代码的最佳实践是什么?
假设我有一个Makefile:
.PHONY: all task01-all task01-clean task01-run task02-all task02-clean task02-run
all: task01-all task02-all
###############################################################################
task01-all: task01-clean task01 task01-run
task01-clean:
rm task01 task01.{exi,o} -f
task01:
compiler task01.ext -O2 --make
task01-run:
./task01
###############################################################################
task02-all: task02-clean task02 task02-run
task02-clean:
rm task02 task02.{exi,o} -f
task02:
compiler task02.ext -O2 --make
task02-run:
./task02
Run Code Online (Sandbox Code Playgroud)
现在,我想补充的任务(task03)新的家庭,我需要copypaste整段,使得s/02/03/它并将其添加到.PHONY节-这是嘈杂,恶心,只是不正确的.
我怎么能避免这种情况?我可以用模板重新定义所有任务,以便在一行中添加新任务组的好机制吗?
由于问题是关于在Makefile中编写可重用代码,我将举例说明如何在GNU Make中使用模式规则(看起来这就是你提到.PHONY目标时所使用的内容).但是,如果您没有使用任何Make的依赖项检查,那么使用shell脚本执行此操作可能更简单 - 例如:
#!/bin/sh
TASKS="task01 task02 task03"
for i in $TASKS; do
rm $i $i.ext $i.o -f;
compiler $i.ext -O2 --make;
./$i;
done
Run Code Online (Sandbox Code Playgroud)
但是,为了将原则扩展到Make,我们还有另一个需要解决的问题.形式的行:
task01-all: task01-clean task01 task01-run
Run Code Online (Sandbox Code Playgroud)
不要告诉Make以什么顺序构建先决条件 - 只需要在task01-all构建之前完成所有这些操作.相反,每个要运行的步骤都应该取决于之前的步骤.像这样的东西:
TASKS=task01-run task02-run task03-run
.PHONY: all $(TASKS) $(TASKS:run=clean)
all: $(TASKS)
$(TASKS:run=clean): %-clean:
rm $* $*.ext $*.o -f
%: %.ext | %-clean
compiler $< -O2 --make
$(TASKS): %-run: %
./$<
Run Code Online (Sandbox Code Playgroud)
规则%被称为"模式规则",它们是避免为不同目标多次重写相同规则的好工具.需要注意的是,Make通常不会检查.PHONY目标的模式规则; 我们通过在目标列表和第二个冒号(例如$(TASKS):)之前添加前缀来告诉Make明确地这样做.
由于task01-run需要task01为了工作,我们制定%-run目标依赖%.此外,您的Makefile显示您希望每次都运行干净,因此我们%依赖于%-clean.由于%-clean实际上并没有产生任何输出,我们将其设为"仅订单"依赖项 - Make不会查找时间戳或任何内容,它只会在需要运行%-clean规则时首先运行%规则."仅订购"依赖项放在|:
%: %.ext | %-clean
Run Code Online (Sandbox Code Playgroud)
值得一提的是,Make的最大优势之一是它可以通过不重复不需要重复的工作来节省时间 - 即,如果依赖关系比目标更新,它只会运行规则.所以,你可以离开过的依赖%-clean,这将导致做出只运行compiler $< -O2 --make,如果%.ext是比新%:
%: %.ext
compiler $< -O2 --make
Run Code Online (Sandbox Code Playgroud)
然后,您可以添加规则以运行所有%-clean目标:
.PHONY: all $(TASKS) $(TASKS:run=clean) clean
clean: $(TASKS:run=clean)
Run Code Online (Sandbox Code Playgroud)
最后一件事:我在食谱中使用了一些特殊的变量.$@代表正在建造的目标.$<代表第一个依赖.$*代表模式规则的"主干"(即,与之匹配的部分%).
| 归档时间: |
|
| 查看次数: |
2409 次 |
| 最近记录: |