Fortranをmakeする

ライブラリなんかを引っ張ってきた時に実行させられるmakeコマンド。
makeが何をしているか、fortranコードのLETKFを例に見てみる。

##make
makeとはコンパイルとかその他もろもろをやってくれるコマンド。
makefileに書いてあることにしたがって実行される。

##makefile

```makefile
目的のファイル: ソースファイル群
	生成方法
```
って書く。
*ただし、生成方法が実行されるのは目的のファイルよりもソースファイルが新しかった場合のみ。

##ソースファイル群をまとめる

```LETKFのmakefile
FILES= \
       dyn_geop.o \
       dyn_grtend.o \
       dyn_implic.o \
       dyn_sptend.o 
#ほんとはもっと長いけど、一部抜粋
```
ソースファイル群はこうやって変数のように設定できる。
`\`は行が続く意。改行しても続いてるって扱いになる。
こうすれば、毎回毎回これらのファイルを呼ぶときに全部書かなくて住み、以下のようにかけるようになる。

```
a.out: $(FILES)
        gfortran $(FILES) -o a.out
```

##生成方法をまとめる
同じ生成方法を何度も書くのがだるいとき、コンパイル前後のファイルの名前を変えないなら、以下のように省略可能。

```
main.o: main.c	   #←生成に使用するファイルは指定するが、生成方法は書かない
sub.o: sub.c

%.o: %.c
        gcc -O -c $< -o $@
```

ここで、
%：ファイル名の共通部分（拡張子以外）
$<：ソースファイル名（拡張子含む）
$@：アウトファイル名（拡張子含む）

##拡張子の関係を定義する
古い書き方。
`.c``.h``.o``.a`以外の拡張子を使いたい時（fortranの`.f`とか）、拡張子の関係を定義する。
fortranの`.f`プログラムを機械語に直された`.o`実行プログラムの関係を定義してある。

```
.SUFFIXES: .f .o #２種類の新拡張子を追加

.f.o: #.fから.oを生成する
	gfortran $< -o $@
```

##生成に必要なファイルを指定

```
main.o: main.c	   #←生成に使用するファイルは指定するが、生成方法は書かない
sub.o: sub.c
```
これは、main.cとmain.oとを明示的に関連付ける方法。
main.cが更新された時にちゃんとmain.oが再コンパイルされるように設定する。

##実際のmakefileを見る
LETKF(局所アンサンブルカルマンフィルタ)のプログラムのmakefileを例に見る。
LETKFはhttps://github.com/takemasa-miyoshi/letkf でダウンロード可能。

```makefile
COMPILE=ifc #ifcをコンパイラとしてセット

COMLIB1=


#COMOTT1=  -tpp7 -O3 -r8 #tpp7はlinux用のコマンド
COMOTT1= -O3 -r8 
#O3は最適化度合い　O3が最高 O0は最適化なし
#r8はrealを倍精度実数として読むオプション

COMCONV= #エンディアンのconvertはなし

#ファイル群を変数として用意
FILES= \
       dyn_geop.o \
       dyn_grtend.o \
       dyn_implic.o \
       dyn_sptend.o \
       dyn_step.o \
       dyn_stloop.o \
       ini_impint.o \
       ini_indyns.o \
       ini_inforc.o \
       ini_iniall.o \
       ini_inphys.o \
       ini_inirdf.o \
       ini_invars.o \
       ini_stepone.o \
       phy_convmf.o \
       phy_fordate.o \
       phy_lscond.o \
       phy_phypar.o \
       phy_radiat.o \
       phy_shtorh.o \
       phy_suflux.o \
       phy_vdifsc.o \
       ppo_diagns.o \
       ppo_restart.o \
       ppo_setctl.o \
       ppo_setctl_daily.o \
       ppo_setgrd.o \
       ppo_tminc.o \
       ppo_tminc_daily.o \
       ppo_tmout.o \
       ppo_tmout_daily.o \
       sfc_anomod.o \
       spe_matinv.o \
       spe_spectral.o \
       spe_subfft_fftpack.o

#.fは.oに変換すると教える
.SUFFIXES: .f .o

#.fをいかにして.oにするかを教える
.f.o:
	$(COMPILE)  $(COMOTT1) $(COMCONV) -c  $<

#全部ま下に書いてある全ファイルを使ってimp.exeを作る
imp.exe: $(FILES)  at_gcm.o
	$(COMPILE)  $(COMOTT1) $(COMCONV)  $(FILES) at_gcm.o -o imp.exe $(COMLIB1) 

#ファイル同士をひも付け
at_gcm.o               : at_gcm.f
dyn_geop.o             : dyn_geop.f
dyn_grtend.o           : dyn_grtend.f
dyn_implic.o           : dyn_implic.f
dyn_sptend.o           : dyn_sptend.f
dyn_step.o             : dyn_step.f
dyn_stloop.o           : dyn_stloop.f
ini_impint.o           : ini_impint.f
ini_indyns.o           : ini_indyns.f
ini_inforc.o           : ini_inforc.f
ini_iniall.o           : ini_iniall.f
ini_inphys.o           : ini_inphys.f
ini_inirdf.o           : ini_inirdf.f
ini_invars.o           : ini_invars.f
ini_stepone.o          : ini_stepone.f
phy_convmf.o           : phy_convmf.f
phy_lscond.o           : phy_lscond.f
phy_fordate.o          : phy_fordate.f
phy_phypar.o           : phy_phypar.f
phy_radiat.o           : phy_radiat.f
phy_shtorh.o           : phy_shtorh.f
phy_suflux.o           : phy_suflux.f
phy_vdifsc.o           : phy_vdifsc.f
ppo_diagns.o           : ppo_diagns.f
ppo_restart.o          : ppo_restart.f
ppo_setctl.o           : ppo_setctl.f
ppo_setctl_daily.o     : ppo_setctl_daily.f
ppo_setgrd.o           : ppo_setgrd.f
ppo_tminc.o            : ppo_tminc.f
ppo_tminc_daily.o      : ppo_tminc_daily.f
ppo_tmout.o            : ppo_tmout.f
ppo_tmout_daily.o      : ppo_tmout_daily.f
sfc_anomod.o           : sfc_anomod.f
spe_matinv.o           : spe_matinv.f
spe_spectral.o         : spe_spectral.f
spe_subfft_fftpack.o   : spe_subfft_fftpack.f 
```