こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

makefileでコピーしてからコンパイルする方法

諸事情あって、C言語のコンパイルするファイルを(vpathで指定せずに)カレントディレクトリにコピーしてから、コンパイルを実行したいと思っています。
以下のように、compile_pre でコピー、compile_main でgcc を起動しているのですが、main.oがコンパイルできない旨、エラーで終了してしまいます。

これはどうしてなのでしょうか?
(compile_pre → comple_main の順番には実行しないのでしょうか?)
また、このようなことをしたいばあい、何か良い方法はありませんでしょうか。

-----------------------------------------------
# (src/main.c から main.o を生成して、main.exe を生成する)
TARGET = main.exe
TARGET_OBJS = main.o
#TARGET_OBJS += sub.o ...

.PHONY: compile compile_pre compile_main

compile: compile_pre compile_main

compile_pre:
     cp -fp ./src/main.c .;
compile_main: $(TARGET)

$(TARGET): $(TARGET_OBJS)
     gcc -o $(TARGET) $(TARGET_OBJS)
%.o : %.c
     gcc -c -o $@ $<
-----------------------------------------------

UNIX%> make compile --dry-run --debug
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for i686-pc-linux-gnu
Reading makefiles...
Updating goal targets....
 File `compile' does not exist.
   File `compile_pre' does not exist.
  Must remake target `compile_pre'.
cp -fp ./src/main.c .;
  Successfully remade target file `compile_pre'.
   File `compile_main' does not exist.
     File `main.exe' does not exist.
       File `main.o' does not exist.
      Must remake target `main.o'.
make: *** No rule to make target `main.o', needed by `main.exe'. Stop.



宜しくお願い致します。

投稿日時 - 2014-03-25 13:32:28

QNo.8528171

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

13人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.5

>%.o : %.c



%.o : src/%.c

にするだけでもコピーなんてしなくても良くなりますけど。

#3へ
-jオプションの並列処理がありますから、その関係で順番はなくなったんじゃないでしょうか。

投稿日時 - 2014-03-26 01:45:46

お礼

ありがとうございます。
ま、諸事情あってのことなので、そう簡単でもありません。

結局正解がでませんでしたが、このmake が動作しない理由は「GNU make 第3版 3.4 変数はいつ展開されるか」にヒントがありました。

make の内部処理は2段階に分かれていて、1段目のファイルチェックの段階ではコピーは実行されてないため、ファイルの依存関係グラフを作成する際にエラーとなるということです。

投稿日時 - 2014-04-04 00:04:57

ANo.4

http://www.gnu.org/software/make/manual/html_node/Instead-of-Execution.html#Instead-of-Execution
よーく読んでください。
http://linuxjm.sourceforge.jp/html/GNU_make/man1/make.1.html
でもいいです。
--dry-runの説明、なんと書いてありますか?


素直にVPATH使うとか(Makefile中に書けないならコマンドラインで指定するとか)、main.cのシンボリックリンクを作るとか、同等のことをするやり方はいくらでもあります。

投稿日時 - 2014-03-26 00:51:37

ANo.3

ちょいと確認しましたが, GNU make では #2 で言われるように依存ファイルの間の順序は「決まっていない」ということなので, 今の場合 compile_pre と compile_main のどちらを先に処理するかわかりません. 必要ならさらに依存関係を追加する必要がありますね.

かつての make では, 必ず compile_pre を先に作り直したものですが.

あと, この最後のエラーは実質的に「『main.o を作るために必要なファイル』を作る方法がわからない」と言っているんだと読むといいかな.

投稿日時 - 2014-03-26 00:39:11

補足

自分でも少ししらべてみました。

> GNU make では #2 で言われるように依存ファイルの間の順
> 序は「決まっていない」ということなので,
は、手元の書籍と見解が違います。

「GNU make 第3版 6章 大きなプロジェクトの管理」p110 によると
> 複数の必須項目が同じ行に書かれていた場合、GNU make はそれらを
> 左から右に更新します。

ご指摘は間違えだと考えます。

投稿日時 - 2014-04-03 23:57:49

ANo.2

>(compile_pre → comple_main の順番には実行しないのでしょうか?)

しません。

>compile: compile_pre compile_main

「compile は、compile_pre と compile_main に依存している」という事であって
「compile の実行には、先に compile_pre, compile_main の順に実行する」ではありませんから。

投稿日時 - 2014-03-25 21:48:22

お礼

ありがとうございます。
No3 で書きましたが、
> 「compile の実行には、先に compile_pre, compile_main の
> 順に実行する」ではありませんから。

は少なくとも GNU makeの実装とは違います。
「compile_pre, compile_main の順に実行する」が正解です。

投稿日時 - 2014-04-04 00:00:35

ANo.1

そりゃそうなるわな.

だって
何もしてない
んだもん.

投稿日時 - 2014-03-25 18:09:25

あなたにオススメの質問