我有一个大而复杂的Makefile设置,可以对一些数据文件进行后处理。总的来说它工作得很好,但是我遇到了一个烦人的问题,即Make在不同的目录名下多次构建相同的目标。
举个简单的例子,考虑一下Makefile
foo : 1/foo 2/foo
cat $^ > $@
%/foo : %/../bar
cat $^ > $@
%/bar : %/baz
cat $^ > $@
使用文件baz
和目录1
和2
初始化,make将以并行模式完成以下一系列构建:
cat 1/../baz > 1/../bar
cat 2/../baz > 2/../bar
cat 2/../bar > 2/foo
cat 1/../bar > 1/foo
cat 1/foo 2/foo > foo
rm 2/../bar
注意前两个命令如何完全相同。
有没有办法说服让1/../bar
和2/../bar
是同一个文件,所以它只应该做一次这个食谱?
答案 0 :(得分:1)
您可以使用realpath or abspath函数
来使用绝对路径,而不是使用相对路径
$(realpath names…)
对于名称中的每个文件名,返回规范的绝对名称。规范名称不包含任何名称。或..组件,也没有任何重复的路径分隔符(/)或符号链接。如果发生故障,则返回空字符串。有关可能的失败原因列表,请参阅
realpath(3)
文档。
$(abspath names…)
对于名称中的每个文件名,返回一个不包含任何名称的绝对名称。或..组件,也没有任何重复的路径分隔符(/)。请注意,与realpath函数相比,abspath不解析符号链接,也不要求文件名引用现有文件或目录。使用通配符函数来测试是否存在。
$(abspath foo): $(abspath 1/foo) $(abspath 2/foo)
cat $^ > $@
%/foo: $(abspath %/../bar)
cat $^ > $@
%/bar: %/baz
cat $^ > $@
或类似的东西:
TOP := $(abspath .)
$(TOP)/foo: $(TOP)/1/foo $(TOP)/2/foo
cat $^ > $@
%/foo: $(abspath %/../bar)
cat $^ > $@
%/bar: %/baz
cat $^ > $@
结果如下
jmlemetayer@prometheus:~/foobar$ make -j5
cat /home/jmlemetayer/foobar/baz > /home/jmlemetayer/foobar/bar
cat /home/jmlemetayer/foobar/bar > /home/jmlemetayer/foobar/1/foo
cat /home/jmlemetayer/foobar/bar > /home/jmlemetayer/foobar/2/foo
cat /home/jmlemetayer/foobar/1/foo /home/jmlemetayer/foobar/2/foo > /home/jmlemetayer/foobar/foo
rm /home/jmlemetayer/foobar/bar