依赖树中的 Makefile 循环

Posted

技术标签:

【中文标题】依赖树中的 Makefile 循环【英文标题】:Makefile cycle in dependency tree 【发布时间】:2015-09-04 09:47:56 【问题描述】:

我正在尝试使用 makefile 和 nmake 在 Windows 上构建我的 c 项目。

我收到以下错误: NMAKE : fatal error U1071: cycle in dependency tree for target 'src\source.c' Stop.

完整的makefile是这个

CC = cl
LINK = link
CFLAGS = /Ox \
/I ext\MulticoreBSP-for-C\ \
/I ext\unistd\include \
/I ext\pthreads-win32\sources\pthreads-w32-2-9-1-release \
/D HAVE_STRUCT_TIMESPEC

SOURCE_DIR = src
OBJECT_DIR = build

LIBS = ext\pthreads-win32\sources\pthreads-w32-2-9-1-release\pthreadVC2.lib

DLLS = bin\pthreadVC2.dll
DLLS_SRC = ext\pthreads-win32\sources\pthreads-w32-2-9-1-release\pthreadVC2.dll

BSP_SOURCES = ext\MulticoreBSP-for-C\mcbsp.c ext\MulticoreBSP-for-C\mcinternal.c ext\MulticoreBSP-for-C\mcutil.c
USER_SOURCES = source.c

SOURCES = src\$(USER_SOURCES) $(BSP_SOURCES)
OBJECTS = $(SOURCES:*.c=build\*.obj)
# OBJECTS = build\source.obj build\mcbsp.obj build\mcinternal.obj  build\mcutil.obj
EXECUTABLE = bin\BSP.exe

all: $(EXECUTABLE) $(DLLS) $(OBJECTS)

$(EXECUTABLE): $(OBJECTS)
    $(LINK) $(OBJECTS) $(LIBS) /OUT:$(EXECUTABLE)

$(DLLS): $(DLLS_SRC)
    copy $** $@

$(OBJECTS): $(SOURCES)
    $(CC) $(LDFLAGS) /c /Fo.\$(OBJECT_DIR)\ $@ $** $(CFLAGS)

clean:
    del $(OBJECT_DIR)\*.obj bin\*.dll bin\*.exe

我可以看到问题来自将第 21 行中的 OBJECTS 定义为 OBJECTS = $(SOURCES:*.c=build\*.obj) 然后有规则 $(OBJECTS): $(SOURCES)。这是循环的事实是相当清楚的,并且使用第 22 行中 OBJECTS 的注释定义可以正常工作。

我怎样才能实现OBJECTS 的自动定义,而第 33 行的规则不会造成麻烦?我需要一个不同的规则,还是别的什么?

(我为源文件和对象有单独的文件夹,我认为这样做会阻止我使用像.c.obj: 这样的简单规则。至少,我还没有使用那种形式的东西来工作) .

谢谢。

【问题讨论】:

您是否尝试打印出SOURCESOBJECTS,以确保它们正确无误? 另外,现在 all 目标文件依赖于 all 源文件。所以修改单个源文件会导致所有源文件的重新编译。 谢谢约阿希姆。回显OBJECTS 变量后,似乎strsub 不起作用,OBJECTS 变量与SOURCES 相同。我将不得不对此进行调查,除非您知道它为什么不起作用。 nmake 不同于 POSIX 环境中的“标准”make 程序,可能不支持这种形式的字符串替换? documentation 表示应该没问题。至少现在我知道这是导致问题的原因,我可以稍微尝试一下以使其正常工作。另外,您提到目前所有对象都依赖于所有来源,这是由于$(OBJECTS): $(SOURCES) 规则吗?我该如何改变呢? 【参考方案1】:

虽然 nmake 支持模式匹配语法$(macroname:string1=string2),但不支持以这种方式使用通配符。如果我找到在 nmake 的字符串替换版本中使用通配符的方法,我将编辑此答案。

编辑:

它有点狡猾,但以下解决了问题

BSP_SOURCES = mcbsp.c mcinternal.c mcutil.c
USER_SOURCES = source.c

SOURCES = src\$(USER_SOURCES) ext\MulticoreBSP-for-C\$(BSP_SOURCES: = ext\MulticoreBSP-for-C\)
_OBJECTS = build\$(USER_SOURCES) build\$(BSP_SOURCES: = build\)
OBJECTS = $(_OBJECTS:.c=.obj)

基本上,模式匹配源列表中元素之间的空格,而不是使用通配符。请注意,第一个前缀是在模式匹配之外添加的,因为列表的开头没有空格。另请注意,替换必须分两步完成。

不优雅但有效。

【讨论】:

以上是关于依赖树中的 Makefile 循环的主要内容,如果未能解决你的问题,请参考以下文章

Makefile循环依赖错误

将具有循环链接依赖的makefile转换为CMake

(转)makefile中的自动依赖规则

Makefile 简介

makefile

makefile 中的自动依赖生成