- 締切済み
GNU make終了時にコマンドを実行できますか?
GNU make 4.x(4.1か4.2)を使ってMakefileを実行したとき、そのMakefileが成功しても失敗しても、make終了時に何かを実行させる方法は用意されていますか? "make && コマンド"や"make || コマンド"などの複合コマンドのほか、シェルスクリプト内で"make"とコマンドを連続実行するという方法は除きます。あくまでも"make"単体で実行するものとします。 実際そういうことをしたいというのではなく、"make"実行後、Makefile中で生成した一部の中間ファイルが勝手に削除されるという謎の現象が発生しており、その原因を探りたいです。 Makefile中の実行コマンドにわざとエラーを起こすようなコマンドを入れてみても(例えば存在しない"hogehoge"のようなコマンド)、そのエラーが表示された直後に、"rm XXXX YYYY"(XXXXとYYYYはMakefile内部で生成したファイル名)のようなコマンドが表示されて、実際にそのファイルは生成しているはずなのに消えてしまっています。 上記のエラーを起こすコマンドの前に"ls -l ディレクトリ名"を実行するようにして、エラーを起こす直前に中間ファイルが存在することは確認できています。しかしその後、勝手に"rm"が実行されてそのファイルは消されてしまいます。 よろしくお願いします。
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- Ultra-Hetare
- ベストアンサー率38% (204/526)
hogehogeではなく、ちゃんと動作する(実害のない)コマンドを 実行させて、違いを確認するということは実施されましたか?
- _kappe_
- ベストアンサー率68% (1581/2304)
質問内容への直接の回答ではありませんが、.DELETE_ON_ERRORが使われているということはありませんか。 .DELETE_ON_ERRORがあると失敗時に指定されたファイルを消します。 https://www.gnu.org/software/make/manual/html_node/Special-Targets.html
お礼
コメントありがとうございます。 .DELETE_ON_ERRORですか、こういう情報を待っていました!初めて知りました。 しかしながら、今回のケースではこれは使っていないです(ここで初めて知ったくらいですから、使ったことはありません)。 また、今回のMakefileは一からフルスクラッチで書いたので、知らない間にどこかで使われていた、という可能性も考えにくいです。 それに、エラーが発生したときだけでなく、エラー無く正常終了したときにも同じrmコマンドがmake終了時に実行されるので、.DELETE_ON_ERRORのように条件付き実行ではなさそうでした。
補足
その後の調査で分かったことは、makeが中間ファイルと判断したファイルは終了時に削除することがあるということらしいです。 例えば、 %.o : %.pp のようなルールを作ると、makeは既定ルールを検索して、 %.pp --> %.c --> %oと生成する方法を探し出すが、このとき%.cの生成はmakeが勝手に推測したルールなのでmake終了時に消すようです。 https://www.gnu.org/software/make/manual/html_node/Chained-Rules.html ただ、私のケースではMakefile中で明示的に指定したターゲットファイルが削除されているのでこれには合致しないように見えるのですが、"Removing intermediate files"をキーワードとして検索すると同じような質問が見つかりました。そして、'.PRECIOUS'疑似ターゲットを使うことで回避できることが分かりました。 マニュアルはちゃんと読むべきでした。
- asciiz
- ベストアンサー率70% (6803/9674)
make は仕様通りの動作をしていると思いますよ。 どういうmakefileを書いたか見せてもらわないと分かりませんけど。 あるいは、「コマンドでエラーが発生した」あるいは「エラー表示があった」としても、そのコマンドの戻り値自体が正常終了(0)を表しているので、次の行に進んでしまうのかもしれません。 「echo $?」コマンドを入れて、エラー時に0以外が返っているか見てみましょう。 -- 無条件にrmコマンドが実行されるのが不都合であれば、rmコマンドは更新ブロックから外して、次のような記述を入れるという手もあります。 clean: rm main.o sub1.o sub2.o make実行後、中間ファイルは要らないな、と思ったときに、 $ make clean と実行することで、そのrmコマンドを実行して綺麗にできます。 ※clean というファイルが存在するとそれを更新しようとしてしまうので注意
お礼
お返事ありがとうございます。 Makefileを示していないこともあり、質問の意図をうまく伝えられていないように思います。すみません。 エラーがあっても無くてもmake終了時に、何故かrmコマンドが発行されていて、Makeの途中で作られる一部のファイルが削除されてしまいます。全部の中間ファイルが削除される訳ではありません。 (ちなみに、今回はC/C++言語のコンパイルではなく、ちょっとしたファイル変換のような処理です。中間ファイルを色々と作って処理を進めるので、make一発で処理したいのでMakefileという方法を採っています) 今回作成中のMakefileにあるすべてのrmコマンドを取り除いても(cleanターゲットのrmも消しても)、make終了時、成功/エラーどちらでも最後に謎のrmが実行されてしまいます。 擬似コードですが、例えば'all'をトップのターゲットとして、 all : $(TARGETS) ls -l $(WORK_DIR) # <-- 終了前に問題のワークディレクトリの中身を確認 hogehoge # <-- わざとエラーを起こす $(TARGETS) : (色々な依存ファイル) (ファイルを処理するコマンド、いろいろ) のようなMakefileを使って、"make all"するとします。 $(TARGETS)のメイクがすべてうまく完了したら、続けてallターゲット中に書いたlsとhogehogeコマンドが実行されますが、 lsが実行される段階ではWORK_DIR内にちゃんとまだ中間ファイルが残っています。 その後hogehogeを実行しようとするも、そんなコマンドはないのでエラーでmakeはエラーで終了するのですが、その後に謎の"rm (WORK_DIR内のファイル名)"というコマンドが表示されて実行されているようです。実際、make終了後そのディレクトリにファイルはありません。Makefileファイル中のrmをすべて取り除いても、rmが最後に実行されてしまいます。なので、make終了時に自動的に実行する仕組みがどこかで働いているのかな?という推測から質問させていただきました。 何かお気づきの点がありましたら、引き続きよろしくお願いします。
補足
補足ですが、最後に実行されるrmコマンドは、自分で書いたMakefileには含まれない内容のものです。なので、自分で書いたrmコマンドが意図せず(=私の勘違いでルールが成立して)実行されているという訳では無さそうなのです。 しかし、最後に実行される謎のrmコマンドが削除してしまうファイルは、実際にMakefile中で使っているファイル名ではあります。そのファイルを狙い撃ちするかのように、rmコマンドが実行されます。(返信の方にも書きましたが)Makefileからすべてのrmコマンドを削除した状態でもそうなってしまいます。しかし、何故かMakefile中で扱う中間ファイルすべてが対象としてrmされる訳でもありません。
お礼
ありがとうございます。 質問の中で、 > Makefile中の実行コマンドにわざとエラーを起こすようなコマンドを入れてみても と書いてあるように、わざとエラーを起こさせているだけで、エラーが起きる場合と起きない場合で同じ問題が出ていることを確認しています。本来、「hogehoge」は不要なものです。 わざとhogehogeを入れた理由は、makeで実行されるコマンドが途中で終了していても、最後に勝手にrmが実行されるのだろうか?という疑問があったからです。言い換えると、自分で書いたルール・コマンドでない「何か」が動いているのか?を調べるためでした。