fpm (Fortran Package Manager)をBuilder兼Runnerとして利用する（続き1）

fortran-langは[Fortran-lang Community Projects](https://fortran-lang.org/community/)の成果を記事にする際に用いているタグです．


# 概要
前の[記事](https://qiita.com/implicit_none/items/167d36fdc3a30e4135d0)で紹介したfpm (Fortran Package Manager)が，Prototype版からver. 0.1.2になったので使ってみました．

大きな変化は

- バイナリが提供されるようになってインストール方法が変わった．
- プロジェクトを作れるようになった．
- 複数のプロジェクトをまとめてビルドできるようになった．

くらいだと思われます．

追記：
バージョン0.5.0での使い方を別記事にまとめました．

- [fpm (Fortran Package Manager)の使い方](https://qiita.com/implicit_none/items/6a65ac1b83efefc782db)
- [fpm (Fortran Package Manager)の設定ファイルの解説](https://qiita.com/implicit_none/items/99c5d12f5c18733c66fd)
- [fpm (Fortran Package Manager)のプロジェクトの作成例](https://qiita.com/implicit_none/items/08a2d26f8288dda7b4f5)

# 環境
- Ubuntu 18.04 (WSL)
- fpm version 0.1.2
- gfortran 8.4.0
- Haskell stack 2.5.1
- git 2.17.1

# fpmのインストール
fpm verion 0.1.0からは，Windows，Linux，MacOS向けのバイナリが提供されるようになりました．
fpmのリポジトリの[リリースページ](https://github.com/fortran-lang/fpm/releases)から，必要なバイナリをダウンロードし，適当なフォルダにコピーすればインストールは完了です．

本記事では，Prototype版に合わせて，`~/.local/bin`にコピーしています．

前の[記事](https://qiita.com/implicit_none/items/167d36fdc3a30e4135d0)でも紹介したように，fpmはHaskell-stackを使ってビルドする必要がありました．これまでと同様に，[リポジトリ](https://github.com/fortran-lang/fpm)をcloneしてstackを使ってビルドすることも可能です．

手順はfpmのGithubリポジトリに書いてあります．

1. fpmのリポジトリをクローン
2. Haskell版のfpmをビルド
3. Haskell版fpmでFortran版のfpmをビルド
4. Fortran版fpmを適当なディレクトリにコピー

少々変わったインストール手順ですし，上記の環境で試したところ，ビルドしたfpmが正常に動作しませんでした．Windows, Linux, MacOSを利用している場合は，素直にバイナリをダウンロードすることをお薦めします．

# fpmによるプロジェクト管理
## プロジェクトの作成
fpmで新しいプロジェクトを作成するには，

```console
fpm new プロジェクト名
```

を実行します．`プロジェクト名`は，各人で置き換えてください．

コマンドを実行すると，実行したディレクトリ以下に`プロジェクト名`のディレクトリが作成され，いくつかのファイルとサブディレクトリが作成されます[^1]．

[^1]: 当然gitで管理するんだろう？という圧を感じます．

```console
$ fpm new sample
 + mkdir -p sample
 + cd sample
 + mkdir -p sample/src
 + mkdir -p sample/test
 + mkdir -p sample/app
 + git init sample
Initialized empty Git repository in コマンドを実行したディレクトリ/sample/.git/
```

```
プロジェクト名
├── app
│   └── main.f90
├── ｓｒｃ
│   └── プロジェクト名.f90
├── test
│   └── main.f90
├── fpm.toml
├── README.md
└── .gitignore
```

fpmの公式によると，`app`や`test`ディレクトリは，オプションを利用した場合に作成されるらしいのですが，現状では何のオプションを付けなくても作成されました．

自動で作成されたソースファイルを見ると，テストは投げやりですが，それ以外はそれなりに形になっています．

```Fortran:app/main.f90
program main
  use sample, only: say_hello
  implicit none

  call say_hello()
end program main
```

```Fortran:src/sample.f90
module sample
  implicit none
  private

  public :: say_hello
contains
  subroutine say_hello
    print *, "Hello, sample!"
  end subroutine say_hello
end module sample
```

```Fortran:test/main.f90
program main
implicit none

print *, "Put some tests in here!"
end program main
```


README.mdの中身は，非常に簡素です．

```
# sample
My cool new project!
```

一方，プロジェクトを管理するfpm.tomlファイルには，色々な情報が書かれています．簡単なプログラムであれば，最初に作られたfpm.tomlのヘッダ部分（名前やバージョンなど）を編集するだけで十分でしょう．

```
name = "sample"
version = "0.1.0"
license = "license"
author = "Jane Doe"
maintainer = "jane.doe@example.com"
copyright = "2020 Jane Doe"


[library]
source-dir="src"

[[test]]
name="runTests"
source-dir="test"
main="main.f90"

[[executable]]
name="sample"
source-dir="app"
main="main.f90"
```

fpm.tomlの項目の並びが`[library]`，`[[executable]]`となっていることが気になった方もいるのではないでしょうか？

Prototype版から，fpmは用途に応じて3通りのパッケージングの方法を提供しています．

- アプリケーション（実行ファイルのみを生成）
- ライブラリ（静的ライブラリのみを生成）
- アプリケーションとライブラリ

また，`app`ディレクトリを作成するには`--with-executable`が必要だという公式の記述から，fpmはライブラリ作成を基本としている（必要があれば実行ファイルも作成できる）のだと考えられます．

## プロジェクトのビルド

fpmでプロジェクトをビルドするには，プロジェクトのディレクトリ（fpm.tomlがあるディレクトリ）で，

```console
fpm build
```

を実行するだけです．

```console
$ fpm build
 + mkdir -p build/gfortran_debug/sample
 + mkdir -p build/gfortran_debug/test/
 + gfortran -c test/main.f90 -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fbounds-check -fcheck-array-temporaries -fbacktrace -fcoarray=single  -J build/gfortran_debug/sample -I build/gfortran_debug/sample -o build/gfortran_debug/test/main.f90.o
 + gfortran -c ./src/sample.f90 -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fbounds-check -fcheck-array-temporaries -fbacktrace -fcoarray=single  -J build/gfortran_debug/sample -I build/gfortran_debug/sample -o build/gfortran_debug/sample/sample.f90.o
 + ar -rs build/gfortran_debug/sample/libsample.a build/gfortran_debug/sample/sample.f90.o
ar: build/gfortran_debug/sample/libsample.a を作成しています
 + mkdir -p build/gfortran_debug/app/
 + gfortran -c app/main.f90 -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fbounds-check -fcheck-array-temporaries -fbacktrace -fcoarray=single  -J build/gfortran_debug/sample -I build/gfortran_debug/sample -o build/gfortran_debug/app/main.f90.o
 + gfortran  -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fbounds-check -fcheck-array-temporaries -fbacktrace -fcoarray=single  -J build/gfortran_debug/sample -I build/gfortran_debug/sample build/gfortran_debug/app/main.f90.o build/gfortran_debug/sample/libsample.a  -o build/gfortran_debug/app/sample
 + gfortran  -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fbounds-check -fcheck-array-temporaries -fbacktrace -fcoarray=single  -J build/gfortran_debug/sample -I build/gfortran_debug/sample build/gfortran_debug/test/main.f90.o build/gfortran_debug/sample/libsample.a  -o build/gfortran_debug/test/runTests
```

プロジェクトディレクトリ直下にbuildディレクトリが作成され，その下にgfortran_debugディレクトリが作られます．gfortran_debug以下には，プロジェクトディレクトリと同じディレクトリapp, sample（プロジェクト名）, testが作られ，コンパイル時に作成されたオブジェクトファイルなどが置かれます．
また，sampleには，静的ライブラリlibsample.aが作成されます．

リリース版をビルドする際は，`--release`オプションを付けてビルドします．

```console
$ fpm build --release
 + mkdir -p build/gfortran_release/sample
 + mkdir -p build/gfortran_release/test/
 + gfortran -c test/main.f90 -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -ffast-math -funroll-loops -fcoarray=single  -J build/gfortran_release/sample -I build/gfortran_release/sample -o build/gfortran_release/test/main.f90.o
 + gfortran -c ./src/sample.f90 -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -ffast-math -funroll-loops -fcoarray=single  -J build/gfortran_release/sample -I build/gfortran_release/sample -o build/gfortran_release/sample/sample.f90.o
 + ar -rs build/gfortran_release/sample/libsample.a build/gfortran_release/sample/sample.f90.o
ar: build/gfortran_release/sample/libsample.a を作成しています
 + mkdir -p build/gfortran_release/app/
 + gfortran -c app/main.f90 -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -ffast-math -funroll-loops -fcoarray=single  -J build/gfortran_release/sample -I build/gfortran_release/sample -o build/gfortran_release/app/main.f90.o
 + gfortran  -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -ffast-math -funroll-loops -fcoarray=single  -J build/gfortran_release/sample -I build/gfortran_release/sample build/gfortran_release/app/main.f90.o build/gfortran_release/sample/libsample.a  -o build/gfortran_release/app/sample
 + gfortran  -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -ffast-math -funroll-loops -fcoarray=single  -J build/gfortran_release/sample -I build/gfortran_release/sample build/gfortran_release/test/main.f90.o build/gfortran_release/sample/libsample.a  -o build/gfortran_release/test/runTests
```

`--release`オプションの有無でコンパイルオプションが変わっていることが確認できます．
オブジェクトファイルなどは，build\gfortran_releaseディレクトリ以下に置かれます．

## 実行
ビルドしたプログラムは，`fpm run`で実行します．

```console
$ fpm run
 + build/gfortran_debug/app/sample 
 Hello, sample!
```

テストは，`fpm test`で実行します．

```console
$ fpm test
 + build/gfortran_debug/test/runTests 
 Put some tests in here!
```

# fpm付属のサンプル
fpmのリポジトリには，fpmプロジェクトの[サンプル](https://github.com/fortran-lang/fpm/tree/master/example_packages)がいくつか存在します．
そのうち，確認しておいた方がよい例を表にまとめました．

| サンプル              | 理由                                        | 
|---|---|
| hello_world         | 最小のプロジェクト                              | 
| hello_complex       | 複数のテストや実行ファイルを含むプロジェクト         | 
| hello_fpm           | hello_complexを参照した，プロジェクト同士の連携の例 | 
| circular_example    | circular_testを循環参照                       |
| circular_test       | circular_exampleを循環参照                    | 
| submodules          | サブモジュールを使用する例                       | 
| link_executable     | 外部ライブラリとの連携                           | 
| with_c              | C言語を含むプロジェクトの例                      | 
| with_makefile       | makefileの使用例（Fortran版fpmでは動作しない）   | 

# まとめ
Prototype版から進化したfpmを使ってみました．
目に見えて大きく変わったということはありませんが，できる事も増えて，着実に良くなっています．

まだ，外部コマンドとの連携や，コンパイルオプションの変更，gfortran以外のコンパイラの利用はできないみたいですが，今後に期待します．

近いうちに，もう1本fpmに関する記事を投稿する予定です．
[投稿](https://qiita.com/implicit_none/items/d755d34e319b3bee78de)しました．（2020 Dec. 13rd）