Makefile 模式规则:Circular makefile.o <- makefile dependency dropped
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
文件名中,我从 XX
中删除 .debug
或 .release
后缀,并使用 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(s),然后它这样做,然后从头开始重新开始 -
包括尝试更新 makefile。参见 3.5 How Makefiles Are Remade。
在你的食谱中:
%.o: $$(basename %)
$(CC) $(CC_FLAGS) $(INCLUDE_FOLDERS) -c -o $@ $<
您已经为 make
提供了从 makefile
生成 makefile.o
的规则。
这也是内置配方中规则的逆
%: %.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
从单个目标文件生成可执行文件。所以你的食谱引入了循环性:
makefile.o <- makefile <- makefile.o
当 make
将 makefile
本身视为目标时。
您可以通过明确删除内置的逆规则来抑制循环,
通过编写空规则:
%: %.o
在生成文件中。然后你可以观察到以下混乱
编译器:
$ 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
path 选项
- 这是预处理器选项 - 通常通过 CPPFLAGS
.
传递
我正在为一个需要支持一些配置的 C++ 项目编写 makefile,即 debug 、 release 以及将来可能更多的自定义配置。
目前,我生成的 .o 文件的命名约定是 $(SOURCE_FULLPATH).$(CONFIGURATION).o
。例如,ABC.cpp
在调试模式下生成 ABC.cpp.debug.o
。
现在我想编写模式规则以独立于配置的方式生成这些目标文件。我所做的是:从每个 XX.o
文件名中,我从 XX
中删除 .debug
或 .release
后缀,并使用 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(s),然后它这样做,然后从头开始重新开始 - 包括尝试更新 makefile。参见 3.5 How Makefiles Are Remade。
在你的食谱中:
%.o: $$(basename %)
$(CC) $(CC_FLAGS) $(INCLUDE_FOLDERS) -c -o $@ $<
您已经为 make
提供了从 makefile
生成 makefile.o
的规则。
这也是内置配方中规则的逆
%: %.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
从单个目标文件生成可执行文件。所以你的食谱引入了循环性:
makefile.o <- makefile <- makefile.o
当 make
将 makefile
本身视为目标时。
您可以通过明确删除内置的逆规则来抑制循环,
通过编写空规则:
%: %.o
在生成文件中。然后你可以观察到以下混乱 编译器:
$ 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
path 选项
- 这是预处理器选项 - 通常通过 CPPFLAGS
.