依赖树中的 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:
这样的简单规则。至少,我还没有使用那种形式的东西来工作) .
谢谢。
【问题讨论】:
您是否尝试打印出SOURCES
和OBJECTS
,以确保它们正确无误?
另外,现在 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 循环的主要内容,如果未能解决你的问题,请参考以下文章