LoginSignup
44
46

More than 5 years have passed since last update.

Fortran 用の Makefile の書き方

Posted at

はじめに

Fortran 90 がこの世に出てからずいぶん経つけど、make のデフォルトルールはモダンな Fortran に対応してないよね。だったら自分で書くしかないんだけど、みたところあまり情報が出回ってないみたい。

いつもながら今さら感があるのだけれどちょっと整理してみようか。

Fortran のモジュール

Fortran に触れたことない人向けに簡単に説明しておくと、Fortran 90 以降のモダンな Fortran (FORTRAN 77 などと区別するために1文字目のみ大文字で書く) では「モジュール」っていうものが導入された。

モジュールの詳しい説明は省くけど、分割コンパイルと関連させて使うことが多くて、例えば submod というモジュールを submod.f90 で定義して別のファイル main.f90 のルーチンから submod に定義されたサブルーチンや変数を参照したりする。

そして submod.f90 をコンパイルするとオブジェクトファイル submod.o と、モジュール中間ファイル submod.mod ていうのができるんだ。submod.mod っていうのは乱暴に言うと C でいうヘッダファイルみたいな役割をするもんだと思ってほしい。

で、main.f90 をコンパイルするときには submod.mod が必要になるっていうわけだ。ルーチンとかの実体がある submod.o はなくてもコンパイルできる (もちろん実行ファイルを作るときには必要)。

submod.f90 が修正されてもそのインターフェースに変更がなければ submod.mod は変わらない。だからそれを参照する main.f90 も再コンパイルの必要がないってわけだ。FORTRAN 77 の時代とは打って変わって Fortran もモダンになったね。

Makefile に対する要件

make のデフォルトルールに Fortran 90 用の定義を追加して、プロジェクトの固有の記述量は減らしたいところ。

先の例でいうと submod.o とsubmod.mod は submod.f90 から作られる。だからそういうルールを書けばいい…って言いたいところだけどそうは問屋が卸さない。

不適切な記述
submod.mod: submod.f90
    gfortran -c $<

依存関係的にはそうなんだけど、submod.mod は submod.f90 を再コンパイルしても更新されるとは限らない。内容に変更なければ更新されないんだ。上のように単純に submod.mod を submod.f90 に依存させると submod.mod が更新されずに submod.f90 より古いファイルの状態になって、make を実行するたびにコンパイルが実行されてしまう場合が発生する。

そこでちょっと工夫が必要になる。

modの依存関係を工夫
submod.o: submod.f90
    gfortran -c $<

submod.mod: submod.f90 submod.o
    @:

submod.f90 から submod.o を作成するルールは通常のものだから説明は不要だろう。

ここで重要なのは submod.mod と submod.o のルール。: は何もしないコマンド。末尾に挙げた参考リンクだと true を使ってたりするけれどここでは Windows でも使える : にした。

この submod.mod のルールでは submod.mod が生成されないのだけれど、もう一つの submod.o を作成するときに submod.mod が生成される。じゃあ submod.mod のルールは要らないんじゃないかと思うかもしれないけれどそうではない。

下の例を見てほしい。

main.oの依存関係
main.o: main.f90 submod.mod
    gfortran -c $<

main.o は main.f90 と submod.mod に依存するのでこのような記述になる。

ここで submod.mod のルールがないと submod.mod が見つからなくて make が終了してしまう。先のルールにより submod.o が参照され、submod.f90 のコンパイルが実行される (そして submod.mod も生成される)。

デフォルトルール

Makefile はできるだけデフォルトルールを有効活用するようにしたほうが記述量も減り管理のミスもなくなる。デフォルトルールが存在しない場合は可能であればデフォルトルールを追加する形で設定するとよい。

gmake のデフォルトルールは -p オプションで確認できる。FORTRAN 77 用のデフォルトルールが存在するのでそれを参考に定義するのがよいだろう。

先の .mod のルールも反映させると下のようになる。

Fortran用のデフォルトルール
FC = gfortran

.SUFFIXES: .f90

%.o: %.f90
    $(COMPILE.f) $(OUTPUT_OPTION) $<

%.mod: %.f90 %.o
    @:

こうしておくとプロジェクト固有の定義は下のように書ける。

プロジェクト固有の定義
TARGET = sample
OBJS = main.o submod.o

$(TARGET): $(OBJS)
    $(LINK.f) $^ $(LOADLIBES) $(LDLIBS) -o $@

main.o: submod.mod 

main.o と submod.mod の依存関係がシンプルに記述できてるのがわかるだろうか。

まとめ

まとめると下のようになる。もちろんデフォルトルールを別ファイルにしてインクルードしてもよい。

Makefileの全体
FC = gfortran

TARGET = sample
OBJS = main.o submod.o

.SUFFIXES: .f90

%.o: %.f90
    $(COMPILE.f) $(OUTPUT_OPTION) $<

%.mod: %.f90 %.o
    @:

$(TARGET): $(OBJS)
    $(LINK.f) $^ $(LOADLIBES) $(LDLIBS) -o $@

main.o: submod.mod 

おわりに

Makefile で Fortran の .mod ファイルを扱うこの手法は自分の発案ではないのだけれど、ネットにまとまった情報が少なかったり記述にミスがあったりしてるので混乱するよねーって思った。

単に需要がないだけかもしれないけど Fortran でプログラムを組む際の助けになればいいんじゃないかな?

参考

http://d.hatena.ne.jp/pyridoxin/20110726/1311691190
http://lagrange.mechse.illinois.edu/f90_mod_deps/

44
46
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
44
46