2010-11-24 78 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

相关问题