2010-11-24 32 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'. 

私が知っているのは、必要に応じて、特定のMakefileを再構築することです。また、現在のMakefileを再構築しようとしていますか?もしそうなら、私はそれをやめ、もしそうでなければ、 "Makefile"がターゲットとして追加されるのはなぜですか?

また、make cleanのようにコマンドラインでターゲットを指定しても、.dファイルが再作成されるため、インクルードが実行されます。それを止める方法はありますか?



# $(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について:インクルード対象に関係なく、常にMakefileがインクルードされます。インクルードされたメイクファイルがない場合(または前提条件より古い場合)、最初に(再)作成されます。これは、make cleanが最初に.d Makefileを生成し、それらを再度削除することを意味します。

あなたは条件付きでincludeディレクティブwrapingで具体的な目標のために含むのを防ぐことができます。ここでは

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

追加提案: "きれいにする" で '.d'ファイルのリメイクは、$(フィルタアウトクリーン、$(MAKECMDGOALS))' HTTP、(ifneq 'で' include'をラップすることによって防止することができます://www.gnu.org/software/make/manual/make.html#Goals – slowdog

+0

恐ろしいです!これらのターゲットを変更すると、ディレクトリ変数の末尾にスラッシュを残しておく方がよいでしょうか? – Jol

+0

@slowdog。ありがとう。私はそれを私の答えに加えました。 – lesmana

関連する問題