Windows资源文件对Makefile的循环依赖性

时间:2019-03-24 20:16:42

标签: makefile circular-dependency win32gui windres

在运行Makefile时,有几个关于循环依赖项被删除的问题(herehere),但是,我对它们为什么仍然有些困惑正在发生。

例如,我正在尝试编译包含资源文件(from this tutorial)的Win32 GUI程序。这些资源文件通过windres命令编译为目标文件,因此可以将它们链接到最终的可执行文件(as described here):

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)

命令$(patsubst %.rc,%.rc.o,$(wildcard *.rc))提取所有以.rc结尾的资源文件,并将.o扩展名加到它们上(例如resource.rc.o)。

运行此命令时,一切似乎都能正常工作,并且我得到了一个可执行的可执行文件,但是,使输出如下:

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

由于我在技术上有两个.o规则,所以发生了循环依赖项吗?换句话说,如何纠正这种循环依赖性?


编辑1:

我尝试遵循@MadScientist的说法,但是,这仍然使用Make创建了循环依赖项。经过更多谷歌搜索后,我遇到了the following page。在最底部,有一个标题为“ 循环文件依赖项”的部分。这让我考虑了Make的输出:

make: Circular menu_one.rc <- menu_one.rc.o dependency dropped.

看起来rc后缀正在创建此依赖关系-即使它不是输出目标文件(即file.rc.o)的文件扩展名的一部分。如果将输出文件后缀更改为.res.o,则循环依赖项将完全消失:

...
RESOBJ = $(patsubst %.rc,%.res.o,$(wildcard *.rc))
OBJ = menu_one.o $(RESOBJ)
...
%.res.o: %.rc
    windres $^ -o $@
...

这引发了一个非常类似的问题,如果我想使用上一个后缀.rc.o,您将如何实现?有可能吗?

编辑2:

@MadScientist的使用match-anything rule的建议可以很好地解决问题。现在,这使我可以使用.rc.o后缀结尾。请参见下面的@MadScientist更新后的答案。

1 个答案:

答案 0 :(得分:1)

一种方法是不使用扩展名windres命名.o输出文件。如果您选择其他扩展名,则不会出现此问题。

另一种方法是对windres目标使用static pattern rules

RCOBJ := $(patsubst %.rc,%.rc.o,$(wildcard *.rc))
OBJ = menu_one.o $(RCOBJ)

  ...
$(RCOBJ) : %.rc.o : %.rc
        windres $^ -o $@

由于静态模式规则是创建显式规则的缩写,并且不是隐式规则,因此它们不参与搜索,因此make不会产生循环依赖性。

ETA

好的,我在本地创建了您的示例。使用make -d,我们可以看到发生了什么:制造menu_one.rc.o的需求,并且它以menu_one.rc的先决条件找到了我们的规则。然后,它需要查看是否可以重建manu_one.rc,并找到用于构建可执行文件的通用模式规则:

%: %.o ; ...

将此模式与目标menu_one.rc相匹配给出了menu_one.rc.o的先决条件,并且有一个循环。

您需要做的是通知make *.rc文件是源文件,并且make不应尝试构建它们。您可以通过声明终止规则来实现。 GNU make手册中全面讨论了处理match-anything rules(仅目标为%的规则,与任何目标匹配的规则)的复杂性。

添加此信息以使您的.rc文件处于终端状态(也就是说,它们不能通过其他方式构建):

%.rc: