这似乎与How to write Makefile where target and source files have the same extension?略有关系。在那个问题中,扩展名是相同的,但输入和输出文件似乎在同一个目录中,文件名被有条件地重命名。
我在.txt
中有大量../src/
个文件需要处理,并作为txt文件转储到./
(这是一个名为target/
的目录)同名。我想使用make
,以便只有../src/
中已更改的文件才会在./
中更新。在将实际代码放入之前,我想让原型工作。
Makefile
中的./
如下:
DIR = ../src
INPUTS = $(wildcard $(DIR)/*.txt)
OUTPUTS = $(patsubst $(DIR)/%.txt,%.txt,$(INPUTS))
all: $(OUTPUTS)
.PHONY: $(INPUTS)
check:
@echo "DIR = $(DIR)"
@echo "INPUTS = $(INPUTS)"
@echo "OUTPUTS = $(OUTPUTS)"
%.txt: $(DIR)/%.txt
sed -e "s/test/cat/g" "$<" > $@
目前,../src/
的内容为test1.txt
和test2.txt
。
正如Makefile现在一样,运行make test2.txt
会按预期生成文件。
target/ $ make test2.txt
sed -e "s/test/cat/g" "../src/test2.txt" > test2.txt
正在运行make check
会正确显示INPUTS
和OUTPUTS
。
target/ $ make check
DIR = ../src
INPUTS = ../src/test1.txt ../src/test2.txt
OUTPUTS = test1.txt test2.txt
如果我运行make all
,它每次都会生成每个文件。这是预期的.PHONY $(INPUTS)
行。
如果我删除.PHONY $(INPUTS)
目标,则Make会自行绑定,尝试找到要生成../src/test1.txt
的目标并在其前面保留$(DIR)
前缀,直到它变得太长文件名并放弃。
make: stat: ../src/../src/../src/ [repeat for a few pages] ../src/../src/test1.txt: File name too long
make: stat: ../src/../src/../src/ [repeat for a few pages] ../src/../src/../src/test1.txt: File name too long
make: *** No rule to make target `../src/../src/../src/[repeat]../src/../src/test1.txt', needed by `../src/[repeat]../src/../src/test1.txt'. Stop.
它永远不会处理test2.txt
。
在我起草这篇文章时,我有意从DIR中删除../
,
并重新定位Makefile,使其成为src/
和target/
的父级。这种方法似乎有效,但并不理想。最终会有一系列这些Makefile,每个Makefiles从一个目录拉到另一个目录。
有没有办法让Makefile
保持在&#39;目标/&#39;以及生成的目标文件,并将这些目标文件基于相对路径中的某些内容?
答案 0 :(得分:2)
替换
%.txt: $(DIR)/%.txt
使用:
${CURDIR}/%.txt: $(DIR)/%.txt
这种方式%.txt
与任何目录中的任何.txt
文件都不匹配。换句话说,您将此规则的范围仅限于${CURDIR}/
中的文件,这可以防止无限递归。
有关详细信息,请参阅§10.5.4 How Patterns Match。
避免相对路径也是一种好习惯:
DIR = $(abspath ../src)