比方说,我有一个makefile与规则的Makefile,头依赖
%.o: %.c
gcc -Wall -Iinclude ...
我想*的.o被重建时一个头文件的变化。而不是制定一个依赖关系列表,只要/include
中的任何头文件发生更改,则必须重建该目录中的所有对象。
我想不出一个很好的方法来改变规则来适应这一点,我愿意提出建议。奖励积分,如果标题的列表不必进行硬编码
比方说,我有一个makefile与规则的Makefile,头依赖
%.o: %.c
gcc -Wall -Iinclude ...
我想*的.o被重建时一个头文件的变化。而不是制定一个依赖关系列表,只要/include
中的任何头文件发生更改,则必须重建该目录中的所有对象。
我想不出一个很好的方法来改变规则来适应这一点,我愿意提出建议。奖励积分,如果标题的列表不必进行硬编码
如果您使用GNU编译器,编译器可以为您组装一系列依赖项。 Makefile片段中:
depend: .depend
.depend: $(SRCS)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ -MF ./.depend;
include .depend
或
depend: .depend
.depend: $(SRCS)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ > ./.depend;
include .depend
其中SRCS
是一个变量指向源文件的完整清单。
也有工具makedepend
,但我从来不喜欢它,就像gcc -MM
如何像:
includes = $(wildcard include/*.h)
%.o: %.c ${includes}
gcc -Wall -Iinclude ...
您也可以直接使用通配符,但我往往会发现,我需要他们更多的比一个地方。
请注意,这只适用于小型项目,因为它假定每个目标文件都依赖于每个头文件。
正如我贴here GCC可以建立依赖关系,并在同一时间编译:
DEPS := $(OBJS:.o=.d)
-include $(DEPS)
%.o: %.c
$(CC) $(CFLAGS) -MM -MF $(patsubst %.o,%.d,[email protected]) -o [email protected] $<
的“-MF '参数指定一个文件来存储依赖项。
'-include'开始处的短划线指示在.d文件不存在时继续进行Make(例如,在第一次编译时)。
请注意,在-o选项中似乎存在gcc中的错误。如果将对象文件名设置为obj/_file__c.o,则生成的文件 .d将仍包含文件.o,而不是obj/_file__c.o。
我更喜欢这个解决方案,而不是Michael Williamson接受的答案,它捕获源+内联文件,源+标题和最终源的更改。这里的优点是,如果只做了一些更改,整个库不会重新编译。对于一个有两个文件的项目来说,这不是一个巨大的考虑因素,如果你有10个或100个源文件,你会发现它们的差异。
COMMAND= gcc -Wall -Iinclude ...
%.o: %.cpp %.inl
$(COMMAND)
%.o: %.cpp %.hpp
$(COMMAND)
%.o: %.cpp
$(COMMAND)
只有在头文件中没有任何需要重新编译除相应实现文件之外的任何cpp文件的情况下才有效。 – matec 2014-11-04 10:28:33
以上马丁的解决方案的伟大工程,但不处理.o文件驻留在子目录中。Godric指出,-MT标志可以解决这个问题,但它同时会阻止.o文件被正确写入。以下将照顾这两个问题:
DEPS := $(OBJS:.o=.d)
-include $(DEPS)
%.o: %.c
$(CC) $(CFLAGS) -MM -MT [email protected] -MF $(patsubst %.o,%.d,[email protected]) $<
$(CC) $(CFLAGS) -o [email protected] $<
大多数答案是惊人的复杂或错误。然而,简单而健壮的示例已在其他地方发布[codereview]。无可否认,GNU预处理器提供的选项有点混乱。然而,去除与-MM
构建目标的所有目录中的文件,而不是一个bug [gpp]:
默认情况下,CPP采用主输入文件名,删除任何 目录组件和任何文件后缀(如“.c”),并附加平台的通用对象后缀。
(较新)-MMD
选项可能是你想要的。为了完整起见,一个makefile文件的例子支持多个src dirs并且用一些注释构建dirs。对于没有构建目录的简单版本,请参见[codereview]。
CXX = clang++
CXX_FLAGS = -Wfatal-errors -Wall -Wextra -Wpedantic -Wconversion -Wshadow
# Final binary
BIN = mybin
# Put all auto generated stuff to this build dir.
BUILD_DIR = ./build
# List of all .cpp source files.
CPP = main.cpp $(wildcard dir1/*.cpp) $(wildcard dir2/*.cpp)
# All .o files go to build dir.
OBJ = $(CPP:%.cpp=$(BUILD_DIR)/%.o)
# Gcc/Clang will create these .d files containing dependencies.
DEP = $(OBJ:%.o=%.d)
# Default target named after the binary.
$(BIN) : $(BUILD_DIR)/$(BIN)
# Actual target of the binary - depends on all .o files.
$(BUILD_DIR)/$(BIN) : $(OBJ)
# Create build directories - same structure as sources.
mkdir -p $(@D)
# Just link all the object files.
$(CXX) $(CXX_FLAGS) $^ -o [email protected]
# Include all .d files
-include $(DEP)
# Build target for every single object file.
# The potential dependency on header files is covered
# by calling `-include $(DEP)`.
$(BUILD_DIR)/%.o : %.cpp
mkdir -p $(@D)
# The -MMD flags additionaly creates a .d file with
# the same name as the .o file.
$(CXX) $(CXX_FLAGS) -MMD -c $< -o [email protected]
.PHONY : clean
clean :
# This should remove all generated files.
-rm $(BUILD_DIR)/$(BIN) $(OBJ) $(DEP)
此方法有效,因为如果存在用于单个目标多重依赖性线,所述依赖关系简单地接合,例如:如上所述
a.o: a.c a.h
./cmd
:
a.o: a.h
a.o: a.c
./cmd
相当于在:Makefile multiple dependency lines for a single target?
以下适用于我:
DEPS := $(OBJS:.o=.d)
-include $(DEPS)
%.o: %.cpp
$(CXX) $(CFLAGS) -MMD -c -o [email protected] $<
这里有一个两班轮:
CPPFLAGS = -MMD
-include $(OBJS:.c=.d)
这适用于默认的化妆食谱,只要你有你的所有目标文件中OBJS
列表。
在下面写下我的回答后,我查看了相关列表并找到了:http://stackoverflow.com/questions/297514/how-can-i-have-a-makefile-automatically-rebuild-source-files-that -include-a-modif看起来是重复的。克里斯多德的答案与我的相同,尽管它使用了不同的命名约定。 – dmckee 2010-03-07 00:37:44