Hatena::ブログ(Diary)

@author pyridoxin このページをアンテナに追加 RSSフィード

ここにある文章や画像は引用されたものでない限り自由に使ってください。
ただし私が開放したようにあなたも私の文章を引用した場合、その文章を開放してください。

July 26(Tue), 2011

[]Makefileで.modの依存関係を上手く書く方法

.modとは

Fortranプログラムでmoduleが含まれるファイルをコンパイルする場合(モジュール名).modというファイルができる。

.modファイルはuse文を使うことで他のファイルからでも参照可能である。

moduleを使った例(mod.f90)
module mod
  integer ,parameter :: ten=10
end module mod
useを使った例(use.f90)
program use
  use mod
  write (*,*) ten
end program use

上記二つのファイルをコンパイルして実行ファイルを作る場合、以下の操作が考えられる

gfortran -c mod.f90

gfortran use.o -J(mod.modがあるディレクトリ)

依存関係

上記操作で最終的に生成されるa.outの依存関係を考えると以下の通りになる

a.out→use.f90 mod.mod

mod.mod mod.o → mod.f90

これをMakefileで表現する

SHELL=/bin/sh
FC=gfortran
EXEC=a.out
all : $(EXEC)
$(EXEC) : use.f90 mod.mod
        $(FC) -J. $< 
mod.mod mod.o : mod.f90
        $(FC) -c $<
clean :
        @rm -f $(EXEC) mod.mod mod.o

全く問題ないMakefileのように見える。

しかしこのMakefileには問題がある

touchコマンドでmod.f90のタイムスタンプを更新してほしい。

makeをもう一度実行すると以下のことが行われると普通は思うはずだ。

  1. mod.f90が更新されたのでmod.f90はコンパイルされる。
  2. mod.f90がコンパイルされたのでmod.modは更新される。
  3. mod.modが更新されたのでuse.f90はコンパイルされる。

しかし実際に行うと1しか行われない。

どの仮定がおかしいのだろうか?

2である。

たとえmod.f90ファイルが更新されていても、moduleの中身に変更が全くない場合、mod.modは更新されない。その結果として以降makeでずっと1のみ実行されてしまう

迷惑な話である。この問題を解決するためには以下のように考えればよい。

  1. mod.oと依存があるファイルはmod.f90だけとする。
  2. mod.modと依存があるファイルはmod.f90とmod.oである。
  3. 1のコマンドにmod.f90をコンパイルする記述を書く
  4. 2のコマンドでは何もしない

上記の条件でMakefileは以下の動作を行う

  • $(EXEC)依存解析のために2の依存解析を行う
  • 2の依存解析を行うために1の依存解析を行う
  • mod.f90がmod.oより新しい場合(mod.oがない場合も含む)コマンドを実行する

mod.modが更新されなくてもmod.oはmod.f90の依存しか見てないので問題は生じない。

以上のことを実際のMakefileに書くと以下のようになる。

SHELL=/bin/sh
FC=gfortran
EXEC=a.out
all : $(EXEC)
a.out : use.f90 mod.mod
        $(FC) -J. $< 
mod.o : mod.f90
        $(FC) -c $<
mod.mod : mod.f90 mod.o
        @true
clean :
        @rm -f $(EXEC) mod.mod mod.o

参考URI

Re: Makefile with .mod files

Matthew West: Fortran 90 Module Dependencies

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/pyridoxin/20110726/1311691190