概要
fpm(Fortran Package Manager) 0.5.0(執筆時点での最新バージョン)の設定ファイルfpm.tomlについて解説します.
具体的なプロジェクトの作成例は,次の記事にまとめました.
環境
- Windows 10
- fpm 0.5.0
- gfortran 10.3.0 (TDM-GCC-64)
- Intel oneAPI 2021.1
- git 2.29.2
Windowsで実行し,動作確認をしています.パスの区切りは\になっています.Unix系OSで動かす場合には,パスの区切りを/に置き換えてください.
fpm
fpm (Fortran Package Manager)は,Fortran-langプロジェクトの一環として開発されているパッケージマネージャ兼ビルドツールです.fpmが対象とする範囲は,ビルドツールとしての範囲とパッケージマネージャとしての範囲があります.
詳しくは前の記事を確認してください.
fpmの設定ファイル
fpmは,ビルドの設定をfpm.tomlに記述します.この設定のことをfpmではmanifestとよんでいます.
manifestの詳細
manifestの解説はFortran package manager (fpm) manifest referenceにあります.
一つずつ解説していくのも大変なので,とりあえずfpm newで作られる標準のfpm.tomlの内容から解説していきます.
標準のfpm.toml
標準のfpm.tomlの中を見ると,[]で分類分けされている設定と,されていない設定が見つかります.分類分けされていない設定は,プロジェクトの概要に関係しています.分類分けされている設定は,fpmの動作に関係しており,例えば[build]はfpm buildの動作に関係した設定です.
name = "sample"
version = "0.1.0"
license = "license"
author = "Jane Doe"
maintainer = "jane.doe@example.com"
copyright = "Copyright 2021, Jane Doe"
[build]
auto-executables = true
auto-tests = true
auto-examples = true
[install]
library = false
プロジェクトの概要
fpm.tomlに書かれているプロジェクトの概要を設定する項目の意味は,下記の通りです.
-
name
プロジェクトの名前 -
version
プロジェクトのバージョン -
license
プロジェクトのライセンス -
maintainer
プロジェクトのメンテナ -
author
プロジェクトの作者 -
copyright
プロジェクトのコピーライト
nameはプロジェクトの名前を意味するだけでなく,fpmパッケージの名前としても用いられます.
ビルドの設定[build]
auto-executables, auto-tests, auto-examplesが設定されています.
これらは,標準のディレクトリapp, test, example内からメインルーチン(=ターゲット)を自動で探してビルドするか否かを制御する設定です.標準では有効に設定されています.
ディレクトリに標準と異なる名前を付けるような場合,たとえばtestsなどに変更する場合は,auto-testsの設定を削除するか,auto-tests=falseとして無効にします.その後,ターゲットの設定でテスト用のソースが格納されているディレクトリ,テストの名前,ソースファイル名を列挙します.
インストールの設定[install]
ここでは,srcディレクトリにあるモジュール群をビルドして作られるライブラリを,インストールの対象とするかを設定します.
標準では無効になっており,インストールされるのは実行ファイルのみです.ライブラリおよび.modファイルもインストールの対象とするには,library = trueとします.
設定一覧
nameversionlicensemaintainerauthorcopyrightdescriptioncategorieskeywordshomepage-
[build]auto-executablesauto-testsauto-examplesexternal-moduleslink
[dependencies]-
[library]source-dirinclude-dir
-
[[executable]]namesource-dirmainlink[executable.dependencies]
-
[[test]]namesource-dirmainlink[test.dependencies]
-
[[example]]namesource-dirmainlink[example.dependencies]
-
[install]library
プロジェクト概要
プロジェクトの概要を設定する項目がいくつかあります.これはらのほとんどは動作に直接関係しませんが,nameはプロジェクトの名前を意味するだけでなく,fpmパッケージの名前としても用いられます.ライブラリや実行ファイルの名前としても用いられ,他のプロジェクトが利用する場合の参照名にもなるので,最も重要な設定です.
-
name
プロジェクトの名前 -
version
プロジェクトのバージョン
標準的な方法として,Semantic Versioningがある. -
license
プロジェクトのライセンス
標準的なライセンスの指定方法として,SPDX License ListのIdentifierが利用できる. -
maintainer
プロジェクトのメンテナ -
author
プロジェクトの作者 -
copyright
プロジェクトのコピーライト -
description
プロジェクトの詳細 -
categories
プロジェクトのカテゴリ -
keywords
プロジェクトを表すキーワード -
homepage
プロジェクトのWebページ
nameにはプロジェクトの名前を書き,プロジェクトの詳細は,descriptionに書くようにします.
categoriesは,プロジェクトのビルドに直接影響はしませんが,将来的にfpmプロジェクトをまとめたリポジトリが作成されるの可能性もあるので,分類の助けになるように付けておくとよいと思います.
ビルド設定[build]
auto-executables, auto-tests, auto-examples以外に[build]では,外部ライブラリのリンクとモジュールの参照の設定を行います.
ビルドするターゲットの自動検出
auto-executables
ビルドするアプリケーションの自動検出を設定します.
標準でこの設定は有効になっており,ディレクトリappを再帰的に検索し,メインルーチンを探してアプリケーションとしてビルドします.
無効にするには,auto-executablesをfalseに設定します.
[build]
auto-executables = false
auto-tests
ビルドするテストの自動検出を設定します.
標準でこの設定は有効になっており,ディレクトリtesetを再帰的に検索し,メインルーチンを探してテストとしてビルドします.
無効にするには,auto-testsをfalseに設定します.
[build]
auto-tests = false
auto-examples
ビルドするデモ・サンプルの自動検出を設定します.
標準でこの設定は有効になっており,ディレクトリexampleを再帰的に検索し,メインルーチンを探してアプリケーションとしてビルドします.
無効にするには,auto-examplesをfalseに設定します.
[build]
auto-examples = false
external-modules
external-modulesでは,プロジェクトが参照しているモジュールを指定します.
fpmプロジェクト内で作成したモジュールや,[dependencies]で設定している依存プロジェクト(およびそれらが依存しているプロジェクト)内で定義されているモジュールは,fpmが自動で参照して依存関係を解決するので指定する必要はありません.
プロジェクト外のモジュール,たとえば既にシステムにインストールされているライブラリを参照する場合に,コンパイラが参照できずにエラーを出すことを抑制します.ただし,fpmはプロジェクト外にあるライブラリや.modを自動で探さないので,パスの通っていないディレクトリに置いている場合は,--flagオプションを利用して,コンパイラにインクルードディレクトリを指定する必要があります.
単一のモジュールを参照する場合は値として指定子,複数のモジュールを参照する場合は,リストとして記述します.
[build]
external-modules = "stdlib_error"
[build]
external-modules = ["stdlib_error", "stdlib_logger"]
このオプションは,基本的には次のlinkと併用することになります.
link
linkでは,プロジェクトがリンクするライブラリを指定します.
fpmプロジェクト内で作成されるライブラリや,[dependencies]で設定している依存プロジェクト(およびそれらが依存しているプロジェクト)で作成されるライブラリは,指定する必要はありません.既にシステムにインストールされているライブラリを列挙するために利用します.
[build]
link = "stdlib"
[build]
link = ["stdlib", "json-fortran", "vtkfortran"]
external-modulesとlinkの使用例
たとえば,Fortranの標準ライブラリをシステムにインストールし,それをプロジェクト内で参照する場合には,下記のように設定します.
[build]
external-modules = ["stdlib_error", "stdlib_logger", "stdlib_strings"]
link = "stdlib"
fpmのプロジェクトとしてsampleを作成し,同じ階層にインストールされ,パスの通っていないstdlibを参照することを想定します.
├── sample
| ├── app\
| ├── src\
| ├── fpm.toml
| └── README.md
└── stdlib
├── include
│ ├── stdlib_error.mod
│ ├── stdlib_logger.mod
│ └── stdlib_strings.mod
└── lib
└── libstdlib.a
fpm.tomlに参照するモジュールやライブラリを書くだけでは自動で探索されません.ビルドするには,下記のようにコンパイラオプションでインクルードディレクトリとライブラリディレクトリを指定します.
sample> fpm build --profile debug --flag "-I..\stdlib\include" --link-flag "-L..\stdlib\lib"
+ mkdir build\gfortran_662B9789102B9463
+ mkdir build\gfortran_64F749E15BDD2333
+ mkdir build\gfortran_662B9789102B9463\sample\
+ gfortran -c .\src\sample.f90 -I..\stdlib\include -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds -fcheck=array-temps -fbacktrace -fcoarray=single -J build\gfortran_662B9789102B9463 -Ibuild\gfortran_662B9789102B9463 -o build\gfortran_662B9789102B9463\sample\src_sample.f90.o
+ lib /OUT:build\gfortran_662B9789102B9463\sample\libsample.a @build\gfortran_662B9789102B9463\sample\libsample.a.resp
Microsoft (R) Library Manager Version 14.00.24234.1
Copyright (C) Microsoft Corporation. All rights reserved.
build/gfortran_662B9789102B9463/sample/src_sample.f90.o
+ gfortran -c app\main.f90 -I..\stdlib\include -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds -fcheck=array-temps -fbacktrace -fcoarray=single -J build\gfortran_662B9789102B9463 -Ibuild\gfortran_662B9789102B9463 -o build\gfortran_662B9789102B9463\sample\app_main.f90.o
+ mkdir build\gfortran_64F749E15BDD2333\app\
+ gfortran -I..\stdlib\include -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds -fcheck=array-temps -fbacktrace -fcoarray=single -L..\stdlib\lib build\gfortran_662B9789102B9463\sample\app_main.f90.o build\gfortran_662B9789102B9463\sample\libsample.a -lstdlib -o build\gfortran_64F749E15BDD2333\app\sample.exe
依存関係設定[dependencies]
この項目は,主にfpmプロジェクトで開発されるライブラリが参照する依存関係の設定を行います.
ローカルプロジェクトの参照
計算機内に存在するfpmプロジェクトを参照するにはpathでパスを指定します.
[dependencies]
stdlib = { path = "../stdlib" }
stdlibのfpmプロジェクトが同じ階層にある場合の設定です.Windowsでもパスの区切りは/です.
オンラインのgitリポジトリの参照
ネットワーク上のgitリポジトリにあるfpmプロジェクトを参照するには,gitでURLを指定します.
[dependencies]
json-fortran = { git = "https://github.com/jacobwilliams/json-fortran" }
特定のブランチを指定するには,branchでブランチ名を指定します.
[dependencies]
stdlib = { git = "https://github.com/fortran-lang/stdlib", branch = "stdlib-fpm" }
ターゲットに関する設定
fpm.tomlでは,ターゲット(ライブラリ,実行ファイル,テスト,デモ・サンプル)に関する設定が可能です.ライブラリはディレクトリ名のみを変更しますが,実行ファイル,テスト,デモ・サンプルは,ディレクトリ名だけでなく実行ファイル名やメインルーチンのソースファイル名なども指定します.
ライブラリ設定[library]
プロジェクトで参照するディレクトリを指定します.
-
source-dirでライブラリ作成用のディレクトリ(プロジェクトで利用するモジュール群を配置するディレクトリ)を指定します.標準はsrcです. -
include-dirでインクルードディレクトリを指定します.標準はincludeです.
source-dirをsource,include-dirをincに変更するには,下記のように設定を記述します.
[library]
source-dir = "source"
include-dir = "inc"
include-dirは複数指定できます.
include-dir = ["include", "../stdlib/include"]
実行ファイル設定[[executable]]
アプリケーションのビルドに関する設定を行います.
ディレクトリ等の指定
この項目を変更する一番の目的は,標準のディレクトリ名を変更することだと思います.例えばappではなくapps等にする場合,下記のように設定を記述します.
[[executable]]
name = "sample1"
source-dir = "apps"
main = "main1.f90"
残念ながら,ディレクトリ名のみを変更することはできず,その中にあるメインルーチンが書かれたソースファイル名およびアプリケーションとしての名前を記述する必要があります.
2重の角括弧[[]]はテーブルの配列を意味しており,複数のアプリケーションの設定を列挙できます.
記述量は多くなりますが,その分柔軟な設定ができるようになっており,異なるディレクトリにあるメインルーチンも参照できるようになります.
[[executable]]
name = "sample1"
source-dir = "apps"
main = "main1.f90"
[[executable]]
name = "sample2"
source-dir = "apps"
main = "main2.f90"
[[executable]]
name = "tool"
source-dir = "tools"
main = "main.f90"
このように列挙するのが手間と感じる場合は,インラインテーブルを用いて簡潔に書くこともできます.ただし,この書き方をすると,次の項で紹介する依存関係の設定ができなくなります.
executable = [
{name = "sample1",source-dir = "apps",main = "main1.f90"},
{name = "sample2",source-dir = "apps",main = "main2.f90"},
{name = "tool",source-dir = "tools",main = "main.f90"}
]
tomlの書式を理解できていないだけかもしれません.どなたかご存じの方はご教示ください.
依存関係の記述
ライブラリでは使われず,アプリケーションのみが使用する外部fpmプロジェクトが存在した場合にも,[[executable]]の設定が必要になります.
アプリケーションのみが依存するプロジェクトを記述するには,少なくとも一つの[[executable]]が必要です.これは標準のディレクトリ名appを用いていても,[build]の設定でauto-executables=trueにしていても必要です.
[[executable]]に続けて,[executable.dependencies]の項目を記述します.書き方は,依存関係の設定と同じです.
[[executable]]
name = "sample"
source-dir = "app"
main = "main.f90"
[executable.dependencies]
json-fortran = { git = "https://github.com/jacobwilliams/json-fortran" }
複数のアプリケーションがある場合,どれか一つを[[executable]]として設定し,依存関係を記述すれば,その他全てのアプリケーションにもその依存関係が適用されます.
外部ライブラリとの依存関係も指定できます.それには,[build]の設定で用いていたlinkを利用します.
ただし,[[executable]]にはexternal-modulesの設定を記述できないため,アプリケーションのみで参照しているモジュールであっても,その名前は[build]にexternal-modulesを設けて記述する必要があります.
[build]
external-modules = "stdlib_error"
[[executable]]
name = "sample"
source-dir = "app"
main = "main.f90"
link = "stdlib"
テスト設定[[test]]
テストのビルドに関する設定を行います.設定の方法,設定可能な内容は実行ファイルの設定と全く同じです.違いは,設定項目の名前が,[[test]]に変わっていることだけです.
ディレクトリ等の指定
例えばtestではなくtests等にする場合,下記のように設定を記述します.
[[test]]
name = "test-1"
source-dir = "tests"
main = "check1.f90"
ディレクトリ名のみを変更することはできず,その中にあるメインルーチンが書かれたソースファイル名およびテストとしての名前を記述する必要があります.異なるディレクトリにあるメインルーチンも参照できます.
[[test]]
name = "test-1"
source-dir = "tests"
main = "check1.f90"
[[test]]
name = "test-2"
source-dir = "tests"
main = "check2.f90"
[[test]]
name = "test"
source-dir = "test"
main = "check.f90"
インラインテーブルを用いて簡潔に書くこともできます.ただし,インラインテーブルを用いると,依存関係の設定ができなくなります.
test = [
{name = "test-1",source-dir = "tests",main = "check1.f90"},
{name = "test-2",source-dir = "tests",main = "check2.f90"},
{name = "test",source-dir = "test",main = "check.f90"}
]
依存関係の記述
テストのみが必要とする外部fpmプロジェクトが存在した場合にも,[[test]]の設定が必要です.
テストのみが依存するプロジェクトを記述するには,少なくとも一つの[[test]]が必要です.これは標準のディレクトリ名testを用いていても,[build]の設定でauto-tests=trueにしていても必要です.現状では,依存関係の記述以外の理由で[[test]]を設定している場合を除いて,[dependencies]にまとめて書いておいた方が手間がありません.
[[test]]に続けて,[test.dependencies]の項目を記述します.書き方は,依存関係の設定と同じです.
[[test]]
name = "test-1"
source-dir = "test"
main = "check1.f90"
[test.dependencies]
test-drive = { git = "https://github.com/fortran-lang/test-drive" }
複数のテストがある場合,どれか一つを[[test]]として設定し,依存関係を記述すれば,その他全てのテストにもその依存関係が適用されます.
linkを利用して外部ライブラリとの依存関係も指定できます.[[test]]にはexternal-modulesの設定を記述できないため,テストのみで参照しているモジュールであっても,その名前は[build]にexternal-modulesを設けて記述する必要があります.
[build]
external-modules = "stdlib_logger"
[[test]]
name = "test-1"
source-dir = "test"
main = "check1.f90"
link = "stdlib"
デモ・サンプル設定[[example]]
デモ・サンプルのビルドに関する設定を行います.設定の方法,設定可能な内容は実行ファイルの設定と全く同じです.違いは,設定項目の名前が,[[example]]に変わっていることだけです.
ディレクトリ等の指定
デモ・サンプルのディレクトリ名をexampleではなくexamplesにする場合,下記のように設定を記述します.
[[example]]
name = "demo-1"
source-dir = "examples"
main = "demo1.f90"
ディレクトリ名のみを変更することはできず,その中にあるメインルーチンが書かれたソースファイル名およびデモ・サンプルとしての名前を記述する必要があります.異なるディレクトリにあるメインルーチンも参照できます.
[[example]]
name = "demo-1"
source-dir = "examples"
main = "demo1.f90"
[[example]]
name = "demo-2"
source-dir = "examples"
main = "demo2.f90"
インラインテーブルも利用できます.ただし,この書き方をすると,次の項で紹介する依存関係の設定ができなくなります.
example = [
{name = "demo-1",source-dir = "examples",main = "demo1.f90"},
{name = "demo-2",source-dir = "examples",main = "demo2.f90"}
]
依存関係の記述
デモ・サンプルのみが参照する外部fpmプロジェクトが存在した場合,[[example]]の設定が必要になります.依存するプロジェクトを記述するには,少なくとも一つの[[example]]が必要です.標準のディレクトリ名exampleを用いていても,[build]の設定でauto-examples=trueにしていても必要です.テストの場合と同様,依存関係の記述以外の理由で[[example]]を設定している場合を除いて,[dependencies]にまとめて書いておいた方が手間がありません.
[[example]]に続けて,[example.dependencies]の項目を記述します.書き方は,依存関係の設定と同じです.
[[example]]
name = "demo-1"
source-dir = "examples"
main = "demo1.f90"
[example.dependencies]
json-fortran = { git = "https://github.com/jacobwilliams/json-fortran" }
複数のデモ・サンプルがある場合,どれか一つを[[example]]として設定し,依存関係を記述すれば,その他全てのデモ・サンプルにもその依存関係が適用されます.
linkを利用して,外部ライブラリとの依存関係を指定できます.[[example]]にはexternal-modulesの設定を記述できないため,デモ・サンプルのみで参照しているモジュールであっても,その名前は[build]にexternal-modulesを設けて記述する必要があります.
[build]
external-modules = "stdlib_quadrature"
[[example]]
name = "demo-1"
source-dir = "examples"
main = "demo1.f90"
link = "stdlib"
インストール設定[install]
ライブラリをインストールの対象とするかを設定します.
標準では無効になっており,インストールされるのは実行ファイルのみです.ライブラリおよび.modファイルもインストールの対象とするには,library = trueとします.
[install]
library = true
コンパイラオプションの記述
現行バージョンでは,fpm.tomlにはコンパイラオプションを記述できません.
しかし,Google Summer of CodeでFortran-langの提案が採用され,開発が進められてきました.近い将来にはコンパイラオプションをfpm.tomlに記述できるようになる見込みです.
FortranCon2021で紹介された設定ファイルの記述方法は,下記のようになっています.
[profiles.debug.gfortran.linux]
flags="-g -Wall"
c_flags="-O1 -g"
link_time_flags="-xlinkopt"
files={"filename.f90"="-g -fcheck=all"}
複数のコンパイラを想定した書き方も示されていました.
name = "hello_world"
[profiles.gfortran.linux]
flags="-Wall"
[profiles.debug.gfortran.linux]
flags="-g -O1"
[profiles.debug.ifort.linux]
flags="-g -traceback"
まとめ
パッケージマネージャ兼ビルドツールであるfpmの設定ファイル(マニフェスト)の解説をしました.
現状では設定項目は少なく,最低限ビルドやリンクができるくらいですが,小規模な開発に用いるには十分な機能を持っています.一方で,ディレクトリを標準の名前から変更すると設定の煩わしさが跳ね上がるなど,少し設定を凝ろうとすると使い勝手が悪いところもあるので,意見をフィードバックして行きたいと思います.
プロジェクトの作成例については,次の記事で取り上げます.