魔術師見習いのノート

プロフィール

魔術師見習い
Author魔術師見習い-_-.
Twitter魔術師見習い

コンピュータ関係のメモを主に書きます.

MENU

make

投稿日:
修正日:
修正日:
タグ:

目次

makeの使い方に関するメモ.

make

makeコマンドとは

makeは,複数のソースファイルからコンパイルする際,それらの依存を解決するためによく使用される.makeはメイクファイルと呼ばれるテキストファイルに基づいて,依存を判断する.例えばhoge.cとfuga.c,piyo.cからfoo.exeを生成する場合,次のようにメイクファイルを記述できる.

foo.exe: hoge.o fuga.o piyo.o
	gcc -o foo.exe hoge.o fuga.o piyo.o

hoge.o: hoge.c
	gcc -c hoge.c

fuga.o: fuga.c
	gcc -c fuga.c

piyo.o: piyo.c
	gcc -c piyo.c
この時,makeは3つのソースファイルの内前回のコンパイル時から変更されたもののみをコンパイルし,3つのCソースファイルから生成されたオブジェクトファイルをリンクする.make自体には,コードを見て依存関係を判断する能力はなく,あくまでユーザが記したメイクファイルに従う.makeはターゲットを作成するために下位の構成要素から順に処理を行う.前述の例でfoo.exeをターゲットとした時,この文を実行するより先に必要な3つのコンポーネントの作成を行う.すなわちそのコンポーネント名がターゲット名である依存関係行から始まる文である.makeはこのような処理を再帰的に行い,最終的なターゲットを生成する.

makeの使い方は次の通りである.

user% make [ -f メイクファイル ] [オプション] [ターゲット] [マクロ定義]
メイクファイルを指定しなかった場合,makeはカレントディレクトリにあるmakefileやMakefileという名前のファイルをメイクファイルと見なす.標準のメイクファイルの名前は,makeの種類に依存する.

ターゲットを指定しなかった場合,メイクファイルで最も上のエントリを処理する.

通常,makeはコマンドがエラー終了(0以外の終了コードでの終了)の場合,そこで処理を中断する.

オプション

以下にオプションの例をいくつか示す.

オプション機能
-b古いmake用のメイクファイルを受付可能にする.
-dデバッグモードで実行.フラグやファイルの最終更新時刻などの詳細情報を表示する.
-iエラーを無視する.
-kエラーが発生すると現在のターゲットに関する作業は中止するが,他のターゲットの構築は続行する.
-nコマンドを実行せずに表示だけを行う.@で始まるコマンド行も表示する.
-pマクロ定義や有効なサフィックス,サフィックスルール,メイクファイルエントリを表示する.
-rデフォルトルールを使用しない.
-s実行するコマンドを表示しない.
-t構築のためにコマンドを実行せずにターゲットの最終変更時刻を最新のものに変更する.

メイクファイル

メイクファイルの名前には,関連としてmakefileやMakefile,または.mkのサフィックス(拡張子)を持つ名前を使用する.また,makeはfオプションを指定して複数のメイクファイルを指定することでそれらを結合して使用できる.

また,makeを次のように指定した場合,makeはファイルの代わりに標準入力から読み取る.

user% make -f - iomod
この場合ファイルの末尾(c-d)を読み取るまで処理を続ける.

構文と意味

ここでは,構文を示した後それらの詳細を説明する.ここでは,[]で囲われた部分は省略可能であることを指す.また,斜字の部分にはファイル名やコマンドなどの文字列が入る.ただし,タブはASCIIコードの9番のHTを意味する.

依存関係行
ターゲット:[:] [コンポーネント] [;[コマンド]]
コマンド行
タブ [-@] コマンド
  • コマンド行はそれぞれ別のシェルで実行するように扱われる.そのためifやforのようなコマンドを扱う場合は;や\を駆使する必要がある.
  • -がついている場合は,コマンド行でエラーが起きても,次のコマンド行を処理する。
  • 行末に\を付けることで,複数行に跨いだ記述ができる.
コメント
#から行末までがコメントとして扱われる.

ターゲット
  • 生成するファイルのこと.
  • ターゲットファイルが存在しない場合以降のコマンド行を実行する.
  • 空白で区切って複数指定可能.
  • 前にたぶを置いてはいけない
  • 英字,数字,ピリオド,アンダースコアが使用可能(それ以外はmakeコマンドに依存)
: (コロン)
  • コロンの両側には空白があってもなくても構わない
  • コロンを2つ使った場合,複数のコマンド行を伴った依存関係行に同一のターゲットを指定することができる(通常同じターゲットの依存関係行は記述できない).
コンポーネント
  • ターゲットを生成するために必要なファイルのこと.
  • コンポーネントがターゲットとして定義されていた場合,その処理を実行
  • コンポーネントのファイルが更新されていなかった場合,以降のコマンド行を無視する.
  • 空白で区切って複数指定可能.
セミコロン・コマンド
  • セミコロンの後にコマンドを記述可能.
  • タブの後に空白があってもなくても構わない.
  • -をつけるとコマンドからエラー(0意外の終了コード)が返されても無視する.
  • @をつけると実行の際にコマンドを表示しない.
  • コマンドには通常ターゲットを構築するためのコマンドを指定する.

サフィックスルール

サフィックスルールを使えばいくつかのメイクファイルのテキストが簡潔に記述できる.サフィックスルールを使用すると,前述のメイクファイルは次のように置き換えられる.

foo.exe: hoge.o fuga.o piyo.o
	gcc -o foo.exe hoge.o fuga.o piyo.o

.c.o:
	gcc -c $<
$<はマクロであり,現在処理中のターゲットよりも後で変更されたコンポーネント名を表す.サフィックスルールの文法は次の通りである.
サフィックスルール
.サフィックス1[.サフィックス2] :[:]
  • サフィックス1を持つファイルが,サフィックス以外が同じでかつサフィックス2を持つファイルがコンポーネントとなりうる.
  • サフィックス2が指定されていない場合,サフィックスを持たずサフィックス1以外が同じ名前のファイルを指す.
  • コロンは2つあっても意味がない
  • サフィックスには英字,数字,ピリオド,アンダースコアが使用可能(それ以外の文字はmakeコマンドに依存).
サフィックスルールは次の条件が成立する場合に適応される.
  • これより下位のコンポーネントが存在しない.
  • ターゲットがコンポーネントよりも古い.

マクロ

マクロの定義は次の文によって行う.

マクロ定義
マクロ名 = 文字列
  • マクロ名の前に空白を記述しても良い.
  • マクロ名の前にタブは記述してはいけない.
  • 等式の周りには空白やタブを置いて良いが,文字列を割り当てる際に文字列の一部として扱われない.
  • "や'は文字列の一部として扱われる.
マクロ参照
  • $(マクロ名)
  • ${マクロ名}
  • $1文字だけのマクロ名
  • 定義されていなマクロは空の文字列として扱われる.
マクロ名
  • 文字として英字,数字,下線などが使用可能(それ以外の文字はmakeコマンドに依存).
  • 慣例として大文字を使う.
VAR = hoge
echo $(VAR)
あらかじめ定義されているマクロ

makeが用意したマクロ
以下にいくつか例を示す.
変数名内容
CCCコンパイラ
CFLAGSCコンパイラのオプション
FCfortranコンパイラ
FFLAGSfortranコンパイラのオプション
ASアセンブラ
ASFLAGSアセンブラのオプション
LDリンカ
LDFLAGSリンカのオプション
MAKEFLAGSmakeコマンドに与えられたオプション.4.3BSDではMFLAGSというマクロ名.
$<現在処理中のターゲットよりも後で変更されたコンポーネント名.サフィックスルールと.DEFAULTエントリでのみ使用可能.
$*現在処理中のターゲットよりも後で変更されたコンポーネントのサフィックス除いた名前.
$@現在処理中のターゲット
$$@現在処理中のターゲット名.依存関係行の右側でのみ使用可能.
$?現在処理中のターゲットよりも後で変更されたコンポーネントのリスト
$%ターゲットがライブラリであった場合に対応する.oファイルの名前.
makeコマンド実行の際に定義したマクロ
前述のmakeコマンドの実行方法で示した通り,その際にマクロの定義を行うことができる.makeは与えられた引数がターゲットかマクロ定義かは=が付いているか否かで判断する.ただし,定義する文字列に空白を含む場合や=の前後を空白で区切る場合,"や'で囲わない限りシェルは正しく認識できない.
シェル変数
シェルに渡された環境変数をマクロとして利用できる.
特殊なマクロ
SHELL
コマンドを解釈するために使用するシェルの種類.

マクロの優先順位

マクロは前述で示した通り様々な方法で定義される.その際,同じ名前のマクロ名を参照する場合は優先順位が高いものが選ばれる.以下に優先順位が高い順に記す.

  1. makeを実行するコマンド上で,makeコマンド名よりも後で定義されたマクロ
  2. メイクファイル内で定義されたマクロ
  3. 環境変数
  4. makeによって予め内部定義されたマクロ

ただしmake実行の際にeオプションを指定した場合,次の優先順位が高い順に従う.

  1. makeを実行するコマンド上で,makeコマンド名よりも後で定義されたマクロ
  2. 環境変数
  3. メイクファイル内で定義されたマクロ
  4. makeによって予め内部定義されたマクロ
これは複数人のプロジェクトで一部それぞれ固有の設定を使用したい際などに便利である.

特殊なターゲット
.DEFAULTこれからつくろうとするファイルに関するメイクファイルエントリやサフィックスルールが存在しなかった場合に実行される.
.IGNORE実行したコマンドのエラーコードを無視する.
.PRECIOUSmakeを中断するためのシグナルやエラー終了する場合でも,ここで指定されたファイルは削除されない.
.SILENT実行するコマンドを表示しない.
.SUFFIXESこのターゲットとして指定されたものは,makeにとって意味を持つサフィックスとなり,サフィックスルールを持つことが出来るようになる.

さまざまなmake

makeは種類やバージョンによって異なる機能を持つ.以降の機能は全てのmakeが共通して持つ機能ではない.

特殊なマクロ
VPATH
カレントディレクトリにコンポーネントが存在しな場合にmakeが探しにいくディレクトリのリストを指定.
マクロ修飾子

いくつかのマクロは文字列からファイル名やディレクトリ部分を抽出できる.次のコードはhoge/fuga/にあるpiyo.cをコンパイルして,そこにpiyo.o生成するメイクファイルである.

all: hoge/fuga/piyo.o

.c.o:
	cd $(<D); \
	$(CC) -c $(<F)
D$?を除くマクロのディレクトリ部分
F$?を除くマクロのファイル名の部分

マクロ文字列置き換え

${value:s1=s2}
${value}を展開した文字列の空白またはタブの直前にあるs1や文字列の最後に位置するs1を全てs2で置き換える. 例えば次のように記述した場合,
SOURCES=hoge.c fuga.c piyo.c
	echo ${SOURCES:.c:.o}
echoは"hoge.o fuga.o piyo.o"と出力する.

サブディレクトリ

makeはディレクトリ毎に分けて管理する機能もサポートしている。

Makefile
サブディレクトリのMakefileを実行するには,「make -C サブディレクトリ」を使用する。サブディレクトリのmakeのターゲットを指定する場合の例も一緒に示す。
.PHONY: sub1 sub2
SUBDIRS := sub1 sub2

all: $(SUBDIRS)
	gcc -o a.out piyo.c -Isub1 -Isub2 -Lsub1 -Lsub2 -lhoge -lfuga

$(SUBDIRS):
	$(MAKE) -C $@

clean:
	rm a.out
	$(MAKE) clean -C sub1
	$(MAKE) clean -C sub2
.PHONYは擬似ターゲットと呼ばれるもので,後述するターゲットが存在する場合でも処理を行う場合に記述する。前述の例では,cleanやallというファイルがないことを前提に記述しているが,不安ならば.PHONYに書いた方がいいだろう。
sub1/Makefile
libhoge.a: hoge.o
	ar rv libhoge.a hoge.o

.c.o:
	$(CC) -c $< -o $@

clean:
	rm libhoge.a hoge.o
sub2/Makefile
libfuga.a: fuga.o
	ar rv libfuga.a fuga.o

.c.o:
	$(CC) -c $< -o $@

clean:
	rm libfuga.a fuga.o

前述で示したもの以外にもmakeはさまざまな機能を持つ.

include

複数のMakefileを使用する場合,一部のコードを共通化すると,便利である。

Makefile.common
CC=gcc
CFLAGS=-O3
Makefile
include Makefile.common

a.out: hoge.o
	$(CC) $(CFLAGS) -o a.out hoge.o

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

一覧