[英]Makefile Pattern rule: Circular makefile.o <- makefile dependency dropped
我正在为一个C ++项目制作一个makefile,该文件需要支持一些配置,例如,debug,release和将来可能的一些自定义配置。
目前,我对生成的.o文件的命名约定是$(SOURCE_FULLPATH).$(CONFIGURATION).o
。 例如, ABC.cpp
在调试模式下生成ABC.cpp.debug.o
。
现在,我想编写模式规则,以独立于配置的方式生成那些目标文件。 我所做的是:从每个XX.o
文件名,我剥去.debug
或.release
从后缀XX
,并使用剩余部分XX
作为源文件名。
%.o: $$(basename %)
$(CC) $(CC_FLAGS) $(INCLUDE_FOLDERS) -c -o $@ $<
使用此技巧,我可以正确构建可执行文件,但从make收到一条警告消息:
make: Circular makefile.o <- makefile dependency dropped.
我很困惑,因为我没有在makefile中的任何地方列出makefile
或makefile.o
作为目标或依赖项。 我在SO上进行了搜索,但是有关循环依赖的大多数问题都在特定的用户源文件上,而不是在makefile本身上。 谁能帮助我了解导致循环依赖的原因以及如何消除此警告消息 ?
下面列出了可以重现此问题的示例生成文件。
.SECONDEXPANSION:
PROJECT := helloworld
CC := clang++
BUILD_FOLDER := Build
OBJ_FILE_SUFFIX := .o
# Source
CPP_FILES :=\
Source/hello.cpp \
Source/mysqrt.cpp \
INCLUDE_FOLDERS := \
-IInclude
# MMD outputs the dependency files (".d" files). These files will be used by
# this makefile to allow for dependency checking on .h files.
CC_FLAGS += -MMD
EXISTING_OBJ_FILES = $(wildcard $(addsuffix *.o, $(basename $(CPP_FILES))))
##--------------------
## Targets definition
##--------------------
.PHONY:default
default: all
.PHONY:all
all: debug release
.PHONY:debug release
# Add a 'debug'/'release' suffix to the name of the object file
# e.g. hello.cpp -> hello.cpp.debug.o
debug release: OBJ_FILES=$(addsuffix .$@$(OBJ_FILE_SUFFIX), $(CPP_FILES))
debug release: $${OBJ_FILES} # Use Secondary Expansion to get the obj names
$(CC) $^ -o $(BUILD_FOLDER)/$(PROJECT)_$@
# Strip configuration name from the end of the object file name
%.o: $$(basename %)
$(CC) $(CC_FLAGS) $(INCLUDE_FOLDERS) -c -o $@ $<
## clean: remove executable, all object files, and all dependency files
.PHONY:clean
clean:
-rm -f $(BUILD_FOLDER)/$(PROJECT) $(EXISTING_OBJ_FILES) $(EXISTING_OBJ_FILES:.o=.d)
# Include the dependent files so that in later builds, modified .h files
# will cause all .cpp dependent on them to rebuild
-include $(OBJ_FILES:.o=.d)
文件夹结构为
makefile
Source
- hello.cpp
- mysqrt.cpp
Include
- mysqrt.h
make debug
的完整输出为
make: Circular makefile.o <- makefile dependency dropped.
clang++ -MMD -IInclude -c -o Source/hello.cpp.debug.o Source/hello.cpp
clang++ -MMD -IInclude -c -o Source/mysqrt.cpp.debug.o Source/mysqrt.cpp
clang++ Source/hello.cpp.debug.o Source/mysqrt.cpp.debug.o -o Build/helloworld_debug
除了第一行,其他一切都很好。
如果有人在我的makefile中存在任何不良做法(如果我仍然是makefile中的新手),那么如果有人可以指向我,我也将非常感激。 先感谢您!
GNU Make总是在尝试进行其他操作之前尝试更新已读取的makefile。 如果发现规则和先决条件要求其更新Makefile,则它将这样做,然后从头开始-包括尝试更新Makefile。 请参见3.5如何重新制作Makefile 。
在您的食谱中:
%.o: $$(basename %)
$(CC) $(CC_FLAGS) $(INCLUDE_FOLDERS) -c -o $@ $<
您所提供make
与制作规则makefile.o
从makefile
。
这也是内置配方中规则的逆向
%: %.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
从单个目标文件生成可执行文件。 因此,您的配方已引入了圆度:
makefile.o <- makefile <- makefile.o
当make
将makefile
本身作为目标时。 通过编写空规则,可以明确删除内置的逆规则来抑制圆度:
%: %.o
在makefile中。 然后,您可以在编译器部分观察到以下混乱:
$ make makefile.o
clang++ -c -o makefile.o makefile
clang: warning: makefile: 'linker' input unused
如果尝试创建任何依赖makefile.o
目标,也会发生同样的情况。
可以肯定地假设您将没有依赖于makefile.o
目标。 但是,尝试从任何现有文件foo
编译foo.o
的规则显然更加需要或需要。 对于您希望捕获的特定依赖性模式:
foo.cpp.{debug|release}.o: foo.cpp
您最好拥有:
%.o: $$(basename $$(basename %)).cpp
$(CC) $(CC_FLAGS) $(INCLUDE_FOLDERS) -c -o $@ $<
注意,顺便说一句,在GNU Make约定中-由GNU Make的内置规则假定的约定CC
表示您的C编译器,而CXX
表示您的C ++编译器。 同样,C编译器的标志表示为CFLAGS
,C ++编译器的标志表示为CXXFLAGS
。
用于预处理器的标志表示为CPPFLAGS
,并且-I
路径选项(即预处理器选项)通常通过CPPFLAGS
传递。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.