比方說,我有一個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