Intel Fortran for Windowsをコマンドラインで使うときのオプション

# 概要
Intel FortranのWindows版をCLIで使用する場合，ディレクトリの指定やライブラリをリンクするためのオプションが，よく知られたgcc/gfortranとは異なります．特にライブラリのリンクはリンカの役割なので，Intel Fortranのリファレンスを調べても出てきません．

情報を調べるのに少し苦戦したので，まとめることにしました．

# 環境
- Windows 10
- Intel Fortran 2021.1
- Visual Studio 2017
- gfortran 10.3.0 (TDM-GCC-64)

# 状況の仮定
下記のようなディレクトリ構造のプロジェクトを作成し，Intel Fortranを用いてビルドを行うことを想定します．作業は，プロジェクトのルートを作業ディレクトリとして，コマンドライン（コマンドプロンプト）で行います．

```
.
├── include
│   └── stdlib_error.mod
├── lib
│   ├── fortran_stdlib.lib
│   └── libfortran_stdlib.a
├── src
│   └── main.f90
├── .gitignore
:
└── README
```

WindowsでVisual Studioもインストールしているのだから，GUIで行えば？という意見はごもっともです．ですが，プログラミングの学習過程でCMakeなどのビルドツールを使い，クロスプラットフォームのプロジェクトを構築しようとした際に，「どうにも上手くいかないので，とりあえずコマンドラインでビルドできるかを確認したい」という状況もあり得ます．

# gfortranによるコンパイルとリンク
上記のようなプロジェクトをgfortran (gcc)でコンパイルする場合，インクルードディレクトリやライブラリディレクトリの指定，およびライブラリのリンクのオプションはよく知られています．ついでに，出力される実行ファイル名を指定しておきます．

```
gfortran src\main.f90 -Iincluce -Llib -lfortran_stdlib -o project.exe
```

コマンドラインオプションには，それぞれ下記の意味があります．

- `-I`<br>インクルードディレクトリを指定する．
- `-L`<br>ライブラリディレクトリを指定する．
- `-l`<br>静的ライブラリを指定する．ライブラリの名前`libfortran_stdlib.a`から`lib`と`.a`を除いた名前を指定する．
- `-o`<br>出力ファイル名を指定する．

# Intel Fortranによるコンパイルとリンク
前節のgfortranと同じことしようとすると，Intel Fortranの場合，下記のようなオプションを付けてコマンドを実行します．

```
ifort src\main.f90 /Iinclude /exe:project.exe /link /LIBPATH:lib fortran_stdlib.lib
```

もしくは

```
ifort src\main.f90 /Iinclude /link /LIBPATH:lib fortran_stdlib.lib /OUT:project.exe
```

コマンドラインオプションには，それぞれ下記の意味があります．

- `/I`<br>インクルードディレクトリを指定する．`/include:`も利用可能．
- `/exe:`<br>出力されるexeもしくはdllの名前を指定する．
- `/link`<br>このオプション以降のオプションがリンカに対するオプションであることを指定する．
- `/LIBPATH:`<br>ライブラリディレクトリを指定する．
- `ライブラリ名`<br>リンクするライブラリ名を指定する．
- `/OUT:`<br>出力されるexeの名前を指定する．

インクルードディレクトリの指定`/I`はコンパイル時に必要なので，Intel Fortranに対するオプションです．しかし，コンパイルによって作成されたオブジェクトファイルとライブラリをリンクして実行ファイルを作成するのは，リンカの役割です．そのため，ライブラリディレクトリの指定`/LIBPATH:`や出力ファイル名の指定`/OUT:`は，リンカに与えるオプションです．

`LIBPATH`および`OUT`に大文字小文字の区別はありません．

Intel Fortranは，リンカに渡すオプションを明示的に区別するために，`/link`オプションを付けます．

## 実行例
コマンドラインオプションの効果を確認するために，オプションを徐々に増やしながらその出力を確認します．
出力を簡略化するために，`/nologo`オプションを付けて著作権表示を抑制しています．

ソースファイルのみを指定してコンパイルすると，`stdlib_error`が見つからないため，コンパイルエラーとなってコンパイルに失敗します．

```
> ifort /nologo src\main.f90
src\main.f90(3): error #7002: Error in opening the compiled module file.  Check INCLUDE paths.   [STDLIB_ERROR]
    use :: stdlib_error
-----------^
compilation aborted for src\main.f90 (code 1)
```

`/I`でインクルードディレクトリを指定すると，コンパイルエラーは出なくなりましたが，`check`手続が見つからないため，リンクエラーが発生しました．

```
> ifort /nologo src\main.f90 /Iinclude
main.obj : error LNK2019: 未解決の外部シンボル STDLIB_ERROR_mp_CHECK が関数 MAIN__ で参照されました。
main.exe : fatal error LNK1120: 1 件の未解決の外部参照
```

`/link fortran_stdlib.lib`を付けても，見つからないというエラーが出ます．

```
> ifort /nologo src\main.f90 /Iinclude /link fortran_stdlib.lib
LINK : fatal error LNK1181: 入力ファイル 'fortran_stdlib.lib' を開けません。
```

`/LIBPATH:`オプションでライブラリディレクトリを指定したところ，コンパイル・リンクに成功しました．警告は出力されますが，実行ファイル`main.exe`が無事に作成されています．

```
> ifort /nologo src\main.f90 /Iinclude /link /LIBPATH:lib fortran_stdlib.lib
LINK : warning LNK4098: defaultlib 'MSVCRTD' は他のライブラリの使用と競合しています。/NODEFAULTLIB:library を使用してください。

> dir *.exe /B
main.exe
```

出力ファイル名を指定するために，`/OUT:`オプションを付けて実行すると，所望の名前で実行ファイルが作成されます．

```
> ifort /nologo src\main.f90 /Iinclude /link /libpath:lib fortran_stdlib.lib /out:project.exe
LINK : warning LNK4098: defaultlib 'MSVCRTD' は他のライブ
ラリの使用と競合しています。/NODEFAULTLIB:library を使用し
てください。

> dir *.exe /B
project.exe
```

LINKの警告が煩わしい場合は，さらに`/NODEFAULTLIB`オプションを追加します．`libary`の箇所を警告メッセージにある`MSVCRTD`に置き換えます．

```
> ifort /nologo src\main.f90 /Iinclude /link /libpath:lib fortran_stdlib.lib /out:project.exe /nodefaultlib:msvcrtd

> dir *.exe /B
project.exe
```

# まとめ
Intel Fortran for Windowsをコマンドラインで使う際に，インクルードディレクトリ，ライブラリディレクトリ，ライブラリ，出力ファイル名を指定するオプションを紹介しました．

- `/I`<br>インクルードディレクトリを指定する．`/include:`も利用可能．
- `/exe:`<br>出力されるexeもしくはdllの名前を指定する．
- `/link`<br>このオプション以降のオプションがリンカに対するオプションであることを指定する．
- `/LIBPATH:`<br>ライブラリディレクトリを指定する．
- `ライブラリ名`<br>リンクするライブラリ名を指定する．
- `/OUT:`<br>出力されるexeの名前を指定する．

Windowsでは，リンカにMicrosoft Incremental Linkerを用い，コンパイラとリンカに渡すオプションを，明示的に分けて指定する必要があります．

コンパイラからすると，何が使われるか判らないリンカの情報を網羅的にまとめるのも大変でしょうし，それをする義理もありません．また，Windows版のIntel Fortranは，Visual Studioと統合され，コンパイルオプションをGUIで設定できるので，コマンドラインオプションの情報はそれほど重要ではなかったことが情報を探すのに苦戦した理由だと考えています．