Makefile Edit

目次 Edit

このページについて Edit

このページで使用している"make"は、主にGNU make(gmake)について解説しています。

Makefileとは Edit

makeコマンド Edit

Makefileを知る前に、makeを学ぶ必要がありそうなため、まずはmakeの説明から。

GNUでプログラムを作る場合、gccというコマンドを使ってコンパイルをします。
ですが、gccコマンドでは、複雑に絡み合ったプログラムをコンパイルする時は大変です。
たとえば、

Common.h
#define AIUEO ( 10 )
Main.c
#include Common.h

a = a + AIUEO;
Sub.c
#include Common.h

b = b + AIUEO

このような構成でコンパイルからリンクまでが終わっている状態のとき、Common.hを書き換えた場合は、再度Main.cとSub.cをコンパイルし、リンクし直す必要があります。

数ファイルから成るプロジェクトなら問題ないですが、大規模になるととてもやっていられないので、コンパイル、アセンブル、リンクなどを自動化する、makeというコマンドができました。
MSでいうところのビルドのようなもの。ただし、ビルドとは違って、makeする手順を自分で1から書くことができます。それがMakefileです。 ちなみに、毎回全部のファイルをいちいちコンパイルしていては時間がかかって効率が悪いので、makeでは、コンパイルする必要のあるもののみをコンパイルしてくれます。かしこい。

Makefileとは Edit

makeコマンドでは、Makefileというファイルを使用します。
Makefileは、Windowsでいうバッチファイルの高機能版のようなもので、コマンドを多数記述しておくことができます。
そのコマンドには、コンパイルやアセンブルの手順を記述しておきます。
つまり、makeはMakefileがあって初めて意味をなすものになります。

Makefileの記述方法 Edit

コメント Edit

Makefileもプログラムのように記述することができるので、コメントも必須です。
コメントは以下のように書くことができます。

#コメント。

ちなみに、Makefileは行指向のため、行コメントしかないようです。

基本文法 Edit

目的ファイルの名前1 [目的ファイルの名前2,3...] : [依存ファイル1,2,3...]
	[目的ファイルを作成するためのコマンド1]
	[目的ファイルを作成するためのコマンド2]
						...
  • 目的ファイルとは、作成したいファイルのことで、名前は拡張子を含め自由に設定することができます。
  • コマンドの前の空白はタブで、必ず先頭をタブにしなければいけません。行頭をタブにすることで、makeはこの行がコマンドであると認識します。

以下は、最も単純な例です。
このほかにも、基本構文に当てはまってさえいれば、さまざまなmakeができます。

HelloWorld: Main.c
	gcc -o HelloWorld Main.c

変数 Edit

Makefileでも、プログラミング言語のように変数を扱うことができます。
変数を使用する場合は以下のようにします。

$(foo)

非常に簡単です。$( )以外に、${ }でも使えます。

次は値の代入方法です。
makeの変数には単純展開変数と、再帰展開変数の2種類があります。

単純展開代入演算子 := Edit

単純展開変数に値を代入する場合にこの演算子を使います。
この演算子は、右辺で変数を使用している場合、代入する時点でその変数を展開します。

foo := $(CC) -o Hello.o Hello.c
この場合、fooには、
gcc -o Hello.o Hello.c
というふうに格納される。

もし、CCに値が入っていない場合は、

 -o Hello.o Hello.c

となります。

再帰展開代入演算子 = Edit

再帰展開代入変数に値を代入する場合にこの演算子を使います。
この演算子は、右辺で変数を使用している場合、使用する時点でその変数を展開します。いわゆる再帰です。

foo = $(CC) -o Hello.o Hello.c
この場合、fooには、
$(CC) -o Hello.o Hello.c
というふうに格納される。

単純展開との違いは、展開するタイミングです。
単純展開は代入する時点で変数の値が決まっている必要がありますが、再帰展開は変数定義の順番をどのようにでもすることができます。

条件付き代入演算子 ?= Edit

この演算子は、代入する変数に値が定義されていれば代入されず、定義されていなければ値を代入されます。
これは環境変数で既に値が定義されている場合などで使うことがあります。
ちなみに、この演算子で代入する場合は、再起展開変数になります。

追加演算子 += Edit

変数に値を追加します。
左辺の変数(追加される側の変数)が単純展開変数なら、すぐに展開され、再起展開変数なら使用するまで展開されません。
単純展開変数に使用する場合は問題ありませんが、再帰展開変数で使用する場合は注意が必要です。
この演算子を使う場合、

foo = $(foo) 追加分

おそらく、こうなりますが、再帰展開変数の場合、makeがうまく扱えないため、自分自身を参照してしまい、無限ループに陥る可能性があります。

定義済みの変数 Edit

GNUのmakeにはすでに定義されている変数があります。
ちなみに、これらの変数は再定義が可能です。

変数名定義文字列説明
ARarアーカイブユーティリティ
ASasアセンブラ
CCccCコンパイラ
CXXg++C++コンパイラ
COco RCSファイルからリビジョンをチェックアウトする
CPP$(CC) -ECプリプロセッサ
FCf77Fortranコンパイラ
GETget調査中。
LEXlexlex
PCpcPascalコンパイラ
YACCyaccyacc
YACCRyacc -r調査中。
MAKEINFOmakeinfoTexinfo -> Info
TEXtexTeX
TEXI2DVItexi2dviTexinfo -> DVI
WEAVEweave調査中。
CWEAVEcweave調査中。
TANGLEtangle調査中。
CTANGLEctangle調査中。
RMrm -fファイルの削除

自動変数 Edit

makeするルールが決まった時に使えるようになる変数。

自動変数説明
$@目的ファイルのファイル名すべてを表す。
$*目的ファイルの拡張子を除いたファイル名を表す。
$^依存ファイルをスペース区切りで表す。
重複した場合は除かれる。
$+依存ファイルをスペース区切りで表す。
重複してもそのまま表される。
$%ライブラリ構成指定中の要素を表します。?
$<最初の依存ファイルを表します。
$?目的ファイルよりも更新日時が新しい依存ファイルすべてをスペース区切りで表します。

ルールが決まったときに使えるので、基本的にはコマンド行で使用する。

OS.img: BootLoader.bin OS.sys
	mformat -f 1440 -C -B $< -i $@
	mcopy -i $@ $*.sys

マクロ Edit

文字列置換 Edit

$(macro:before=after)

変数macrobeforeの部分をafterに置換します。

SOURCE = aiu.c aaa.cpp bbb.S
TEMP_C		= $(SOURCE:.c=.o)
TEMP_CPP	= $(TEMP_C:.cpp=.o)
OBJECTS	= $(TEMP_CPP:.S=.o)
→aiu.o aaa.o bbb.o
先頭に文字列を結合 Edit

$(addprefix prefix, string)

文字列stringの先頭にprefixを追加します。

OBJECTS = aiu.o aaa.o bbb.o
$(addprefix dir/, $(OBJECTS))
→dir/aiu.o dir/aaa.o dir/bbb.o

コマンドラインのオプションをつけたり、ディレクトリ名をつけたり、いろいろできます。

末尾に文字列を結合 Edit

$(addsuffix suffix, string)

文字列stringの末尾にsuffixを追加します。

NAME = aiu aaa bbb
$(addsuffix .o, $(NAME))
→aiu.o aaa.o bbb.o

参考・関連 Edit

リンク Edit

書籍 Edit

GNU Make Edit

GNU Make公式マニュアル。
makeの概念、ルールの文法、変数とマクロ、関数、大規模プロジェクトで利用する方法、Windows環境での注意など、基礎から高度なテクニックまでを詳解する。
原著第3版の翻訳。


Since 2008 July. OS Project Wiki
リロード   新規 下位ページ作成 編集 凍結 差分 添付 コピー 名前変更   ホーム 一覧 検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS