ソフトウェア設計及び演習2017

Makefileの書き方

Makefileのごく簡単な解説

Makefileは,一見すると複雑ですが,ルールさえ分かれば構造は単純です.

Makefileの基本構造

(作りたいもの): (その元になる材料)
__[TAB]__(実際の作り方)   <-- 先頭が空白ではなくTAB

(作りたいもの) の後にコロン(:)を書き,続いて(その元になる材料)を記述します.

次の行に,先頭にTAB,続いて(実際の作り方)を記述します.

具体例

main.c,sub.cの二つのソースファイルから exe という実行バイナリを作成するには,

% gcc main.c sub.c -o exe

とすることは既に習っていると思いますが,これでは,どちらか一方のソースだけを修正した場合でも 両方をコンパイルし直さなければなりません.

したがって,普通は

% gcc -c main.c
% gcc -c sub.c
% gcc main.o sub.o -o exe

のように,別々にオブジェクトファイルを生成して,最後にリンクします.

さて,ソースファイルの数が増えてくると(例えば,20個とか),これらを手動で入力・管理していくことが面倒になります (し,間違いのもとにもなります).そこで,Makefileを利用します.

exe: main.o sub.o
        gcc -o exe main.o sub.o

main.o: main.c
        gcc -c main.c

sub.o: sub.c
        gcc -c sub.c
  • gccの前はTABであることに注意しましょう.

makeコマンドは,

% make (作りたいもの)

として実行するのが基本ですが,(作りたいもの)を省略した場合には,一番最初の(作りたいもの)が作成されます.つまり,

% make

とすれば,exeを作成することになります.

この際,makeコマンドは,exeの元材料であるオブジェクトファイル(main.o と sub.o)を使って,gcc -o exe main.o sub.oを実行しようとします.

ただし,main.o,sub.o についても,それぞれMakefileに材料と作り方が記述されていますので,次のような順序で動作します.

  • まず,main.oとmain.cのタイムスタンプを比較して,main.oの方が古ければ(main.cに編集が加えられていることになるので)gcc -c main.cを実行してmain.oを作り直します.もちろん,main.oが存在しないときも同様にコンパイルされます.
  • sub.oとsub.cについても同様に動作します.(もしsub.cが編集されていなければ何も起こりません)
  • このように,main.o,sub.oを最新に更新した上で,一番上のgcc -o exe main.o sub.oが実行され,exeが出来上がります.

以上のように,ある実行形式を作りたいとき,その材料がどれなのか,どうやって作るのか,といった「各ファイルの依存関係」を記述したものがMakefileです.

一般的な例

一般的なMakefileの例

CC            = gcc
CFLAGS        = -O4 -Wall -I../include
DEST          = ~/bin
LDFLAGS       = -L../lib
LIBS          = -lm
OBJS          = main.o sub.o
PROGRAM       = exe

all:            $(PROGRAM)

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

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

install:        $(PROGRAM)
                install -s $(PROGRAM) $(DEST)

はじめの方の「○=○」という記述は,単に後で使う変数の定義です.

実行バイナリを作成する部分は以下です.基本に忠実に,作りたいもの,その元となる材料,実際の作り方が書かれているだけです.

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

以下の部分は make install と実行したときにのみ,参照されます.若干変則的ですが,makeコマンドは「installの作成には材料$(PROGRAM)が必要で,実際の作り方は実行バイナリを所定のディレクトリにコピーすること」と解釈します.つまり,installというファイルは作成されませんが,installコマンドを実行した時点でmakeは終了します.

install:        $(PROGRAM)
                install -s $(PROGRAM) $(DEST)

以下の部分も少々変則的です.作りたいもの(all)とその材料は示されてますが,実際の作り方が記述されていません.

all:            $(PROGRAM)

allを作りたければ,まず$(PROGRAM)を作れ,という意味になります.

注意点

■先頭のTAB

(実際の作り方)は,必ずTABの後に書く必要があります.コピー&ペースト等でMakefileを作成すると,TABがスペースに置き換わってしまって動かない!というトラブルがよく起こります.注意しましょう.

■暗黙のルール

先ほどのMakefileには「main.cとsub.cから,それぞれmain.oとsub.oを作成する」ための方法が書かれていません.

このように,*.cから*.oを作成する手順は省略することも可能です.

ただし,コンパイル時には,最適化オプション-Oやインクルードファイルの所在を明示する-Iオプションが使われることが普通ですので,CFLAGSにその内容を定義しておきます.(*.cから*.oが自動作成される際には,CFLAGSをオプションとみなします)


最終更新日:2017/04/03 09:14:26