Makefile与Windows资源文件的循环依赖关系

问题描述 投票:0回答:1

在运行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)。

当我运行它时,一切似乎都工作,我得到一个可行的可执行文件,但是,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

这种循环依赖是否发生,因为我在技术上有两个.o规则?换句话说,我该如何纠正这种循环依赖?


Edit 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,你会怎么做到这一点?可能吗?

Edit 2:

@MadScientist建议使用match-anything rule完美地纠正了问题。这现在允许我使用.rc.o后缀结尾。请参阅下面的@MadScientist更新的答案。

makefile circular-dependency win32gui windres
1个回答
1
投票

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

另一种方法是使用static pattern rules作为windres目标:

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

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

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

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

%: %.o ; ...

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

您需要做的是通知make *.rc文件是源文件,make不应该尝试构建它们。您可以通过声明终端规则来执行此操作。在GNU制作手册中,全面讨论了处理match-anything rules(单独使用%的目标,与任何目标相匹配的规则)的复杂性。

添加此项以通知make你的.rc文件是终端(也就是说,它们不能用其他东西构建):

%.rc:
© www.soinside.com 2019 - 2024. All rights reserved.