いくつかのFortranコンパイラのオプションの整理

# 背景
Fortranコンパイラは複数のベンダによって提供されています．Fortranは歴史の長い言語であり，その歴史の中で，方言とよばれるベンダの独自拡張が追加されています．そのため，コンパイラ間の可搬性を確保するには注意が必要です．

コンパイラ間の可搬性を確保する最も簡単な方法は，複数のコンパイラでビルドしてみることです．著者は3種類のコンパイラを併用しています．普段使用していないコンパイラを使用しようとすると，オプションが分からないとか，以前に使ったけど忘れているというのが普通でしょう．

この記事では，使用頻度の高いコンパイラのオプションをまとめておき，備忘録的に参照できるように整理しました．

# コンパイラ
以下のコンパイラの情報を調べました．
- Intel Fortran Classic for Windows
- Intel Fortran Classic for Linux
- gfortran 
- NAG Fortran

Intel FortranはWindows版とLinux版でオプションの書き方が大きく異なります．Windows版では，Linux版のshort sytleの`-`を`/`に変更し，直後の`Q`を付けるスタイルが頻出します．また，オプションに続けて数値等を指定する場合には，区切りとして`:`が使われます．

# オプション
## 情報の表示
||Intel (Windows)|Intel (Linux)|GNU|NAG|
|:--|:--|:--|:--|:--|
|バージョン情報の表示|`/QV`|`-V`<br>`--version`|`--version`|`-V`|
|ヘルプの表示|`/help [<category>]`[^ifort_specific_help]<br>`/? [<category>]`|`-help [<category>]`|`--help[=<category>]`[^gfortran_specific_help]|`-help`|
|dryrun|-|`-dryrun`|-|`-dryrun`|

[^ifort_specific_help]: 指定した分類のヘルプを表示します．分類は`{advanced|codegen|compatibility|component|data|deprecated|diagnostics|float|help|inline|ipo|language|link|misc|opt|output|pgo|preproc|reports|openmp}`
[^gfortran_specific_help]: 指定した分類のヘルプを表示します．分類は`{common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...]`

## ディレクトリや名前の指定
||Intel (Windows)|Intel (Linux)|GNU|NAG|
|:--|:--|:--|:--|:--|
|インクルードディレクトリの指定|`/I<path>`|`-I<path>`|`-I<path>`|`-I <path>`|
|ライブラリディレクトリの指定|`/link /LIBPATH:<path>`|`-L<path>`|`-L<path>`|`-L<path>`|
|モジュールファイルディレクトリの指定|`/module:<path>`|`-module <path>`|`-J<path>`|`-mdir <path>`|
|リンクするライブラリ名の指定|`/link <filename>`|`-l<libname>`|`-l<libname>`|`-l<libname>`|
|出力される実行ファイル名の指定|`/exe:<exename>`<br>`/link /out:<exename>`|`-o <exename>`|`-o <exename>`|`-o <exename>`|

Intel Fortran ClassicのWindows版は`/link`によってリンカに対するオプションであることを明示しています．`/link`の後ろはリンカに対するオプションと認識されます．

Intel Fortran ClassicのWindows版では，出力される実行ファイル名の指定は，コンパイラに対するオプションでも，リンカに対するオプションでも指定できます．

NAG Fortranでインクルードディレクトリを指定するオプション（だけ）は，`-I`とパスの間に半角スペースが必要です．

## コンパイラ標準の指定とその拡張
||Intel (Windows)|Intel (Linux)|GNU|NAG|
|:--|:--|:--|:--|:--|
|言語標準の指定|`/stand:{f90\|f95\|f03\|f08\|f18}`|`-stand {f90\|f95\|f03\|f08\|f18}`|`-std={f95\|f2003\|f2008\|f2018\|gnu\|legacy}`|`-f90`<br>`-f95`<br>`-f2003`<br>`-f2008`<br>`-f2018`|
|固定形式のカラム上限の指定|`/extend-source[:{72\|80\|132}]`|`-extend-source [{72\|80\|132}]`|`-ffixed-line-length-<n>`<br>`-ffixed-line-length-none`|`-132`|
|自由形式のカラム上限の指定|-|-|`-ffree-line-length-<n>`<br>`-ffree-line-length-none`|-|
|入力ファイルを固定形式として解釈|`/fixed`|`-fixed`|`-ffixed-form`|`-fixed`|
|入力ファイルを自由形式として解釈|`/free`|`-free`|`-ffree-form`|`-free`|
|入力ファイルのエンコーディングの指定|-|-|-|`-encoding={ISO_Latin_1\|Shift_JIS\|UTF_8}`|
|暗黙の型宣言の無効化|-|-|`-fimplicit-none`|`-u`|

`<n>`は正の整数です．

`-ffree-line-length-none`を指定すると，自由形式でもカラム数の上限を撤廃できます．他のコンパイラではできないので，可搬性という意味では使用しない方が無難でしょう．最近は，1行を80文字以下にするなどのお作法が浸透しており，時代がFortranに追いついた気がします．
コメントにURLを掲載した場合など，長いコメントによって1行132文字の制限を超えた場合，警告を出すかはコンパイラによって異なります．

## 最適化，デバッグ，エラートレース
||Intel (Windows)|Intel (Linux)|GNU|NAG|
|:--|:--|:--|:--|:--|
|最適化レベルの指定|`/O1`<br>`/O2`<br>`/O3`<br>`/O`|`-O1`<br>`-O2`<br>`-O3`<br>`-O`|`-O1`<br>`-O2`<br>`-O3`<br>`-O0`|`-O0`<br>`-O1`<br>`-O2`<br>`-O3`<br>`-O4`|
|他の最適化フラグ|`/fast`|`-fast`|`-Ofast`|-|
|ループ展開|`/Qunroll[:<n>]`|`-unroll[=<n>]`|`-funroll-loops`|`-Ounroll=<n>`|
|デバッグ情報の付与|`/debug:full`<br>`/Z7`<br>`/Zi`|`-g[{0\|1\|2\|3}]`|`-G`|`-g`|
|実行時エラーのトレースバック情報の生成|`/traceback`|`-traceback`|`-fbacktrace`|`-gline`|
|コンパイルを中断するエラー上限の指定|`/Qdiag-error-limit:<n>`|`-diag-error-limit=<n>`|`-fmax-errors=<n>`|-|

`<n>`は正の整数です．

## プリプロセス
||Intel (Windows)|Intel (Linux)|GNU|NAG|
|:--|:--|:--|:--|:--|
|プリプロセスの有効化|`/fpp`|`-fpp`|`-cpp`|`-fpp`|
|プリプロセス結果の画面表示|`/E`|`-E`|`-E`|-|
|プリプロセッサマクロの定義|`/D<name>[=<value>]`|`-D<name>[=<value>]`|`-D<name>[=<value>]`|`-D<name>[=<value>]`|
|コンパイラを識別するためのプリプロセッサ識別子|`__INTEL_COMPILER`|`__INTEL_COMPILER`|`__GFORTRAN__`|`NAGFOR`|

## OpenMPおよびCoarrayの有効化
||Intel (Windows)|Intel (Linux)|GNU|NAG|
|:--|:--|:--|:--|:--|
|OpenMPディレクティブの有効化|`/Qopenmp`|`-qopenmp`|`-fopenmp`|`-openmp`|
|`do concurrent`の並列化[^concurrent]|`/Qopenmp`<br>`/Qparallel`|`-qopenmp`<br>`-parallel`|`-ftree-parallelize-loops=<n> -floop-parallelize-all`|※調査中|
|Coarrayの有効化|`/Qcoarray[:{shared\|single\|distributed}]`|`-coarray[={shared\|single\|distributed}]`|`-fcoarray={none\|single\|lib}`|`-coarray[={single\|cosmp}]`|
|像の数の指定|`/Qcoarray-num-images:<n>`|`-coarray-num-images=<n>`|-[^num_images]|`-num_images=<n>`|

[^concurrent]: `do concurrent`は，並列化しても問題ないことをコンパイラに教えるための構文であり，記述したとしても直ちに並列化されません．並列実行する方法は，コンパイラに依存します．

[^num_images]: コンパイル時に像の数を設定することはできず，mpirunで実行する際のプロセス数として指定します．

## 実行時エラーへの対処
||Intel (Windows)|Intel (Linux)|GNU|NAG|
|:--|:--|:--|:--|:--|
|一時配列の割り付け場所の変更|`/heap-arrays:<n>`|`-heap-arrays=<n>`|`-fmax-stack-var-size=<n>`|-|
|heapの不使用|`/heap-arrays-`|`-no-heap-arrays`|-|-|
|stackの不使用|`/heap-arrays`|`-heap-arrays`|`-fno-automatic`|-|
|配列境界のチェック|`/check:bounds`|`-check bounds`|`-fcheck=bounds`|`-C=array`|

`heap-arrays`は，`n` [kB]以上の一時配列を，ヒープメモリに割り付けます．`n`が指定されない場合，すべての一時配列がヒープメモリに割り付けられます．`/heap-arrays-`あるいは`-no-heap-arrays`は，一時配列をスタックに割り付けます．`-fmax-stack-var-size`は，stackに割り付けられる配列の最大サイズを`n` [B]に設定します．

## 並列ビルド
||Intel (Windows)|Intel (Linux)|GNU|NAG|
|:--|:--|:--|:--|:--|
|並列ビルド|`/MP[:<n>]`|`-multiple-processes[=<n>]`|-|-|