Makefile

Makefile

ソースコードが複数のファイルに渡って存在する場合に、それらを一度にコンパイルし、実行ファイルを生成するシステム。 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

最終更新:2014年07月06日 16:54
|新しいページ |検索 |ページ一覧 |RSS |@ウィキご利用ガイド |管理者にお問合せ
|ログイン|