我试图理解为什么有些 Makefile 具有先决条件%.txt
,而其他 Makefile 则具有*.txt
.
我已经创建了这个文件夹布局。
$ tree .
.
├── hi1.txt
├── hi2.txt
├── hi3.txt
└── Makefile
首先,我尝试了这个。
foo.txt: *.txt
echo $^
它达到了我的预期。
$ make
echo hi1.txt hi2.txt hi3.txt
hi1.txt hi2.txt hi3.txt
但是,后来我看到一些 Makefile 用作%.txt
通配符。所以我接下来尝试了。
foo.txt: %.txt
echo $^
但是,这会导致错误。
$ make
make: *** No rule to make target '%.txt', needed by 'foo.txt'. Stop.
有人可以解释为什么会发生这种情况吗?
GNU Make 4.3
答案1
在 中make
,百分号用于模式匹配,它需要目标中的 1 以及(至少)先决条件中的 1:
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
通过这个 makefile,我们指定为了构建文件名以 结尾的文件.o
,您需要有一个具有相同前缀的文件,但以 结尾.c
而不是.o
为了能够构建这些规则,您显然需要能够参考目标和先决条件;这就是$@
和$<
变量的用武之地。$@
表示“此规则的目标”,并且$<
表示“此规则的第一个列出的先决条件”。如果您需要构建一个使用的命令全部先决条件(例如,链接可执行文件),那么您可以使用变量$^
:
%: %.o lib.o
$(CC) $(LDFLAGS) -o $@ $^
如果您将上述两个示例 makefile 片段合并到一个 makefile 中,并且您有一个文件“lib.c”,其中包含一些您想要在同一目录中的多个 C 程序中使用的通用代码,那么您可以添加任何随机.c
文件,比如说foo.c
,并将其编译成一个程序foo
,该程序也链接到 中的代码lib.c
,而不需要对 makefile 进行任何更改。
请注意,只要先决条件不同,也可以具有具有相同目标的模式;例如,以下内容将起作用:
%.o: %.c
$(CC).....
%.o: %.cpp
$(CXX).....
也就是说,只要此目录中没有任何与 C 源文件同名(无扩展名)的 C++ 源文件,它就会按预期工作。如果确实是这种情况,C++ 版本将被忽略,而 C 源代码将被编译(因为 C 规则在 makefile 中首先列出)
欲了解更多信息,请参阅相关部分在 GNU make 手册中。