2016-10-20 10 views
0

私はそれは少し下のメイクファイルのように見える、いくつかのCソースファイルをコンパイルするためのMakefileを持っており、異なるビルドディレクトリに出力を置く:暗黙のルールがmakefileによってスキップされましたか?

OBJDIR=/home/test/alpha 
SRCDIR=/home/test/beta 
# make variable will be exanded when used (and not at declaration) 
OBJECTS:= $(addprefix $(OBJDIR), $(notdir $(patsubst %.c,%.o,$(wildcard $(SRCDIR)/*.c)))) 

SOURCES:=$(wildcard $(SRCDIR)/*.c)) 

.PHONY: copySourcesOver linkSources sharedLibrary 
copySourcesOver: $(SOURCES) 
cp $(SOURCES) $(OBJDIR)/ 

# pattern 
$(OBJECTS)/%.o : $(OBJECTS)/%.c 
gcc -fPIC $< -o [email protected] 

linkSources: $(OBJECTS) 
gcc -shared -o libshared.so [email protected] 

sharedLibrary: copySourcesOver \ 
linkSources \ 

だから何が起こっているが、私は、ターゲットを実行するとことです。

make sharedLibrary 

$(OBJECTS)のルールはありません。面白いのは、このターゲットをもう一度makefileエラーが出ないようにするときです。共有ライブラリを取得します。

私は少しの研究を行いましたが、MakefileがPHONYターゲットの暗黙のルールを拡張しないことを知りました。そのため、をPHONYターゲットから通常のファイルに変更しました。しかし残念ながら、それは問題を解決しません。

パターンは、私がmake sharedLibrary

+1

以下の答えが何を指摘しているかとは別に、複数のジョブ( '-j')を使用するとmakefileも壊れます。前提条件が順番に実行されるという保証はありません。一方の前提条件が他の条件に依存する場合は* makefile *でこれを表現してください。 – user657267

+0

良い点。すべての依存関係を追加します – Bionix1441

+1

あなたのルールの中には、ターゲットを依存関係としてターゲットや依存関係として記述していないものがあるため、ルールを実行する必要があるかどうかを 'make'がチェックして正しく動作することは期待できません。 – reinierpost

答えて

2

を実行して二回目は2段階に分けて実行してくださいのみ実行され、なぜ私は表示されません。最初のフェーズでは、どのターゲットが期限切れで更新が必要かをチェックします。第2段階では、ターゲットを更新するコマンドを実行します。つまり、ソースファイルを実際にコピーする前に、オブジェクトファイルが最新であることをチェックします。

オブジェクトファイルが最新であることを確認して判断した後、(更新された)ソースファイルを$(OBJDIR)にコピーします。

この件に関するいくつかの良い読書がありますin the docs

+0

だから私はドキュメントを読んだ後に結論づけることができます:OBJDIR =/home/test/alphaとSRCDIR =/home/test/betaの右側に遅延拡張があります。 $(OBJECTS)はmakefileの最初の実行時には展開されませんが、最初の実行時には拡張されません。 – Bionix1441

+1

鍵情報は最後に 'Rule definition'です。ルール 'sharedLibrary:copySourcesOver linkSources'が直ちにチェックされます。 'linkSources'をチェックすると、ファイルが最新であるため(更新されたファイルはまだコピーされていないことに注意してください)、' copySourcesOver'のチェックの結果、更新されたソースファイル。 –

1

引用:

# pattern 
$(OBJECTS)/%.o : $(OBJECTS)/%.c 
    gcc -fPIC $< -o [email protected] 

OBJECTSは、複数の単語を含む変数ではなく、単一パス成分であるので、このルールは無意味です。さらに、.cソースはオブジェクトと同じディレクトリにありません(この点全体)。

私はあなたが欲しい疑う:

$(OBJDIR)/%.o : $(SRCDIR)/%.c 

は、左のパターンは、あなたが$(OBJDIR)に自分の$(SRCDIR)一部を書き換えることにより、OBJECTSで計算されているオブジェクトファイルのパターンのいずれかと一致します。

ちなみに、このパターンルールが逆書き換えを簡単に実行する方法を参照してください。左の試合は、右の前提条件の.cに変換されます。ルールがnotdirまたはaddprefixを使用しない方法を参照してください。 OBJECTSを計算するときに同じことを(逆に)行うことができます。 notdiraddprefixを削除し、各パスを単一のpatsubstに変換します。

また、私は繰り返すことを避けるだろうwildcard。最初にSOURCESを取得し、ソースからOBJECTSを計算します。

最後に、オブジェクトディレクトリが存在しないときに新しくチェックアウトするとどうなりますか?そこにはmkdir -pが必要です。gcc ... -o foo/bar.oは、fooディレクトリを作成しません。

+0

最初のターゲットcopySourcesOverは、ソースをオブジェクトディレクトリにコピーします。はい、私は静的パターンルール$(OBJECTS)に変更しました:%。o:%。c – Bionix1441

+0

オブジェクトディレクトリがまったく存在しない状況でMakefileを実行できるかどうか – Kaz

+0

逆の書き換えは何ですか? – Bionix1441

関連する問題