我正在尝试向多个文件添加公共依赖项。我已经通过模式匹配尝试了此操作,但无法正常工作。下面是我的可复制性最低的示例:
file1.out:
cat source.txt | grep "hello,world" > file1.out
file2.out:
cat source.txt > file2.out
%.out: source.txt
我的目标是将source.txt添加为对file1.out和file2.out(以及以后可能添加的所有其他* .out文件)的依赖项。任何建议都将不胜感激(如果这是一个基本问题,我深表歉意,但我在制造手册中找不到任何相关内容。
答案 0 :(得分:3)
我假设您正在使用GNU make。您的问题来自GNU make如何处理模式(隐式)规则。从Implicit Rule Search Algorithm的GNU make manual部分开始介绍:
以下是用于搜索隐式规则的过程 目标t每个双冒号规则都遵循此过程, 没有配方,对于普通规则的每个目标都没有一个 配方,以及不是任何规则目标的每个先决条件。 还递归地遵循了来自的先决条件 隐式规则,用于搜索规则链。
因此,file1.out
和file2.out
目标不会考虑您的模式规则,因为它们是带有食谱的普通规则的目标。
解决方案:您可以在变量中列出*.out
个目标,并使用它来声明它们都依赖于source.txt
:
OUTFILES := $(wildcard *.out)
$(OUTFILES): source.txt
file1.out:
cat source.txt | grep "hello,world" > file1.out
file2.out:
cat source.txt > file2.out
如果目标可以位于子目录中,则可以使用shell
make函数来调用find
,而不要使用wildcard
make函数:
OUTFILES := $(shell find . -type f -name '*.out')
注意:
这仅适用于现有的*.out
文件。如果目标文件列表尚不存在(因此可以通过make进行搜索),并且您自己没有在makefile中提供该列表,则make不会发明目标文件的列表。
如果cat source.txt | grep "hello,world" > file1.out
文件不包含source.txt
字符串,则您的hello,world
配方将失败,退出状态为非零。如果发生这种情况,make将终止并显示一条错误消息。您可以通过以下方式避免这种情况:
cat source.txt | grep "hello,world" > file1.out || true
自动变量非常方便。如果source.txt
是目标的唯一前提,则可以使用以下方法简化所有步骤:
file1.out:
cat "$<" | grep "hello,world" > "$@" || true
file2.out:
cat "$<" > "$@"
({$@
扩展为规则的目标,$<
扩展为第一个前提)。这样可以避免输入错误,并使配方更加通用。有时,您甚至可以针对多个目标使用相同的配方:
file1.out file3.out:
cat "$<" | grep "hello,world" > "$@" || true