2010-11-24 51 views
3

我有一個使用自動依賴關係生成的C++程序的Makefile。 %.d配方來自GNU Make手冊。Makefile將自己添加爲目標

問題是,以某種方式將「Makefile」添加爲目標,然後隱式規則導致它假定它是可執行文件並使用我的src /%。cpp規則嘗試編譯src/Makefile.cpp。在查看調試信息時,這總是在包含執行之後發生。

No need to remake target `build/Sprite.d'. 
Considering target file `Makefile'. 
    Looking for an implicit rule for `Makefile'. 
    ... 
    Trying pattern rule with stem `Makefile'. 
    Trying implicit prerequisite `Makefile.o'. 
    Looking for a rule with intermediate file `Makefile.o'. 

我知道include會導致給定的Makefiles在必要時被重建。它是否也嘗試重建當前的Makefile?如果是這樣,我該如何阻止它,如果沒有,那麼爲什麼將「Makefile」添加爲目標?

此外,包含被執行,導致.d文件被重新映射,即使我在命令行上指定目標(例如make clean)。有什麼辦法可以阻止這種情況發生?



# $(call setsuffix,newsuffix,files) 
# Replaces all the suffixes of the given list of files. 
setsuffix = $(foreach file,$2,$(subst $(suffix $(file)),$1,$(file))) 

# $(call twinfile,newdir,newsuffix,oldfile) 
# Turns a path to one file into a path to a corresponding file in a different 
# directory with a different suffix. 
twinfile = $(addprefix $1,$(call setsuffix,$2,$(notdir $3))) 

MAIN = main 

SOURCE_DIR = src/ 
INCLUDE_DIR = include/ 
BUILD_DIR = build/ 

SOURCES = $(wildcard $(SOURCE_DIR)*.cpp) 
OBJECTS = $(call twinfile,$(BUILD_DIR),.o,$(SOURCES)) 
DEPENDENCIES = $(call twinfile,$(BUILD_DIR),.d,$(SOURCES)) 

CXX = g++ 
LIBS = -lpng 
CXXFLAGS = -I $(INCLUDE_DIR) 


.PHONY: all 
all: $(MAIN) 

$(MAIN): $(OBJECTS) 
$(CXX) $(LIBS) $^ -o $(MAIN) 

include $(DEPENDENCIES) 

%.o: $(BUILD_DIR)stamp 
$(CXX) $(CXXFLAGS) -c $(call twinfile,$(SOURCE_DIR),.cpp,[email protected]) -o [email protected] 

$(BUILD_DIR)%.d: $(SOURCE_DIR)%.cpp $(BUILD_DIR)stamp 
@ echo Generate dependencies for $ [email protected]$$$$; \ 
sed 's,\($*\)\.o[ :]*,$(BUILD_DIR)\1.o [email protected] : ,g' [email protected]; \ 
rm -f [email protected]$$$$ 

$(BUILD_DIR)stamp: 
mkdir -p $(BUILD_DIR) 
touch [email protected] 

.PHONY: clean 
clean: 
rm -rf $(BUILD_DIR) 

.PHONY: printvars 
printvars: 
@ echo $(SOURCES) 
@ echo $(OBJECTS) 
@ echo $(DEPENDENCIES) 


回答

9

Make在執行Makefile之前總是會嘗試重新生成Makefile。爲此,make會查找可用於重新創建Makefile的規則。 Make會查找很多隱式規則和其他不明確的方法來(重新)創建Makefile。

在你的情況下,不知何故決定應該使用模式規則%.o: $(BUILD_DIR)/stamp重新創建失敗的Makefile。

爲了防止化妝從改造Makefile中,你可以寫一個規則與空配方:

Makefile: ; 

閱讀化妝手冊中的一章Remaking Makefiles更多的解釋。

關於包含的Makefiles:包含的Makefiles將始終包含在內,無論目標是什麼。如果包含的makefiles缺失(或者比他們的先決條件早),那麼他們將首先被重新創建。這意味着make clean將首先生成.d Makefiles,但只能再次刪除它們。

可以防止包括具體的目標通過在有條件的包木窗指令include

ifneq ($(MAKECMDGOALS),clean) 
include $(DEPENDENCIES) 
endif 

這裏是你的一些修復整個Makefile文件。我標記了我改變某些東西的地方。

# Makefile 

# $(call setsuffix,newsuffix,files) 
# Replaces all the suffixes of the given list of files. 
setsuffix = $(foreach file,$2,$(subst $(suffix $(file)),$1,$(file))) 

# $(call twinfile,newdir,newsuffix,oldfile) 
# Turns a path to one file into a path to a corresponding file in a different 
# directory with a different suffix. 
twinfile = $(addprefix $1/,$(call setsuffix,$2,$(notdir $3))) 

MAIN = main 

SOURCE_DIR = src 
INCLUDE_DIR = include 
BUILD_DIR = build 

SOURCES = $(wildcard $(SOURCE_DIR)/*.cpp) 
OBJECTS = $(call twinfile,$(BUILD_DIR),.o,$(SOURCES)) 
DEPENDENCIES = $(call twinfile,$(BUILD_DIR),.d,$(SOURCES)) 

CXX = g++ 
LIBS = -lpng 
CXXFLAGS = -I $(INCLUDE_DIR) 


.PHONY: all 
all: $(MAIN) 

$(MAIN): $(OBJECTS) 
    $(CXX) $(LIBS) $^ -o $(MAIN) 

# -------> only include if goal is not clean <--------- 
ifneq ($(MAKECMDGOALS),clean) 
include $(DEPENDENCIES) 
endif 

# ---------> fixed this target <-------------- 
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(BUILD_DIR)/stamp 
    $(CXX) $(CXXFLAGS) -c $(call twinfile,$(SOURCE_DIR),.cpp,[email protected]) -o [email protected] 

# ---------> and this target <--------------- 
$(BUILD_DIR)/%.d: $(SOURCE_DIR)/%.cpp $(BUILD_DIR)/stamp 
    @ echo Generate dependencies for [email protected]; 
    @set -e; rm -f [email protected]; \ 
    $(CC) -M $(CPPFLAGS) $< > [email protected]$$$$; \ 
    sed 's,\($*\)\.o[ :]*,$(BUILD_DIR)\1.o [email protected] : ,g' < [email protected]$$$$ > [email protected]; \ 
    rm -f [email protected]$$$$ 

$(BUILD_DIR)/stamp: 
    mkdir -p $(BUILD_DIR) 
    touch [email protected] 

.PHONY: clean 
clean: 
    rm -rf $(BUILD_DIR) 

.PHONY: printvars 
printvars: 
    @ echo $(SOURCES) 
    @ echo $(OBJECTS) 
    @ echo $(DEPENDENCIES) 
+1

其他建議:可以通過在`ifneq包裹`include`(,$(過濾得一乾二淨,$(MAKECMDGOALS))可以防止`.d`文件 「使清潔」 翻拍`HTTP ://www.gnu.org/software/make/manual/make.html#Goals – slowdog 2010-11-25 01:23:44

相關問題