Makefileについて教えてください


以下のMakefileでmakeすると

------- ここから -----------

CC = gcc
INCLUDE = -I/opt/fm/include
CFLAGS = -O4 -Wall $(INCLUDE)
LDFLAGS = -L/opt/fm/lib
LIBS = -lfmlog
OBJS = test.o
PROGRAM = test

all: $(PROGRAM)

$(PROGRAM): $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) $(LIBS) -o $(PROGRAM)

clean:; rm -f *.o *~ $(PROGRAM)


------------ ここまで -------------------

以下のように2回 gccが実行されるのですが
なぜでしょうか

gcc -O4 -Wall -I/opt/fm/include -c -o test.o test.c
gcc test.o -L/opt/fm/lib -lfmlog -o test

もしありましたら
参考サイトについても
紹介いただけると助かります

回答の条件
  • 1人5回まで
  • 13歳以上
  • 登録:2014/02/09 23:56:56
  • 終了:2014/02/10 12:35:09

ベストアンサー

id:a-kuma3 No.2

a-kuma3回答回数4557ベストアンサー獲得回数19032014/02/10 07:53:57

ポイント85pt
gcc test.o -L/opt/fm/lib -lfmlog -o test

↑のコマンドは、↓のルールで実行されている、ということは分かりますか?

$(PROGRAM): $(OBJS)
    $(CC) $(OBJS) $(LDFLAGS) $(LIBS) -o $(PROGRAM)

不思議に思っているのは、↓のコマンドがどんな仕組みによって起動されているか、ということだと思います。

gcc -O4 -Wall -I/opt/fm/include -c -o test.o test.c

make には「暗黙のルール」というのがあります。
質問にある Makefile だと、test と test.o を比較して、必要があれば gcc ($(CC)) を実行する、というルールが書いてあります。
では、test.o というのは、どうやって作るの、というのがあらかじめ決められたルールがあります。
使われている暗黙のルールは、↓のような感じです。

%.o: %.c
    $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

これに、.SUFFIXES の指定が関係してきます(これも、デフォルトがあります)。
test.o は、test.c から作る可能性があって、そのソースがあるなら、このコマンドを使う、というのを、あらかじめ make が持っていて、そのルールに従って実行されます。

質問のケースだと、*.o がひとつだけなので、自分でルールを書いてもたいしたことはありませんが、ソースが増えてきたり、c言語だけじゃなくて、他の言語も混ぜて作ったり、ということがあると単純な内容でも自分で書いていくのは大変です。
暗黙のルールは、そういったありがちなルールを書かなくて済むようにしてくれます。


因みに、*.c から *.o を経由しない暗黙のルールもありますので、以下のような Makefile だけで test.c から test を生成することができます。

CC = gcc
INCLUDE = -I/opt/fm/include
CFLAGS = -O4 -Wall $(INCLUDE)
LIBS = -lfmlog
LDFLAGS = -L/opt/fm/lib $(LIBS)

PROGRAM = test

all: $(PROGRAM)


clean:; rm -f *.o *~ $(PROGRAM)

GNU の環境であれば、CC = gcc も要らない。
暗黙のルールは GNU make であれば -p オプションを指定すると、全ての暗黙のルールが出力されます。


ちょっと内容が難しいですが、make コマンドのマニュアルに詳細が書いてあります。
http://quruli.ivory.ne.jp/document/make_3.79.1/make-jp_9.html

id:fujimasa1985

詳しく回答いただきありがとうございます
大変参考になりました

2014/02/10 12:33:29

その他の回答(1件)

id:windofjuly No.1

うぃんど回答回数2625ベストアンサー獲得回数11492014/02/10 03:12:37

ポイント15pt

gccは、オブジェクトファイル生成と、
オブジェクトファイルを結合しての実行ファイル生成の2ステップで使われるため、
gccの実行回数は生成するオブジェクトの数+1。

ステップ1:オブジェクトファイル生成
gcc -O4 -Wall -I/opt/fm/include -c -o test.o test.c

ステップ2:実行ファイル生成
gcc test.o -L/opt/fm/lib -lfmlog -o test


より深い知識を得たいならば、
Makefileについて調べるよりもgccの処理の流れとコマンドオプションについて学んだほうが良いでしょう。

id:a-kuma3

gcc でリンクまでするときには 2ステップで実行されるのは、その通りですが、質問にあるケースは make コマンドの挙動です。
Makefile に、以下のような行を足して、暗黙のルールを書き換えてみると、何が起きているのか分かります。

%.o: %.c
    echo "Oops"
2014/02/10 07:59:36
id:fujimasa1985

回答いただきありがとうございます

2014/02/10 12:33:52
id:a-kuma3 No.2

a-kuma3回答回数4557ベストアンサー獲得回数19032014/02/10 07:53:57ここでベストアンサー

ポイント85pt
gcc test.o -L/opt/fm/lib -lfmlog -o test

↑のコマンドは、↓のルールで実行されている、ということは分かりますか?

$(PROGRAM): $(OBJS)
    $(CC) $(OBJS) $(LDFLAGS) $(LIBS) -o $(PROGRAM)

不思議に思っているのは、↓のコマンドがどんな仕組みによって起動されているか、ということだと思います。

gcc -O4 -Wall -I/opt/fm/include -c -o test.o test.c

make には「暗黙のルール」というのがあります。
質問にある Makefile だと、test と test.o を比較して、必要があれば gcc ($(CC)) を実行する、というルールが書いてあります。
では、test.o というのは、どうやって作るの、というのがあらかじめ決められたルールがあります。
使われている暗黙のルールは、↓のような感じです。

%.o: %.c
    $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

これに、.SUFFIXES の指定が関係してきます(これも、デフォルトがあります)。
test.o は、test.c から作る可能性があって、そのソースがあるなら、このコマンドを使う、というのを、あらかじめ make が持っていて、そのルールに従って実行されます。

質問のケースだと、*.o がひとつだけなので、自分でルールを書いてもたいしたことはありませんが、ソースが増えてきたり、c言語だけじゃなくて、他の言語も混ぜて作ったり、ということがあると単純な内容でも自分で書いていくのは大変です。
暗黙のルールは、そういったありがちなルールを書かなくて済むようにしてくれます。


因みに、*.c から *.o を経由しない暗黙のルールもありますので、以下のような Makefile だけで test.c から test を生成することができます。

CC = gcc
INCLUDE = -I/opt/fm/include
CFLAGS = -O4 -Wall $(INCLUDE)
LIBS = -lfmlog
LDFLAGS = -L/opt/fm/lib $(LIBS)

PROGRAM = test

all: $(PROGRAM)


clean:; rm -f *.o *~ $(PROGRAM)

GNU の環境であれば、CC = gcc も要らない。
暗黙のルールは GNU make であれば -p オプションを指定すると、全ての暗黙のルールが出力されます。


ちょっと内容が難しいですが、make コマンドのマニュアルに詳細が書いてあります。
http://quruli.ivory.ne.jp/document/make_3.79.1/make-jp_9.html

id:fujimasa1985

詳しく回答いただきありがとうございます
大変参考になりました

2014/02/10 12:33:29

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません