<<目次>>
makefileって何?
一番簡単な例
一番短いmakefile
サブディレクトリの処理
依存関係を自動作成
makefileを自動作成
makefileの汎用例



■makefileって何?
makefileはプログラムをコンパイル&リンクするのを自動化してくれるツールです。
これがないと、複数ファイルをコンパイルするとき、
  • プログラマがどのファイルを変更したかを覚えておいて、それらのファイルに対してコンパイルし、最後にリンクする
  • 全ファイルをコンパイル&リンクする
のどちらかを行うことになります。
前者では管理が大変ですし、後者ではファイルが多い場合、やたらとコンパイル&リンクに時間がかかって、時間の無駄になります。



■環境面
デファクトスタンダードとしては、GNU Makeが最大のシェアを抱えていますので、これを覚えておけば、問題ないです。
LinuxやCygwinでは(大抵は)こいつが標準インストールされているので、ソースディレクトリでmakeとするだけで、プログラムをコンパイル&リンクしてくれます。
ちなみに、Sun系列のOSでは、gmakeというコマンド名でインストールされていることが多いです。makeとして、エラーが出る場合は、gmakeをたたいてみるとよいでしょう。

参考書籍:
一押しは、make改訂版です。
また、makefileとは無関係ですが、組込みソフトウェア開発における品質向上の勧め (コーディング編)もお勧め。最近バグの多い情報機器の開発者には是非とも読んでほしい一冊。



■とりあえず知っておきたい規則
これ以降を読み進むに当たってとりあえず知っておいて欲しい内容を挙げておきます。
  • 変数定義
    変数名 = 値
    と書いておくと、$(変数名)でその値にアクセス出来ます。
  • 組み込み変数
    makefileでは、予め幾つかの変数が用意されています。その変数を上書きすることにより、デフォルトのオプション(コンパイル時のWarningレベルや最適化のレベルなど)を制御することができます。
    最も代表的なものは、C言語では、CFLAGS、C++では、CXXFLAGS、になります。
  • ターゲット、依存関係、コマンド
    例えば、hello.cからhello.oを作成したい場合は、
    hello.o:hello.c
    	コマンド(例えば、gcc -o hello.o hello.c)
    		
    コマンド行は、TABコードを入れる必要がありますので、ご注意を。



■一番簡単なmakefileの例
makefileには、暗黙の省略とかがあって、実はすごくシンプルに記述することができるのですが、それだと訳分からん状態になりかねませんので、省略無しの記述を紹介します。
ここでは、ソースファイルとして、hello.c,global.c,global.h、実行ファイルとしてhelloを作成する例を挙げています。
all: hello

hello: hello.o global.o
	gcc -o hello -lm hello.o global.o

global.o:global.c global.h
	gcc -o global.o $(CFLAGS) global.c

hello.o: hello.c global.h
	gcc -o hello.o $(CFLAGS) hello.c

	  
分かりやすく、下から上に見ればよいように記述してあります。
一番下がhello.oの作成方法、その上がglobal.oの作成方法、一番上がhello(実行ファイル名)の作成方法を表しています。
all行は、makeをオプション無しで実行したときにmakefileがどのファイルを作成すればいいんだろう?ってことを自動認識するものだと思ってもらえばよいです。
複数の実行ファイルを一つのmakefileで管理する必要がある場合なんかに、all行に実行ファイル名を複数書いておくと、各々の依存関係とルールをmakeが自動判定して、複数の実行フィルを作成してくれます(とりあえず今は気にしなくてよいです)。
このmakefileでmakeすると
  • global.hが変更されたときは、hello.o,global.o作成後、helloのリンクが行われます。
  • hello.cが変更されたときは、hello.o作成後、helloのリンクが行われます。
  • global.cが変更されたときは、global.o作成後、helloのリンクが行われます。
  • オブジェクトが削除された場合は、存在しないオブジェクトを作成後、helloのリンクが行われます。
  • hello(実行ファイル名)が削除された場合は、helloのリンクのみ行われます。
  • 変更ファイルがないときは、何も起こりません。
この短いmakefileでこれだけのことを自動的にやってくれます。
今はファイルが3つだけだからよいですが、これが50ファイルになったらどうしますか、是非ともmakefileの書き方を習得しておきましょう。
なお、後で省略形の書き方も紹介しますので、ファイルが多い場合は、そっちの形で書かないと大変です。今は、心配しなくてよいです。

■もっと簡単な記述方法
依存関係を気にしない(ヘッダファイル無し)なら、
hello: hello.o global.o
	  

だけでもOKですし、
hello: hello.o global.o
hello.o: hello.c global.h
global.o: global.c global.h
	  

なら、依存関係まで含めてOKです。
  • コンパイルオプションを指定する場合は、CFLAGS
  • リンクオプションを指定する場合は、LOADLIBES
  • コンパイラを指定する場合は、CC
に記述しておけばOKです。

 
 
 
 

ページ先頭へ

■一番短いmakefileの例
同一ディレクトリに、hello.cだけ作成しておき、
makefileには、
hello :
とだけ記述し、makeすれば、無事、実行ファイルが生成されます。
 
 
 
 

ページ先頭へ

■サブディレクトリの処理
グループでプログラムを作成するときは勿論、個人で作成するときでも機能別にサブディレクトリで管理したほうが何かと便利ですね。
こんなときは、VPATHを使えばOKです。

--- top - makefile main.c
|- sub1 - sub11.c sub12.c
|- sub2 - sub21.c sub22.c

上のようなディレクトリ構成の場合のmakefileは、下のようにすればOKです。
TARGET = vpath.exe
VPATH = ./sub1:./sub2
OBJS = main.o sub11.o sub12.o sub21.o sub22.o

CFLAGS = -Wall $(DEBUG)
DEBUG = -g

$(TARGET): $(OBJS)
	gcc $(DEBUG) -o $(TARGET) $(OBJS)

clean:
	rm -f *.o
	rm -f $(TARGET)
	  
どうですか、簡単でしょ。
 
 
 
 

ページ先頭へ

■makefileの依存関係を自動生成
makefileの依存関係を手書きで書いているのをよく見かけますが、自動生成可能です。
多くのコンパイラ(実はプリプロセッサ)では、
  • -M
  • -MM
のどちらか、または両方が用意されている場合が多いです。
マニュアルでは、プリプロセッサの項目に記載されている場合が多いです。
一度、お使いのコンパイラのマニュアルを見てみては如何でしょうか。
マニュアル等に記載がない場合でも、使用できる場合もありますので、一度お試しを。
また、Windows環境でもCygwinを利用すれば、gccが使えますので、依存関係部分だけをgccに任せてしまう、という手もあります。
gccの場合、gcc -MM ソースファイル名
で依存関係が標準出力に表示されます。必要に応じてリダイレクトなりすればよいでしょう。
ちなみに、gccの場合、拡張子はデフォルトで.oになっていますので、他の拡張子にしたい場合は、sedとgrepを組み合わせればOKです。
sedはsオプション、grepはvオプションを使用します。
これを流用すると、特定のファイルを依存関係に含めないようにすることも可能になります。

参考書籍:
一押しは、Make―C programming utilityです。(make改訂版の新版のようです)
(データ提供:Amazon.co.jp)

これで、ヘッダを修正したらmake cleanしてね、というのをしなくてよくなります。

 
 
 
 

ページ先頭へ

■makefileを自動生成
autoconfとautomakeを使うと、makefileを自動生成出来ます。
ただ、Cygwinだと、よくあるUnix用の説明のとおり実行しても、
「できないじゃん」ってことになってしまいます。
これは、雛形ファイルの配置場所とautoconf,automakeの実行パスによるものです。
  • 雛形ファイル
    /usr/autotool/devel/share/automake-1.9/ 1.9は異なるかもしれません。適宜読み替えてください
  • 実行パス
    /usr/autotool/stable/bin
では、hello.cのmakefileを自動生成する例を挙げていきます。
  1. 作業ディレクトリにcd
  2. 事前準備
    cp /usr/autotool/devel/share/automake-1.9/install-sh .
    cp /usr/autotool/devel/share/automake-1.9/mkinstalldirs .
    cp /usr/autotool/devel/share/automake-1.9/missing .
    cp /usr/autotool/devel/share/automake-1.9/depcomp .
    touch INSTALL NEWS README COPYING AUTHORS ChangeLog
  3. configure.inを作成
    /usr/autotool/stable/bin/autoscan 
    mv configure.scan configure.in
    configure.inを以下のように書き換えます
    dnl Process this file with autoconf to produce a configure script.
    AC_INIT(hello.c)
    AM_INIT_AUTOMAKE(hello, 0.1.0)
    AM_CONFIG_HEADER(config.h)
    
    dnl Checks for programs.
    AC_PROG_CC
    
    dnl Checks for libraries.
    
    dnl Checks for header files.
    
    dnl Checks for typedefs, structures, and compiler characteristics.
    
    dnl Checks for library functions.
    
    AC_OUTPUT(Makefile)
  4. Makefile.amとacconfig.hを準備
    touch Makefile.am
    touch acconfig.h
    Makefile.amを以下のように書き換えます
    bin_PROGRAMS = hello
    hello_SOURCES = hello.c
    acconfig.hを以下のように書き換えます
    #undef PACKAGE
    #undef VERSION
  5. configureスクリプトを自動生成
    以下のコマンドを実行することで、configureファイルが生成されます。
    /usr/autotool/stable/bin/aclocal
    /usr/autotool/stable/bin/autoconf 
    /usr/autotool/stable/bin/autoheader 
    /usr/autotool/stable/bin/automake
    /usr/autotool/stable/bin/automake
  6. Makefileを自動生成
    configureスクリプトを実行(./configure)すれば、Makefileが自動生成されます。
    元になったMakefileは、こちらも自動生成されたMakefile.inになります。

後は、ソースを編集してmakeするだけです。
単一ファイルでは面倒なだけですが、他環境への配布を意識する必要がある場合などは、configure対応しておいたほうがよいでしょう。

★参考になる書籍:
GNU Autoconf/Automake/Libtool
GNU Autoconf/Automake/Libtool


 
 
 
 

ページ先頭へ



■makefileのサンプル
私は人材派遣会社やアウトソースの名目で様々な会社で勤務してきました。
最近勤務した会社で、
  • makefileの依存関係が...
  • makefileをちゃんと作ってなくて...
などという話をしているのを聞き、それなら、ある程度汎用性を持った、makefileを提供しよう。
というのが、このページ開設のきっかけになっています。
もちろん、依存関係も自動生成です。手書きで書くなんて、ナンセンスです。

汎用的なmakefileの一例(単一ターゲット)
上のmakefileは、
  • SRC=で定義されたCソースファイル
  • HEADER=で定義されたCヘッダファイル
  • makefile本体
のどれかのファイルに変更があった際に、
TARGET=で定義された実行ファイルを作成する
makefileの一例です。

環境は、CygwinのGCC環境を想定しています。
他の環境の場合は、若干の修正が必要かもしれません。

一応汎用的になっていて、
Cソースが追加になったら、SRC=とOBJ=に追加
Cヘッダが追加になったら、HEADER=に追加
するだけで大丈夫です。
但し、
特定のファイルに対して別のオプションでコンパイルしたい場合は、
そのファイルに対して、別途ルールを指定する必要があります。

使用方法は、makefile冒頭部分に記述してあるとおりです。
基本的には、コマンドラインから、"make"とするだけです。
Meadow/Mule/Emacsなどでは、
ソースファイルやmakefileのウィンドウにフォーカスを当てて、
M-x compile として、ミニバッファで、make、と入力すればOK

余談になりますが、C++を扱う場合の注意点は
  • CFLAGSではなく、CXXFLAGSにコンパイルオプションを指定する
  • CCではなく、CXXにコンパイラを指定する
これらに注意しておけば、基本的にはCと同じです。

GNU makeの日本語マニュアルがCOOPさんの部屋にあります。
作者に感謝し、おおいに活用させていただきましょう。

それでは、makefileなどに振り回されることなく、
プログラム開発に時間を費やしましょう。


またまた余談ですが、
Cygwinに標準でX-WindowとEmacsが添付されました。
これで、GDB+Emacsデバッグ環境がCygwinのみで、
整うことになりました。
GDB+Meadowでは、工夫しないと無理がありましたから、
これは、助かる方も多いでしょう。
makefileを見てもらえば分かりますが、CygwinのGCCでは、
Windowsアプリケーション開発が可能です。
デバッグ環境まで考えれば、BorlandFreeCompilerを
超えたかもしれませんね。


ページ先頭へ






■お知らせと連絡先

このウェブサイトで取り上げて欲しい話題や分かりにくい点などありましたら、
以下のメールアドレス宛にメッセージをいただければ、参考にさせていただきます。

メールアドレスは、work_komiあっとまーくyahoo.co.jpです。
(「あっとまーく」は、半角英数のあっとまーくに変換してね。)

また、XBOXをお使いの方は、ゲーマータグ(akbox)にてフレンドリクエストを受け付けています。