ソースコードが複数のファイルに渡って存在する場合に、それらを一度にコンパイルし、実行ファイルを生成するシステム。 Makefileが賢いのは、ソースファイルとオブジェクトファイルファイルの時間を確認し(タイムスタンプを比較)し、更新された ソースファイルだけをコンパイルする点である。 こうする事で、コンパイル時間を節約できる。
Makefileの最も基本的な構造は
TARGET: DEPENDENCES (tab) COMMAND
である。ここで(tab)はタブ・スペースであり、タブ・スペースがないとMakefileは機能しないので重要である。
TARGETは最終的な生成物であり、またこの動作を指定する名前のような物である。
DEPENDENCESには依存ファイル、つまり互いに依存するソースコードをここに書く。
もしTARGETがDEPENDENCESよりも古ければ、COMMANDが実行され、新しいTARGETが生成されることになる。
具体例を記すと、
foo: hello.f90 world.f90 (tab) gfortran hello.f90 world.f90 -o exename
などのようにする。 ここでコマンドラインで
make foo
と打ち込むと、hello.f90 world.f90から実行ファイルexenameが生成される。 また、単に
make
を打ち込んだ場合、一番先頭にあるtargetが実行される。
さて、ここからはマクロを用いてMakefileをより見やすくする。 マクロとは、いってみれば変数である。
TARGET = foo EXEFNAME = jikkou SRCS = hello.f90 world.f90 FC = gfortran $(target): $(SRCS) (tab) $(FC) $(SRCS) -o $(EXEFNAME)
ここで前半が変数に値を代入し、後半は各変数を用いてMakefileの基本構造を作っている。 端末で
make
と打ち込むと、jikkouという名前の実行ファイルが生成される。
さて、次が重要であるが、更新されたソースコードだけをコンパイルするという部分をMakefileに 書き込む。
TARGET = foo EXEFNAME = jikkou SRCS = hello.f90 world.f90 OBJS = $(SRCS .f90=.o) FC = gfortran .SUFFIXES .f90 .f90.o: (tab) $(FC) -c $< $(target): $(OBJS) (tab) $(FC) $(OBJS) -o $(EXEFNAME)
ここで.f90.oを書いた部分は”*.f90ファイルから*.oを作成せよ”という指令である。 このような書き方をサフィックスルールと呼ぶ。 ただ、.f90という拡張子はMakefileにはデフォルトではサフィックスルールには従わないので、 .SUFFIXES .f90とすることで、.f90をサフィックスルールに従いますよ、と宣言しておく。
・make clean Makefileを使用するもう一つのご利益がこのcleanである。 makefileに以下を付け加える
.PHONY: clean clean: (tab) @rm -f $(OBJS) $(OBJS:.o=.mod) $(EXEFNAME)
端末で
make clean
とすればコンパイルによって生じたオブジェクトファイルや実行ファイル、モジュールファイルなどが消去される。 こうすることでディレクトリがスッキリとする。
・make tarball ソースコードなどを一纏めに圧縮しておきたい場合もmakeでできる。 自分が圧縮したいと思うファイルを事前にALLFILESなどと適当なマクロを定義して、
tarball: (tab) @tar zcvf $(PROGRAM).tgz $(ALLFILES)
とMakefileに書き込む。端末で
make tarball
とすると、ALLFILESで指定されたファイル達が圧縮され、$(PROGRAM).tgzという名前で圧縮される。
最後に、私が使用しているMakefileの例を示す。
PROGRAM = result EXEFNAME = $(PROGRAM).x SRCS = test1.f90 test2.f90 INCLUDE = test3.dat LIBS = test4.a OBJS = $(SRCS:.f90=.o) FC = gfortran FCFLAGS = -O2 ALLFILES = $(SRCS) Makefile .SUFFIXES: .f90 all: $(PROGRAM) .f90.o: (tab) $(FC) $(FCFLAGS) -c $< $(FCFLAGS) -o $@ $(PROGRAM): $(OBJS) $(INCLUDE) (tab) @echo "Linking $(PROGRAM)..." (tab) @$(FD) $(FCFLAGS) -o $(EXEFNAME) $(OBJS) $(LIBS) (tab) @echo "Done." tarball: (tab) @tar zcvf $(PROGRAM).tgz $(ALLFILES) .PHONY: clean clean: (tab) @rm -f $(OBJS) $(OBJS:.o=.mod) $(EXEFNAME)
本稿を纏めるにあたって、以下のサイトを参考にしました。
この場を借りて、お礼申し上げます。
http://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/make-intro/macro.html
http://www.atmarkit.co.jp/ait/articles/1106/10/news115.html
http://d.hatena.ne.jp/rontas/20121226/1356511831
https://www.mlab.im.dendai.ac.jp/~tobe/xp-2/gmake.html