速習 makefileの作り方

Linuxにはmakeという便利な機能があります。
通常ですとプログラムをコンパイルする時は、コンパイルする度にコマンドラインコンパイラ名とソースファイル名とコンパイルオプションと・・・と大変めんどうなのです。
さらに、ある一つのソースファイルを書き換えたとき、すべてをもう一回プログラムをすべてコンパイルし直すのは面倒です。
これを"make"のコマンド一発でやってのけてくれます。
makeを使えば、コマンドラインに面倒くさいオプションを書く必要もなし、更新されたファイルだけを選択的に選んでコンパイルしてくれるので、書き直した時のコンパイル時間の短縮にもなります。
このmakefileの作り方は全く難しいものではなく、一度作ってしまえばあとは使い回すことができます。
今回はFortran90のプログラムの場合を考えますが、C言語にも簡単に応用することができます。

復習 ソースコードから実行プログラムになるまで

この項はプログラミングをある程度慣れ親しんでいる方には常識だと思いますので読み飛ばしてください。

プログラムを書いたコードは、機械語に翻訳しないとコンピュータは理解できません。
Fortran90で書いたコードを機械が読めるように翻訳してやる、これがコンパイルです。
コンパイルをするとオブジェクトファイル(拡張子.o)が完成します。
ところで、ソースコードの書かれたファイルは、普通は一つではありません。
先人の作った便利なプログラム群であるライブラリを読み込む必要も出てきます。
すなわち、それぞれのファイルをコンパイルした後、一つにまとめて実行プログラムにする必要があり、これがリンクです。
実行プログラムは、Windowsですと拡張子として.exeがついたりしますが、特に明示する必要はありません。

すなわち、あなたの書いたソースコード
コンパイル->リンク
の過程を経て、実行プログラムとなります。
以上の過程をまとめてビルドと呼んだりします。

準備

ソースファイルが

main.f90
interface.f90
globals.f90
sub1.f90
sub2.f90

というファイルに分けて書かれているとします。
interface.f90にはインターフェイスモジュールinteface_modが、globals.f90にはグローバル変数モジュールglobalsが書かれているとしましょう。
また、プログラムにはライブラリとしてLAPACK(あるいはIntel MKL)とOpenMPが使われているとします
実行ファイル名は

sample

というにしようと思います。

makefileの準備

ソースコードのあるフォルダに makefile という名前のファイルを作ります。
Linuxディストリビューションによってはファイル名を make とか Makefile とかにしないといけないものもあるみたいです。
makefileをgeditでもEmacsでもなんでもいいから開いて、次の様に入力します。

TARGET = sample
OBJECTS = globals.o interface.o main.o \
	sub1.o sub2.o
MOD_FILES  = globals.mod interface_mod.mod
#FC = gfortran
FC = ifort

FFLAGS =
LDFLAGS =


# for gfortran
ifeq (${FC},gfortran)
	FFLAGS += -fimplicit-none -fbounds-check
	LDFLAGS += -fopenmp -llapack -lblas
endif

# for ifort
ifeq (${FC},ifort)
	MKLROOT = /opt/intel/composer_xe_2011_sp1.7.256/mkl
	FFLAGS += -I${MKLROOT}/include/ia32 -I${MKLROOT}/include
	LDFLAGS += -L${MKLROOT}/lib/ia32 ${MKLROOT}/lib/ia32/libmkl_blas95.a
	LDFLAGS += ${MKLROOT}/lib/ia32/libmkl_lapack95.a
	LDFLAGS += -lmkl_intel -lmkl_intel_thread -lmkl_core -openmp -lpthread -lm
endif


.SUFFIXES : .o .f90
.f90.o:
	${FC} -c $<

${TARGET} : ${OBJECTS}
	${FC} -o $@ ${OBJECTS} ${LDFLAGS} ${FFLAGS} 


.PHONY: clean
clean:
	${RM} ${TARGET} ${OBJECTS} ${MOD_FILES}

文頭に空白がある場合は、スペースキーで空白を作るのではなく、Tabキーで作ることに注意してください。
端末を開いてmakefileのあるフォルダに移動し

$ make

で、プログラムがビルドされます。
また

$ ./sample

でプログラムが実行されます。
ソースコード以外のプログラムのコンパイルの途中に生成されるファイルたちをすべて消したいときは

$ make clean

で削除できます。

makefileの解説

順番に解説していきましょう。

TARGET = sample
OBJECTS = globals.o interface.o main.o \
	sub1.o sub2.o
MOD_FILES  = globals.mod interface_mod.mod

#FC = gfortran
FC = ifort

FFLAGS =
LDFLAGS =

例えば、一番上の TARGET = sample というのは、 TARGET という変数に'sample'という文字列を入れろという意味です。
呼び出す場合は ${TARGET} か $(TARGET) と書きます。
文末にある\マークは改行を意味し、一つの文が長くなりすぎる場合に使います。
また、#はコメント文を表し、その行で#よりも後ろにある文は無視されます。
FCにはコンパイラの種類を入れています。

# for gfortran
ifeq (${FC},gfortran)
	FFLAGS += -fimplicit-none -fbounds-check
	LDFLAGS += -fopenmp -llapack -lblas
endif

gfortranを使う場合です。
FFLAGSにはコンパイル時のオプションやインクルードファイルのパス設定が入ります。
LDFLAGSにはリンク時のオプションやライブラリのパス設定が入ります。

-fimplicit-noneは、ソースコードに出てくる関数にすべてimplicit noneを指定するオプションです。
implicit noneのつけ忘れに効果的です。

また、-fbounds-checkはデバッグ用のオプションで、配列の領域外を参照してないかチェックします。
例えば dimension a(3) で配列aを定義したのに a(4) を使ってないかをチェックします。
デバッグ用のオプションをつけると実行速度がやや落ちるので、実際の計算の際はこのオプションを落としましょう。

デバッグ用のオプションについては以下のページが参考になります。
http://www.rcs.arch.t.u-tokyo.ac.jp/kusuhara/fswiki/wiki.cgi?page=Fortran%A5%C7%A5%D0%A5%C3%A5%B0%CD%D1%A5%AA%A5%D7%A5%B7%A5%E7%A5%F3

# for ifort
ifeq (${FC},ifort)
	MKLROOT = /opt/intel/composer_xe_2011_sp1.7.256/mkl
	FFLAGS += -I${MKLROOT}/include/ia32 -I${MKLROOT}/include
	FFLAGS += -lmkl_intel -lmkl_intel_thread -lmkl_core -openmp -lpthread -lm
	LDFRAGS += -L${MKLROOT}/lib/ia32 ${MKLROOT}/lib/ia32/libmkl_blas95.a
	LDFLAGS += ${MKLROOT}/lib/ia32/libmkl_lapack95.a
	LDFLAGS += -lmkl_intel -lmkl_intel_thread -lmkl_core -openmp -lpthread -lm
endif

今度はIntel Fortran Compilerを使う場合です。
MKL(Math Kernel Library)の場所は人によって違うので確認しておきましょう。
MKLを使う場合のコンパイルオプションの付け方は、以下のページで質問に答えていけば教えてくれます。
Intel® Math Kernel Library Link Line Advisor | Intel® Software

.SUFFIXES : .o .f90
.f90.o:
	${FC} -c $<

一行目でサフィックスルール摘要対象の拡張子を指定します。
サフィックスとは拡張子のことです。
'.SUFFIXES : .o .f90' は、.oを作るときは必ず.f90から作られるよ、という意味です。
三行目がmakeがコマンドラインに代わりに入れてくれる行です。
$<は、前回に.oファイルを作ってから、現在にソースコードが更新されている.f90の拡張子のファイルだけを選択的に選んで挿入してくれる記号です。

${TARGET} : ${OBJECTS}
	${FC} -o $@ ${OBJECTS} ${LDFLAGS} ${FFLAGS}

今度は一行目が${OBJECTS}から${TARGET}を作るよ、という意味です。
$@はターゲットファイル名(:の左側のファイル名)が入ります。


最後に、プログラムをビルドする時にできたファイルたちを一掃するマクロを書いておきます。

.PHONY: clean
clean:
	${RM} ${TARGET} ${OBJECTS} ${MOD_FILES}

こうすると

$ make clean

と入力することで、${TARGET} ${OBJECTS} ${MOD_FILES}のファイルが消えます。
${RM}は定義済みのマクロで、'rm -f'を表します。
Linuxディストリビューションによっては${RM}が使えない場合もありますので、このときは rm -f に置き換えてください。