2013-05-24 16 views
9

私はmakefileをセットアップする方法を学んでおり、問題が発生しました。これを実証するために、ソースファイルmain.mtest.mからなる単純な "プロジェクト"を作成しました。Makefileは常にファイルを再コンパイルする

私はこれらのファイルを(代が変わっている場合のみ)、コンパイル、および(ここではbuild/)をどこか別の場所にオブジェクトファイルを保存するために作るのセットアップしようとしています

私のMakefile:

OBJ = ./build 

SOURCES=main.m test.m 
OBJECTS=$(addprefix $(OBJ)/,$(SOURCES:.m=.o)) 
EXECUTABLE=test 

all: $(EXECUTABLE) 

$(EXECUTABLE): $(OBJECTS) 
     gcc $(OBJECTS) -o $(EXECUTABLE) 

$(OBJECTS): $(OBJ)/%.o: %.m build/ 
     gcc -c $< -o [email protected] 

build/: 
     mkdir build 

私は実行それ(だけMakefileと、カレントディレクトリにあるソースとの)最初の時間のためにそれは私がそれを行うことを期待します:

しかし
gcc -c main.m -o build/main.o 
gcc -c test.m -o build/test.o 
gcc ./build/main.o ./build/test.o -o test 

私はを実行した場合もう一度:

gcc -c main.m -o build/main.o 
gcc ./build/main.o ./build/test.o -o test 

どうしたのですか?私は "良い" Makefileを作成することを学んでいるので、Makefileに他のエラーがあることにも気づくでしょう。

編集:私はmake -dから発見何

Finished prerequisites of target file `build/main.o'. 
Prerequisite `main.m' is older than target `build/main.o'. 
Prerequisite `build/' is older than target `build/main.o'. 
No need to remake target `build/main.o'. 

Finished prerequisites of target file `build/test.o'. 
Prerequisite `test.m' is older than target `build/test.o'. 
Prerequisite `build/' is newer than target `build/test.o'. 
Must remake target `build/test.o'. 
+0

私はあなただけで、 '/'にbuild' 'に接続したくないと思いますいくつかの場所。ここでそれを試してみましょう。 'make -d'を使って' make 'が何を構築するかを決定する方法を知ることができます。 –

+0

ありがとうございます。しかし、 'make -d'ルートは、927行の情報を出力するので、しばらく時間がかかるでしょう:) – varesa

+0

posisbleと同じくらい多くの暗黙のルールを取り除くことで、それを静めることができます。私は単純なテストプロジェクトでメイクファイルを試しましたが、期待どおりに動作するように見えました。つまり、2回目の試合では、私はちょうど 'make: 'all'のために何もするつもりはない。 –

答えて

9

あなたmake -d出力はmakeは、ビルドディレクトリが更新されていると考えていることを示しており、そのため、ファイルのニーズ再建される。

あなたのビルドシステムの一部またはファイルシステム内の何らかの操作によって、そのディレクトリのタイムスタンプが更新されて更新される可能性があります。

あなたはそのルールに|を追加することにより、buildため、唯一の前提条件を行うことで問題を解決することができます:それは何もしていなかったので、

$(OBJECTS): $(OBJ)/%.o: %.m | build 

を私は、あまりにも/を削除しました。

あなたが尋ねたので、他のいくつかの社説ノートは:

  1. cleanターゲットを追加します。何かのように:あなたはOBJを設定すると

    clean: 
        rm -rf $(EXECUTABLE) $(OBJ) 
    
  2. あなたは./必要はありません。ちょうどOBJ = buildで十分です。

  3. 上記のようにをbuildにする必要はありません。とにかくそれを言及してはならないので、それは本当に重要ではありません。あなたがそれを見るところでに$(OBJ)と返信してください。

  4. mkdirディレクトリがすでに存在する場合は失敗します。おそらく-と、そのコマンドの前に付ける必要があります:私は上記の#3で述べた$(OBJ)との交換を行ってきた

    $(OBJ): 
        -mkdir $(OBJ) 
    

    注意。

  5. 依存関係の自動生成は非常に役に立ちます。あなたのプロジェクトは本当に必要なだけの大きさではありませんが、追加するのは簡単です。あなたはいくつかのことをする必要があります。まず、適切な依存関係ファイル名を取得:

    DEPFILES = $(addprefix $(OBJ)/,$(SOURCES:.m=.d)) 
    

    その後-MMDフラグ追加することによって、それらを生成するコンパイラを得る:

    gcc -MMD -c $< -o [email protected] 
    

    最後に、彼らが利用できるなら、あなたのメイクファイルに含める、ことにより、あなたのメイクファイルの末尾に行を追加:

    -include $(DEPFILES) 
    
+0

それは基本的に 'ビルド/'にオブジェクトファイルを作成してそれを更新し強制的に再コンパイルする 'make'でしたか? – varesa

+0

そうそうです。私のマシンでは起こりませんが、その動作はファイルシステムに依存する可能性があります。 –

+0

また、マウントパラメータと何か関係があります。主に、タイムスタンプを更新する必要があるときに通知します。 – varesa

関連する問題