makefileにターゲットを再構築させる方法


184

ビルドしてから別のメイクファイルを呼び出すメイクファイルがあります。このmakefileは、実際には変更されない作業を行うより多くのmakefileを呼び出すため、したがって、プロジェクトが構築され、最新のものであると常に考えています。

dnetdev11 ~ # make
make: `release' is up to date.

makefileでターゲットを再構築するにはどうすればよいですか?

clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean


build = svn up ~/xxx                                                       \
        $(clean)                                                                \
        ~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace        \
        $(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1)                    \


release:
        $(build )

debug:
        $(build DEBUG=1)

clean:
        $(clean)

install:
        cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
        cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib

注:無実を保護するために削除された名前

編集:最終修正バージョン:

clean = $(MAKE) -f xxx_compile.workspace.mak clean;


build = svn up;                                         \
        $(clean)                                        \
        ./cbp2mak/cbp2mak -C . xxx_compile.workspace;   \
        $(MAKE) -f xxx_compile.workspace.mak    $(1);   \


.PHONY: release debug clean install

release:
        $(call build,)

debug:
        $(call build,DEBUG=1)

clean:
        $(clean)

install:
        cp ./source/xxx_utillity/release/xxx_util /usr/bin
        cp ./dlls/Release/xxxcore.so /usr/lib

Lodle、これは頻繁に訪れる質問なので、質問をより現代的なものに編集しますか?(それは.PHONYあなたの唯一の問題ではなかったようであり、あなたは実際に解決策を質問に編集することになっている、または少なくとももうそうではありません。)
Keith M

回答:


23

1つ以上のターゲットを偽物として宣言できます。

偽のターゲットは、実際にはファイルの名前ではないターゲットです。むしろ、明示的なリクエストを行ったときに実行されるレシピの単なる名前です。偽のターゲットを使用する理由は2つあります。同じ名前のファイルとの競合を回避することと、パフォーマンスを向上させることです。

...

偽のターゲットは、実際のターゲットファイルの前提条件であってはなりません。もしそうなら、そのレシピはmakeがそのファイルを更新しようとするたびに実行されます。偽のターゲットが実際のターゲットの前提条件になることがない限り、偽のターゲットが指定された目標である場合にのみ、偽のターゲットのレシピが実行されます


68
この答えは、「受け入れられ」、非常に「賛成」されているものの、実は目立たないものです。最初に、「ターゲットを偽物であると宣言する」と表示されますが、「偽のターゲットは実際にはファイルの名前ではありません」と表示されます。まあ、ターゲットがファイルの場合、それは答えの矛盾です。第二に、それは「偽のターゲットは本当の前提条件であってはならない」と言っています-そうですね 元の質問は、そうであるかそうでないかを特定していませんでした。正しい答えは、である、ない宣言するあなたの偽であることを目標に、ではなく、追加の偽の目標を宣言した後、その上、あなたが再建したい目標を依存しています。
Mark Galeck 2014年

2
@MarkGaleck。答えが「偽のターゲットは実際にはファイルの名前ではないものである」と述べている場合、それはgcc makeマニュアルから直接引用しています。それは完全に正しいです。
drlolly

"ターゲット"は、:作成したい最終結果(バイナリファイルなど)だけでなく、コロンの左側のテキストを指すMake用語です。質問には、releasedebugclean、およびinstallメイクターゲット、ではないxxx_utilか、xxxcore.soまたは何か他のもの。
キースM

728

-B長い形式がであるmakeへの切り替えは--always-makemakeタイムスタンプを無視して指定されたターゲットを作成するように指示します。これはmakeを使用する目的に反するかもしれませんが、それが必要な場合もあります。


4
@MarkKCowan完全に同意します!このオプションはまさに私が探していたものであり、Daveが示唆するような回避策のハックではありません。
Maarten Bamelis

8
このアプローチの注意点は、多くのことを構築するだけであるということです。特にautotoolsを使用して、configureを再実行しているのを見ました。LD_PRELOADベースのソリューションを構築できることを願っています!!
vrdhn 2017年

はい、それはあなたがしたくないファイルを書き換えることもできます!依存関係に表示され、再構築されて上書きされるグローバルシステムライブラリなど
Julio Guerra '20

18

Sunのマニュアルに記載されていたトリックの1つmakeは、(存在しない)ターゲット '.FORCE'を使用することです。これを行うには、以下を含むforce.mkファイルを作成します。

.FORCE:
$(FORCE_DEPS): .FORCE

次に、既存のmakefileがと呼ばれているとするとmakefile、次のコマンドを実行できます。

make FORCE_DEPS=release -f force.mk -f makefile release

以来.FORCE存在していない、それに依存して何が日付と再構築外となります。

これはすべてのどのバージョンでも機能しmakeます。Linuxでは、GNU Makeがあるため、前述のように.PHONYターゲットを使用できます。

makeリリースが最新であると見なされる理由についても検討する価値があります。これはtouch release、実行されたコマンドの中にコマンドがあるためと考えられます。これは、「release」というファイルまたはディレクトリが存在し、依存関係がないため最新であるためである可能性があります。次に、実際の理由があります...


14

他の誰かが間違いなく正しい.PHONYを提案しました。.PHONYは、入力と出力の間の日付比較が無効であるルールに使用する必要があります。フォームのターゲットがないoutput: inputため、すべてに.PHONYを使用する必要があります。

そうは言っても、おそらく、さまざまなファイル名に対してmakefileの先頭にいくつかの変数を定義し、入力セクションと出力セクションの両方を持つ実際のmakeルールを定義して、makeの利点を使用できるようにする必要があります。つまり、実際にコンパイルするだけです。コミールするために必要なもの!

編集:例を追加しました。未テストですが、これが.PHONYの方法です

.PHONY: clean    
clean:
    $(clean)

1
まあ、例を見せていただければいいですね。Atm imは、ダムを機能させるためにそれをハッキングするだけです:P
Lodle

1
.PHONYターゲットの場所は関係ありません。Makefile。のどこにでも配置できます。
エイドリアンW

5

私が正しく思い出した場合、「make」はタイムスタンプ(ファイル変更時間)を使用して、ターゲットが最新かどうかを判断します。強制的に再構築する一般的な方法は、 'touch'コマンドを使用してタイムスタンプを更新することです。Makefileで 'touch'を呼び出して、ターゲットの1つ(おそらくそれらのサブMakefileの1つ)のタイムスタンプを更新してみてください。これにより、Makeはそのコマンドを強制的に実行します。


5

この単純な手法により、強制が不要な場合にメイクファイルが正常に機能するようになります。makefileの最後にforceという新しいターゲットを作成します。力の目標は、あなたのデフォルトのターゲットが依存するファイルを触れます。以下の例では、touch myprogram.cppを追加していますmakeへの再帰呼び出しも追加しました。これにより、make forceと入力するたびにデフォルトのターゲットが作成されます。

yourProgram: yourProgram.cpp
       g++ -o yourProgram yourProgram.cpp 

force:
       touch yourProgram.cpp
       make

makeMakefile内では絶対に使用しないでください。$(MAKE)代わりに使用してください。
ベンジャミンクロフォードCtrl-Alt-Tut

3

私はこれを試しました、そしてそれは私のために働きました

これらの行をMakefileに追加します

clean:
    rm *.o output

new: clean
    $(MAKE)     #use variable $(MAKE) instead of make to get recursive make calls

保存して今すぐ電話

make new 

そしてすべてを再コンパイルします

どうした?

1)「新規」コールはクリーンです。'clean' do 'rm'は、拡張子が '.o'のオブジェクトファイルをすべて削除します。

2)「new」は「make」を呼び出します。「make」は、「。o」ファイルがないことを確認するため、すべての「.o」を再度作成します。次に、リンカはすべての.oファイルを1つの実行可能出力にリンクします。

幸運を


1
以下のためのレシピにnew活用$(MAKE)よりmake
バジーレStarynkevitch

1

Millerの再帰的な有害性の考慮によると、呼び出しを避ける必要があります$(MAKE)!あなたが示す場合、これは無害です。これは、実際にはMakefileではなく、単なるラッパースクリプトであり、Shellで記述されている可能性もあるからです。しかし、より深い再帰レベルでそのように続けると言うので、おそらくその目を見張るようなエッセイに示されている問題に遭遇したことでしょう。

もちろん、GNUでは回避するのが面倒です。そして、彼らはこの問題を認識していますが、それは文書化された方法です。

OTOH、makeppはこの問題の解決策として作成されました。makefileはディレクトリレベルで作成できますが、それらはすべて一緒にプロジェクトの完全なビューに描画されます。

ただし、従来のメイクファイルは再帰的に書き込まれます。したがって$(MAKE)、サブリクエストをメインのmakeppプロセスに戻す以外に何もしない回避策があります。サブメイク間で冗長な、またはさらに悪いことに、矛盾することを行う場合にのみ、リクエストする必要があります--traditional-recursive-make(もちろん、makeppのこの利点を壊します)。私はあなたの他のメイクファイルを知りませんが、それらがきちんと書かれていれば、makeppで必要な再構築が自動的に行われ、ここで他の人が提案するハックは必要ありません。


質問に回答しませんでした。要点に正接し、回答ではなくコメントにする必要があります。
flungo

多分私は十分にはっきりしていませんでした。makeppこの全体のラッパーメイクファイルは必要ありません。正確な依存関係(の後にリストされているものだけでなく、すべての依存関係)を知ることにより:、必要なときに常に再構築されます。
Daniel


0

それは実際にはターゲットが何であるかに依存します。それが偽のターゲットである場合(つまり、ターゲットがファイルに関連していない場合)、. PHONYとして宣言する必要があります。

ただし、ターゲットが偽のターゲットではなく、何らかの理由で再構築する場合(たとえば、__ TIME__プリプロセスマクロを使用する場合)は、ここの回答で説明されているFORCEスキームを使用する必要があります。



0

それはすでに言及されましたが、使用に追加できると思いました touch

あなたの場合はtouch、すべてのソースファイルをコンパイルするために、touchコマンドは、システム時刻にファイルのタイムスタンプを変更するtouchコマンドが実行されました。

ソースファイルのタイムスタンプはmake、ファイルが変更されたことを「知る」ために使用されるものであり、再コンパイルする必要があります。

例:プロジェクトがC ++プロジェクトである場合はtouch *.cpp、実行してからmake再度実行すると、プロジェクト全体が再コンパイルされます。


0

アベニエが指摘したように、GNU makeマニュアルには、「偽の」ターゲットを使用してターゲットの再構築を強制する推奨ソリューションがあります。

clean: FORCE
        rm $(objects)
FORCE: ; 

これは、他の依存関係に関係なく、クリーンに実行されます。

マニュアルのソリューションにセミコロンを追加しました。それ以外の場合は、空の行が必要です。


-1

私のLinuxシステム(Centos 6.2)では、ルールが実際にターゲットに一致するファイルを作成する場合、ターゲット.PHONYの宣言とFORCEへの偽の依存関係の作成には大きな違いがあります。ファイルを毎回再生成する必要がある場合、ファイルに対する偽の依存関係のFORCEと、偽の依存関係の.PHONYの両方が必要でした。

違う:

date > $@

正しい:

FORCE
    date > $@
FORCE:
    .PHONY: FORCE

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.