[英]Makefile circular dependency with Windows resource files
There have been several questions regarding circular dependencies being dropping when running a Makefile ( here and here ), however, I am still a bit confused as to why they are occurring. 关于在运行Makefile时( 此处和此处 )删除循环依赖项有几个问题,但是,我对为什么会出现它们有些困惑。
For example, I am trying to compile a Win32 GUI program that contains resource files ( from this tutorial ). 例如,我试图编译一个包含资源文件的Win32 GUI程序( 来自本教程 )。 These resource files are compiled to object files through the
windres
command, so they can be linked to the final executable ( as described here ): 这些资源文件通过
windres
命令编译为目标文件,因此可以将它们链接到最终的可执行文件( 如此处所述 ):
CC = gcc
CFLAGS = -mwindows
DEPS = resource.h
OBJ = menu_one.o $(patsubst %.rc,%.rc.o,$(wildcard *.rc))
all: menu_one
%.rc.o: %.rc
windres $^ -o $@
%.o: %.c $(DEPS)
$(CC) -c $< -o $@ $(CFLAGS)
menu_one: $(OBJ)
$(CC) $^ -o $@ $(CFLAGS)
The command $(patsubst %.rc,%.rc.o,$(wildcard *.rc))
takes all the resource files ending in .rc
and slaps a .o
extension onto them (eg resource.rc.o
). 命令
$(patsubst %.rc,%.rc.o,$(wildcard *.rc))
接收所有以.rc
结尾的资源文件,并在文件上加上.o
扩展名(例如, resource.rc.o
)。
When I run this, everything seems to work and I get a working executable, however, Make outputs the following: 当我运行此命令时,一切似乎都可以正常工作,并且可以正常运行,但是,Make输出以下内容:
gcc -c menu_one.c -o menu_one.o -mwindows
make: Circular menu_one.rc <- menu_one.rc.o dependency dropped.
windres menu_one.rc -o menu_one.rc.o
gcc menu_one.o menu_one.rc.o -o menu_one -mwindows
Is this circular dependency occurring because I technically have two .o
rules? 因为我在技术上有两个
.o
规则,所以发生这种循环依赖吗? In other words, how can I correct this circular dependency? 换句话说, 如何纠正这种循环依赖性?
I tried following what @MadScientist said, however, this still created a circular dependency with Make. 我尝试按照@MadScientist的说法进行操作,但是,这仍然与Make产生了循环依赖关系 。 After some more Googling, I came across the following page .
经过更多谷歌搜索之后,我遇到了下一页 。 Towards the very bottom there is a section titled " Circular File Dependencies ."
在最底部,有一个标题为“ 循环文件依赖项 ”的部分。 This got me thinking about the output from Make:
这让我考虑了Make的输出:
make: Circular menu_one.rc <- menu_one.rc.o dependency dropped.
It looks to be that the rc
suffix is creating this dependency - even though it is not part of the file extension of the outputted object file (ie file.rc.o
). 看起来
rc
后缀正在创建此依赖关系-即使它不是输出目标文件(即file.rc.o
)的文件扩展名的一部分。 If I change the output file suffix to be .res.o
, the circular dependency goes away entirely: 如果将输出文件后缀更改为
.res.o
,则循环依赖关系将完全消失:
...
RESOBJ = $(patsubst %.rc,%.res.o,$(wildcard *.rc))
OBJ = menu_one.o $(RESOBJ)
...
%.res.o: %.rc
windres $^ -o $@
...
This sparks a very similar question, if I wanted to use the previous suffix .rc.o
, how would you accomplish this? 如果我想使用前面的后缀
.rc.o
,这会引发一个非常类似的问题, 您将如何实现? Is it possible? 可能吗?
@MadScientist 's suggestion of using a match-anything rule worked perfectly with correcting the problem. @MadScientist提出的使用任何匹配规则的建议可以完美地解决问题。 This now allows me to use the
.rc.o
suffix ending. 现在,这使我可以使用
.rc.o
后缀结尾。 See @MadScientist 's updated answer below. 请参阅下面的@MadScientist更新后的答案。
One way is to not name your windres
output files with a .o
extension. 一种方法是不以
.o
扩展名命名windres
输出文件。 If you choose a different extension, you won't have this problem. 如果您选择其他扩展名,则不会有此问题。
Another way is to use static pattern rules for the windres
targets: 另一种方法是对
windres
目标使用静态模式规则 :
RCOBJ := $(patsubst %.rc,%.rc.o,$(wildcard *.rc))
OBJ = menu_one.o $(RCOBJ)
...
$(RCOBJ) : %.rc.o : %.rc
windres $^ -o $@
Since static pattern rules are shorthand for creating explicit rules, and are not implicit rules, they don't participate in searches so make won't come up with a circular dependency. 由于静态模式规则是创建显式规则的缩写,并且不是隐式规则,因此它们不参与搜索,因此make不会产生循环依赖关系。
ETA ETA
OK I created your example locally. 好的,我在本地创建了您的示例。 Using
make -d
we can see what happens: make needs to build menu_one.rc.o
and it finds our rule with a prerequisite of menu_one.rc
. 使用
make -d
我们可以看看会发生什么:让需要建立menu_one.rc.o
并找到我们的规则,用的前提menu_one.rc
。 Then it needs to see if it can rebuild manu_one.rc
, and it find the generic pattern rule for building executables: 然后,需要查看是否可以重建
manu_one.rc
,并找到用于构建可执行文件的通用模式规则:
%: %.o ; ...
Matching this pattern with a target of menu_one.rc
gives a prerequisite of menu_one.rc.o
, and you have a loop. 此模式匹配与目标
menu_one.rc
给人的先决条件menu_one.rc.o
,和你有一个循环。
What you need to do is notify make that the *.rc
files are source files and make shouldn't try to build them. 您需要做的是通知make
*.rc
文件是源文件,并且make不应尝试构建它们。 You can do this by declaring a terminal rule . 您可以通过声明终止规则来执行此操作。 There is a comprehensive discussion of the intricacies of dealing with match-anything rules (rules with a target of
%
alone, which matches any target) in the GNU make manual. 在GNU make手册中,全面讨论了处理任何匹配规则 (仅目标为
%
规则,该目标与任何目标均匹配)的复杂性。
Add this to inform make that your .rc
files are terminal (that is, they can't be built from something else): 添加以下内容以通知使您的
.rc
文件处于终端状态(即,它们不能由其他内容构建):
%.rc:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.