• 締切済み

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"が実行されてそのファイルは消されてしまいます。 よろしくお願いします。

みんなの回答

回答No.3

hogehogeではなく、ちゃんと動作する(実害のない)コマンドを 実行させて、違いを確認するということは実施されましたか?

haniriito2019
質問者

お礼

ありがとうございます。 質問の中で、 > Makefile中の実行コマンドにわざとエラーを起こすようなコマンドを入れてみても と書いてあるように、わざとエラーを起こさせているだけで、エラーが起きる場合と起きない場合で同じ問題が出ていることを確認しています。本来、「hogehoge」は不要なものです。 わざとhogehogeを入れた理由は、makeで実行されるコマンドが途中で終了していても、最後に勝手にrmが実行されるのだろうか?という疑問があったからです。言い換えると、自分で書いたルール・コマンドでない「何か」が動いているのか?を調べるためでした。

  • _kappe_
  • ベストアンサー率68% (1520/2213)
回答No.2

質問内容への直接の回答ではありませんが、.DELETE_ON_ERRORが使われているということはありませんか。 .DELETE_ON_ERRORがあると失敗時に指定されたファイルを消します。 https://www.gnu.org/software/make/manual/html_node/Special-Targets.html

haniriito2019
質問者

お礼

コメントありがとうございます。 .DELETE_ON_ERRORですか、こういう情報を待っていました!初めて知りました。 しかしながら、今回のケースではこれは使っていないです(ここで初めて知ったくらいですから、使ったことはありません)。 また、今回のMakefileは一からフルスクラッチで書いたので、知らない間にどこかで使われていた、という可能性も考えにくいです。 それに、エラーが発生したときだけでなく、エラー無く正常終了したときにも同じrmコマンドがmake終了時に実行されるので、.DELETE_ON_ERRORのように条件付き実行ではなさそうでした。

haniriito2019
質問者

補足

その後の調査で分かったことは、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% (6623/9386)
回答No.1

make は仕様通りの動作をしていると思いますよ。 どういうmakefileを書いたか見せてもらわないと分かりませんけど。 あるいは、「コマンドでエラーが発生した」あるいは「エラー表示があった」としても、そのコマンドの戻り値自体が正常終了(0)を表しているので、次の行に進んでしまうのかもしれません。 「echo $?」コマンドを入れて、エラー時に0以外が返っているか見てみましょう。 -- 無条件にrmコマンドが実行されるのが不都合であれば、rmコマンドは更新ブロックから外して、次のような記述を入れるという手もあります。 clean: rm main.o sub1.o sub2.o make実行後、中間ファイルは要らないな、と思ったときに、 $ make clean と実行することで、そのrmコマンドを実行して綺麗にできます。 ※clean というファイルが存在するとそれを更新しようとしてしまうので注意

haniriito2019
質問者

お礼

お返事ありがとうございます。 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終了時に自動的に実行する仕組みがどこかで働いているのかな?という推測から質問させていただきました。 何かお気づきの点がありましたら、引き続きよろしくお願いします。

haniriito2019
質問者

補足

補足ですが、最後に実行されるrmコマンドは、自分で書いたMakefileには含まれない内容のものです。なので、自分で書いたrmコマンドが意図せず(=私の勘違いでルールが成立して)実行されているという訳では無さそうなのです。 しかし、最後に実行される謎のrmコマンドが削除してしまうファイルは、実際にMakefile中で使っているファイル名ではあります。そのファイルを狙い撃ちするかのように、rmコマンドが実行されます。(返信の方にも書きましたが)Makefileからすべてのrmコマンドを削除した状態でもそうなってしまいます。しかし、何故かMakefile中で扱う中間ファイルすべてが対象としてrmされる訳でもありません。

関連するQ&A

  • Cygwinでmakeコマンドが使えない(Vista)

    今までFedora-Linuxで使っていたプログラムをWindows上で実行するために、VistaにCygwinをインストールし、使い始めていることろです。 Makefileを使いコンパイルをするため [make]や[make -f Makefile]などをコンソールに入力しても、 bash: make: command not found が出てしまいます・・・。これを解決したいのです。 これは、Linux上でいつも行っていた操作と全く同じです。 Cygwin用にMakefileを書き換える必要がある、何かのツールをインストールする必要がある、makeに代わる何かのコマンドが存在する・・・ など、あるのでしょうか?

  • Cygwinで、makeコマンドが使えない(Vista)

    今までFedora-Linuxで使っていたプログラムをWindows上で実行するために、VistaにCygwinをインストールし、使い始めていることろです。 Makefileを使いコンパイルをするため [make]や[make -f Makefile]などをコンソールに入力しても、 bash: make: command not found が出てしまいます・・・。これを解決したいのです。 これは、Linux上でいつも行っていた操作と全く同じです。 Cygwin用にMakefileを書き換える必要がある、何かのツールをインストールする必要がある、makeに代わる何かのコマンドが存在する・・・ など、あるのでしょうか?

  • gnu make empty target

    Managing Projects with GNU Make, 3rd Editionを読んでいます。 p.15 Empty targetについてのサンプルでエラーが出ます。 Makefileは以下のとおりです。 ----- prog: size prog.o gcc $(LDFLAGS) -o $@ $^ prog.o: prog.c gcc -c $^ size: prog.o size $^ touch size ----- make prog と実行すると以下のエラーとなります。 ----- gcc -c prog.c size prog.o text data bss dec hex filename 152 0 0 152 98 prog.o touch size gcc -o prog size prog.o size: file not recognized: File truncated make: *** [prog] Error 1 ----- 自分なりの理解では、sizeという空ファイルを作り、そのタイムスタンプをtouchで更新することにより、progをmakeすることができるということだと思います。 ただ、最後に gcc $(LDFLAGS) -o $@ $^ をする時に$^に空ファイルsizeが含まれていて、そのため size: file not recognized: File truncated というエラーを出しているように思います。 そもそものサンプルMakefileが間違っているのでしょうか? あるいはどこかを修正すれば、Empty targetというのが使い物になるのでしょうか?

  • makeというコマンドに関する質問

    おちゅーしゃという2chブラウザをturboLinuxにインストールしようと思うのですが、Makeするところがわかりません。 makeというコマンド事は調べたのですが、「make」とだけ打って実行すれば、makeできると書いてあったのでochusha-0.5.8.2というディレクトリに移動して実行してみた所 make: *** ターゲットが指定されておらず、makefile も見つかりません。中止。 と表示されました。 他にも色々な事をやってみましたがどれも失敗でした 誰かMakeのやり方をしっている人が居たら教えてください

  • Windows環境へのmakeについて

    Windowsの開発環境でmakeを使用したいと思います。シェルでフォルダを選んでmakeコマンドを投入するとmakefileの指示に従ってそのフォルダのソースファイルなどを集めて実行ファイルを作成するところまでやってくれるというものです。 Linuxはmakeコマンドが当然ながら普通に利用できるのでその方向に沿ってシェルに依存したmakefileを作成すると思います。Windowsの場合は基本はmakeコマンドがないので、別途、取り寄せるのだと思います。 今の状態で、Windowsのパワーシェルでwhich make -a とすると、Rtools, bcc55, Gow(Gnu on Windows)のmake.exeが出てきます。適切なmakeが最初に呼ばれるように環境を編集してあとはmakefileを編集すればいいということなのでしょうか。Windowsにはnmake, cmakeなどいろんなものもありますが。コンパイラはgfortranとかgccなどのGNUのコンパイラで、これはシェルからコンパイルできるようになっています。Visual studio系はすぐには使いません。 Windowsのシェルでmakeを利用する手順を教えて頂きたいと思います。よろしくお願いします。

  • makeコマンドについて

    こんにちは、 CentOS4.0に、Snortをインストールしようと思い、下記のように 解凍し、インストールを行ったのですが、 $ tar -zxvf snort-2.6.0.tar.gz $ cd snort-2.6.0 $ ./configure $ make # make install $ ./configure までは上手くいったのですが、 $ make のコマンドを実行したとき、 make: *** ターゲットが指定されておらず、makefile も見つかりません。中止。 のメッセージが表示され、上手くインストールできません。 実は恥ずかしながら、makeコマンドを使用してソフトをインストールする時は いつもこのメッセージが表示され、上手くセットアップ出来たことがありません。 原因として何が考えられるでしょうか? どなたかご存知の方がいらっしゃいましたらアドバイスよろしく お願いいたします。

  • make実行時のエラーについて

    makeについてお尋ねします(先日、お尋ねした件の延長なのですが)。 あるプログラムソース群からの実行ファイルの作成に関する質問です。 以下操作手順です。 ------------ 1. configure.sh というのが用意されていて、中を見てみたら私の計算機のコンパイラの状況などを調べたりして、make.incを出力しています。それは所定の場所に置かれます。これをマニュアルどおり実行しました。 2. その場所(ソース群とかmakefile,make.incがあるフォルダ)でmakeを実行しました。makeはmakefile, make.incを読み込んでいます。make.incがmakefileから呼ばれている記述も確認しました。 makeを実行すると、makefileの以下の部分がおかしいとしてmakeが終了します。 c.o: $(CC) -c $(CFLAGS) $(INCS) $*.c メッセージとして、 cc -c -I hoge.c cc: fetal error: no input files ----------- $(CC),$(CFLAGS),$(INCS) というのはcc, スペース, -I を意味するようですが、これはどこで指定されるのでしょうか。 make.incの中にはそのようなものを指定するところはありませんでした。Fortranコンパイラは調べて調整されていることが分かり、"FC= gfortran -O3" というような記述が見えます。configure.shを使って調査したことが分かります。 また、cc -c -I abc.c は、-Iでインクルードファイルのフルパスを指定なのでしょうか。man ccによるとそういう風です。 $(INCS)を削除すればいいのかもですが、一応、セットとして導入されているものなので、どこで副作用が出るかわからないのでそのままにしているのですが。理屈が分からないので、自発的に編集することをためらっています。 make全般ですが、どういう分野に属するのでしょうか。C言語の1分野でもなく、必ずしもLinuxの習得の中に組み込まれているわけでもないように見えます。学習するシステムとしてどこに属するのかということですが。その場その場でアドホックに調べて習得していくものなのでしょうか。 if......fiというようにフィーリングではわかるのですが、しっかり説明されるような学習の場面がないのですが。

  • makeでcshのコマンド展開を使用したい

    makeの中で例えば /bin/rm -f AAA*.{s,loc} のようなコマンド展開を記述した所、 solaris版 のgnu makeではこれが認識されず、一方linux版のgnu makeでは認識されるという現象が出ております。 [SOLARIS] AAA*.s AAA*.loc共に削除されない [LINUX] AAA*.s AAA*.loc共に削除される 特にエラーメッセージも出ないので原因が分かりませんが、 make "{s,loc}"という記法はcshのものなので、makeから呼ばれるshellに原因があるのでは無いかと想像していますがどうなのでしょうか? もしshellに起因する問題である場合、makeの中で用いられる展開をcshに行わせる為の指定方法としてどのようなものがあるのでしょうか? 以上宜しくお願い致します。

  • makeコマンドの意味

    make -f unix/Makefile LOCAL_UNZIP="-D_FILE_OFFSET_BITS=64 -DNO_LCHMOD -D_MBCS -DNO_WORKING_ISPRINT" linux_noasm https://gist.github.com/hamano/573753 上記サイトでunzipコマンドのソースにパッチを当ててコンパイルするのに上記のコマンドを実行していました。これは 1. Makefileの中に「$(LOCAL_UNZIP)」という部分があるのですが ここに"-D_FILE_OFFSET_BITS=64 -DNO_LCHMOD -D_MBCS -DNO_WORKING_ISPRINT" という文字列を代入するという意味であってますでしょうか。 また、文字列の中に「-D_MBCS」という記述があり、 パッチファイルの中によく似た「#ifdef _MBCS」という記述があるのですがこのif文を有効にしているという解釈であってますでしょうか。 2. コマンドの最期に'linux_noasm' とあり、Makefileの中を検索したら以下の記述がありました。これはどう解釈すればよいでしょうか。 linux_noasm: unix_make $(MAKE) unzips CC=gcc LD=gcc CFLAGS="-O -Wall"

  • コマンドを実行?

    http://journal.mycom.co.jp/column/osx/145/ 上のURLの中で 【ファイルの入手】のしたのほうに 『コマンドを実行してCVS版のソースからバイナリを生成』と 書いてありますがまったくやり方がわかりません。 コマンドを実行するとはどういう意味ですか? 教えてください。