概要
fpm(Fortran Package Manager) 0.5.0(執筆時点での最新バージョン)の使い方について解説します.
fpmの使い方について,これまでにQiitaに3本の記事を書いてきました.
- fpm (Fortran Package Manager)をBuilder兼Runnerとして利用する
- fpm (Fortran Package Manager)をBuilder兼Runnerとして利用する(続き1)
- fpm (Fortran Package Manager)をBuilder兼Runnerとして利用する(続き2)
使い方はそれほど変わっていませんが,色々と機能が追加されているので,fpmについて改めて解説します.
環境
- 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のドキュメントは https://fpm.fortran-lang.org に用意されています.プロジェクトの構成についてはPreparing your package for FPM,設定ファイルの解説はFortran package manager (fpm) manifest referenceにあります.
fpmのインストール
fpmのインストール方法は何通りかあります.
バイナリのダウンロード
一番簡単なのは,GitHubのリリースページからバイナリをダウンロードし,適切な場所に配置してパスを通すことです.
それ以外には,Conda, pacman, Spackを用いてインストールできます.
conda
conda config --add channels conda-forge
conda create -n fpm fpm
conda activate fpm
MSYS2
WindowsでMSYS2を用いている場合は,pacmanでインストールできます.
pacman -S mingw-w64-x86_64-fpm
Spack
spack install fpm
spack load fpm
fpmの使用法
fpmを用いたプロジェクト作成・ビルド・実行の流れ
上で解説したとおり,fpmは,プロジェクトの作成・ビルド・実行,テストやデモのビルド・実行を対象としています.
プロジェクトの作成・ビルド・実行を試してみます.
D:\> fpm new sample
+ mkdir sample
+ cd sample
+ mkdir sample\src
+ mkdir sample\app
+ mkdir sample\test
+ git init sample
Initialized empty Git repository in D:/sample/.git/
fpm: Leaving directory 'D:'
D:\> cd sample
D:\sample> fpm build
+ mkdir build\dependencies
+ mkdir build\gfortran_2A42023B310FA28D
+ mkdir build\gfortran_2A42023B310FA28D\sample\
+ gfortran -c .\.\src\sample.f90 -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds -fcheck=array-temps -fbacktrace -fcoarray=single -J build\gfortran_2A42023B310FA28D -Ibuild\gfortran_2A42023B310FA28D -o build\gfortran_2A42023B310FA28D\sample\src_sample.f90.o
+ lib /OUT:build\gfortran_2A42023B310FA28D\sample\libsample.a @build\gfortran_2A42023B310FA28D\sample\libsample.a.resp
Microsoft (R) Library Manager Version 14.00.24234.1
Copyright (C) Microsoft Corporation. All rights reserved.
build/gfortran_2A42023B310FA28D/sample/src_sample.f90.o
+ gfortran -c app\main.f90 -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds -fcheck=array-temps -fbacktrace -fcoarray=single -J build\gfortran_2A42023B310FA28D -Ibuild\gfortran_2A42023B310FA28D -o build\gfortran_2A42023B310FA28D\sample\app_main.f90.o
+ mkdir build\gfortran_2A42023B310FA28D\app\
+ gfortran -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds -fcheck=array-temps -fbacktrace -fcoarray=single build\gfortran_2A42023B310FA28D\sample\app_main.f90.o build\gfortran_2A42023B310FA28D\sample\libsample.a -o build\gfortran_2A42023B310FA28D\app\sample.exe
D:\sample> fpm run
Hello, sample!
fpmにはいくつかのサブコマンドがあります.上の例では,new
, build
, run
サブコマンドを使いました.
プロジェクトの作成
fpmのプロジェクトを新規に作成するには,fpm new
を用います.
fpm new プロジェクト名
fpm new
を実行すると,下記のような構造のディレクトリが作成されます.これがfpmの基本的なプロジェクトの構造です.
.
├── .git
├── app
│ └── main.f90
├── src
│ └── sample.f90
├── test
│ └── check.f90
├── fpm.toml
└── README.md
また,ファイルの内容はそれぞれ次のようになっています.
app\main.f90
program main
use sample, only: say_hello
implicit none
call say_hello()
end program main
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
test\check.f90
program check
implicit none
print *, "Put some tests in here!"
end program check
fpm.toml
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 = true
README.md
# sample
My cool new project!
fpmのプロジェクト構造とディレクトリは関係しており,それぞれ役割があります.
-
app
: メインルーチン -
src
: モジュール群 -
test
: 単体テスト -
example
: デモ・サンプル
app
ディレクトリには,メインルーチンを配置します.fpmでビルドをすると,このメインルーチンがビルドされて実行ファイル(アプリケーション)が作成されます.
src
ディレクトリには,プロジェクトで利用するモジュール群を配置します.このモジュール群は,fpmでビルドするとライブラリとなり,app
ディレクトリに置かれたメインルーチンにリンクされます.つまり,app
ディレクトリには基本的にメインルーチン以外のファイルは置かず,メインルーチンから参照されるモジュールは,全てsrc
に配置します.
ライブラリを開発するようなプロジェクトでは,app
ディレクトリは不要でsrc
ディレクトリがプロジェクトの中心になります.
test
ディレクトリには,src
に置かれるモジュール内の単体機能テストを配置します.ここには複数のメインルーチンを配置できるので,テストごとにメインルーチンを作成すると,テストが楽になります.テストが失敗した際にerror stop
でプログラムの実行を止めることによって,テストの成否を判定できるようになります.メインルーチンのファイル名が実行ファイルの名前になります.
example
ディレクトリには,デモプログラムを配置します.ライブラリ内で定義される機能の使用例を作成できるので,特にライブラリを開発するプロジェクトで非常に有効に利用できます.
各ディレクトリの名前は変更できますが,標準の名前を用いてれば,その中のソースが自動的に探されて,ビルドされます.
ディレクトリの名前を変更する場合,その設定はfpm.toml
に記述します.詳しくは次の記事で説明します.
プロジェクト作成のより詳しい説明
説明を展開
ライブラリを作成するのにapp
ディレクトリは必要ありません.プロジェクトの用途に応じて作成するディレクトリを指定するには,オプションでfpm new
コマンドのオプションで指定します.
-
--lib
もしくは--src
src
ディレクトリが作成され,その中にプロジェクト名.f90
が作られます. -
--app
app
ディレクトリが作成され,その中にmain.f90
が作られます. -
--test
test
ディレクトリが作成され,その中にcheck.f90
が作られます. -
--example
example
ディレクトリが作成され,その中にdemo.f90
が作られます. -
--full
全てのディレクトリを作成します.
例えば,ライブラリを開発するプロジェクトで,テストやデモを同時に作成する場合には,
fpm new ライブラリ名 --lib --test --example
とします.
既存のプロジェクトにディレクトリを追加する場合は,--backfill
オプションを併用します.例えば,オプションなしで作ったプロジェクト(app
, src
, test
ディレクトリをもつ)にexample
ディレクトリを追加するには,
fpm new 既存プロジェクト名 --example --backfill
とします.--backfill
オプションがないと,プロジェクトが既に存在することがエラーメッセージとして表示されます.
D:\> fpm new sample --example
<ERROR> sample already exists.
perhaps you wanted to add --backfill ?
fpm: Leaving directory 'D:'
D:\> fpm new sample --example --backfill
backfilling sample
+ cd sample
<INFO> sample\README.md already exists. Not overwriting
+ mkdir sample\example
<INFO> sample\fpm.toml already exists. Not overwriting
+ git init sample
Reinitialized existing Git repository in D:/sample/.git/
fpm: Leaving directory 'D:'
example\demo.f90
program demo
implicit none
print *, "Put some examples in here!"
end program demo
ここまでに紹介してきたオプションとは逆に,ディレクトリを何も作成しないようにするオプションも用意されています.--bare
オプションを付けると,プロジェクトディレクトリとその中にfpm.toml
, README.md
が作成されます.
プロジェクトのビルド
fpmのプロジェクトをビルドするには,fpm build
を用います.
fpm build
fpm build
を実行すると,build
ディレクトリが作成され,その中でビルドが行われます.
fpm build
には,ビルドに関わるオプションがいくつかあります.
-
--profile ビルドプロファイル
ビルドプロファイルを選択します.現状では,debug
とrelease
が用意されています.debug
プロファイルはデバッグに関係するオプションが自動で付与されます.release
プロファイルは,高い最適化オプションが付与されます.
このオプションを省略すると,debug
プロファイルが選択されます. -
--compiler コンパイラ名
コンパイラ名(実行コマンド名)を指定します.
オプションを省略したとき,環境変数FPM_FC
にコンパイラ名が設定されていればそれが選択されます.標準ではgfortran
が選択されます. -
--flag "コンパイラオプション"
ビルド時にコンパイラに渡すオプションを文字列で指定します.このオプションのみを指定すると,debug
プロファイルが適用されず,指定したコンパイラオプションのみが適用されます.--profile
オプションと併用すると,指定したコンパイルオプションとプロファイルによって指定されるオプションが併用されます.--flag
オプションを省略したとき,環境変数FPM_FFLAGS
が設定されていれば,それが利用されます.
例えば,Intel Fortranを用いてreleaseビルドを行いつつ,インクルードディレクトリ(プロジェクトディレクトリ直下にinclude
を作ったと仮定)やプリプロセスを有効にするには,
fpm build --compiler ifort --profile release --flag "/Iinclude /fpp"
を実行します.(fpmは,コンパイラにオプションを渡さなくても,プロジェクトディレクトリ直下のinclude
ディレクトリを標準のインクルードディレクトリとして取り扱います.)
プロジェクトビルドのより詳しい説明
説明を展開
fpmのビルドは,他のビルドツールとは挙動が異なります.fpmは,ビルド時のオプションに応じて出力ディレクトリ名が変化します.
例えば,fpm build
でビルドすると,中間ファイルや.modファイル,ライブラリ,実行ファイルはbuild\gfortran_2A42023B310FA28D
に出力されます.fpm build --compiler ifort
を実行し,Intel Fortranを用いてビルドすると,出力ディレクトリはbuild\ifort_782887A201FCE169
に変化します.
.
├── .git
├── app
│ └── main.f90
├── build
│ ├── dependencies
│ ├── gfortran_2A42023B310FA28D
│ │ ├── app
│ │ │ └── sample.exe
│ │ ├── sample
│ │ │ ├──app_main.f90.o
│ │ │ :
│ │ │
│ │ └── test
│ │ └── check.exe
│ └── ifort_782887A201FCE169
│ ├── app
: :
後で説明しますが,fpm run
やfpm test
で実行ファイルを実行するにも,これらのディレクトリ名を認識する必要があります.そのため,fpm run
やfpm test
でもfpm build
と同じオプションを指定しなければなりません.
fpm build
には先に紹介したオプション以外にも,いくつかオプションがあります.
-
--c-compiler コンパイラ名
Cコンパイラ(実行コマンド名)を指定します.
オプションを省略したとき,環境変数FPM_CC
にコンパイラ名が設定されていればそれが選択されます.標準決まっておらず,自動で決定されます. -
--c-flag "コンパイラオプション"
ビルド時にCコンパイラに渡すオプションを文字列で指定します.オプションを省略したとき,環境変数FPM_CFLAGS
が設定されていれば,それが利用されます. -
--archiver アーカイバ名
複数のファイルをまとめて一つのライブラリを作成するアーカイバを指定します.オプションを省略したとき,環境変数FPM_AR
が設定されていれば,それが利用されます. -
--link-flag "リンクオプション"
リンカに渡すオプションを指定します.オプションを省略したとき,環境変数FPM_LDFLAGS
が設定されていれば,それが利用されます. -
--list
ビルドせずに,ビルドによって作られるファイルを一覧で表示します. -
--tests
全てのテストをビルドします. -
--show-model
ビルドせずに,fpmのビルド設定(build_model_t
)を表示します.
ビルドしたアプリケーションの実行
fpmのプロジェクトをビルドした際に作成される実行ファイル(アプリケーションやテスト,デモ)を実行するには,下記のコマンドを実行します.
fpm run
fpm run
を実行すると,アプリケーション(app
ディレクトリに置かれたメインルーチンをビルドして作られた実行ファイル)が実行されます.
fpm run
で実行するアプリケーションに引数を渡す場合は,コマンドの後ろに--
を付け,スペースを空けてコマンドライン引数を列挙します.
例えば,プロジェクトの名前がsampleで,ビルドによってsample.exe
が作られる場合,
fpm run -- a b c
を実行すると,実行ファイルにコマンドライン引数a b c
が渡され,
sample.exe a b c
を実行したことと同じになります.
fpm run
には,fpm build
と同じオプション(--profile
, --compiler
, --flag
など)が利用できます.その理由はプロジェクトビルドのより詳しい説明で説明していますが,簡単には,fpm run
を実行するときは,fpm build
と同じオプションが必要と覚えてください.
つまり,
fpm build --compiler ifort --profile release --flag "/Iinclude /fpp"
でビルドしたアプリケーションを実行するには,
fpm run --compiler ifort --profile release --flag "/Iinclude /fpp"
を実行します.
アプリケーション実行のより詳しい説明
説明を展開
プロジェクトに複数のアプリケーションが存在する場合,--target アプリケーション名
で実行するアプリケーションを指定します.実行可能なアプリケーション名を確認するには,--list
オプションを利用します.
D:\sample> fpm run --list
Matched names:
sample
D:\sample> fpm run --target sample
Hello, sample!
--all
オプションを付けると,全てのアプリケーションを実行します.
example
ディレクトリの中で作成されたライブラリの使用例やデモプログラムも,fpm run
で実行します.これらを実行するには,--example
オプションを利用します.上で紹介した--list
, --target
, --all
は,--example
オプションと併用できます.
D:\sample> fpm run --example --list
Matched names:
demo
D:\sample> fpm run --example --target demo
Put some examples in here!
説明してきたオプションとは少し毛色が変わりますが,--runner
オプションを利用することで,アプリケーションを参照するプログラム・コマンドを選択できます.
例えば,デバッガgdbでsample.exe
のデバッグを実行したい場合,
fpm run --runner gdb
を実行します.
D:\sample> fpm run --runner gdb
GNU gdb (GDB) 10.2
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-w64-mingw32".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from build\gfortran_2A42023B310FA28D\app\sample.exe...
(gdb)
Windowsでfpm run --runner dir
を実行すると,sample.exe
の情報が表示されます.この--runner
オプションの用途は他にもあり,Unix系のOSでfpm run --runner time
を実行すると,実行時間を計測できます.
テストの実行
テストを実行するには,下記のコマンドを実行します.
fpm test
fpm test
もfpm run
と同様に,fpm build
と同じオプション(--profile
, --compiler
, --flag
など)が利用できます.その理由はプロジェクトビルドのより詳しい説明で説明しています.
fpm test
では,fpm build
とは状況が異なる場合があります.テストを作成するためにテスト用の外部fpmプロジェクトを利用し,その外部プロジェクトが要求するオプションを付ける必要が生じるといった状況です.fpm build
で必要とするオプションに加えて,fpm test
で必要になるオプションもあることから,fpm test
を実行するときは,少なくともfpm build
と同じオプションが必要と覚えてください.
プロジェクトのビルドに
fpm build --compiler ifort --profile release --flag "/Iinclude /fpp"
を用いた場合,テストには,
fpm test --compiler ifort --profile release --flag "/Iinclude /fpp"
を利用します.test
ディレクトリ内のソースファイルのビルドに他のオプションが必要な場合など,必要に応じてオプションを追加します.
テストのより詳しい説明
説明を展開
fpm test
では,ビルドしたアプリケーションの実行で説明したfmp run
と同じオプションが利用できます.
プロジェクトに複数のテストが存在する場合,--list
オプションでテストの一覧を確認し,--target アプリケーション名
で実行するテストを指定します.ただし,fpm test
は標準で全てのテストを実行するので,--all
オプションはありません.
D:\sample> fpm test
Put some tests in here!
D:\sample> fpm test --list
Matched names:
check
D:\sample> fpm test --target check
Put some tests in here!
ビルドしたターゲットのインストール
fpmのプロジェクトをビルドすると,アプリケーションもしくはライブラリ(併せてターゲットと称する)が作成されます.そのターゲットをインストールするには,
fpm install
を実行します.
fpm install
は,ターゲットによって挙動が変化します.
- ターゲットが実行ファイルの場合は,インストールディレクトリ直下に
bin
ディレクトリを作成し,その中に実行ファイルをコピーします. - ターゲットがライブラリの場合,インストールディレクトリ直下に
lib
およびinclude
ディレクトリを作成します.lib
ディレクトリにライブラリを,include
ディレクトリ内に.mod
ファイルをコピーします.
標準ではライブラリはインストールされません.ライブラリをインストールするには,設定ファイルfpm.toml
にその設定を書く必要があります.
[install]
library = true
インストールディレクトリ等を指定するには,fpm install
のオプションを利用します.ここで,fpm install
で指定するディレクトリのパスは,全て区切りに/
を用います.(コンパイラオプションで指定するディレクトリパスは,OSのセパレータの設定に沿います)
-
--prefix インストールディレクトリ
インストールディレクトリを指定します.絶対パスでも相対パスでも指定できます.
標準のインストールディレクトリは,Unix系OSの場合$HOME/.local
,Windowsの場合は%APPDATA%\local
です. -
--bindir バイナリディレクトリ名
実行ファイルをコピーするサブディレクトリ(インストールディレクトリ直下)の名前を指定します.
標準はbin
です. -
--libdir ライブラリディレクトリ名
ライブラリファイルをコピーするサブディレクトリ(インストールディレクトリ直下)の名前を指定します.
標準はlib
です. -
--includedir インクルードディレクトリ名
.mod
ファイルをコピーするサブディレクトリ(インストールディレクトリ直下)の名前を指定します.
標準はinclude
です.
fpm install
も,fpm run
やfpm test
と同様にfpm build
と同じオプション(--profile
, --compiler
, --flag
など)が利用できます.詳しい理由はプロジェクトビルドのより詳しい説明で説明していますが,ビルドしたターゲットがどのディレクトリにあるかを認識するためです.
fpm build --compiler ifort --profile release --flag "/Iinclude /fpp"
でビルドしたアプリケーションやライブラリをインストールするには,
fpm install --compiler ifort --profile release --flag "/Iinclude /fpp"
を実行する必要があります.必要があれば,--prefix
などのオプションを付与します.
インストールのより詳しい説明
説明を展開
プロジェクトにターゲットが存在する場合,--list
オプションでターゲットを確認できます.ただし,--target
オプションはなく,オプションでインストールするターゲットを選択できません.標準では実行ファイルをインストールするようになっており,ライブラリをインストールするには,設定ファイルfpm.toml
にその設定を書く必要があります.
--no-rebuild
オプションを付けると,インストール時にプロジェクトをリビルドせず,既存のターゲットをコピーします.
--verbose
オプションを付けるとインストールの際にコンパイラやオプションなどの情報を出力します.
D:\sample> fpm install --prefix build
# Update: build\gfortran_2A42023B310FA28D\sample\libsample.a -> build\lib
1 個のファイルをコピーしました。
# Update: build\gfortran_2A42023B310FA28D\sample.mod -> build\include
1 個のファイルをコピーしました。
# Update: build\gfortran_2A42023B310FA28D\app\sample.exe -> build\bin
1 個のファイルをコピーしました。
D:\sample> fpm install --prefix build --verbose
<INFO> BUILD_NAME: build\gfortran
<INFO> COMPILER: gfortran
<INFO> C COMPILER: gcc
<INFO> COMPILER OPTIONS: -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds -fcheck=array-temps -fbacktrace -fcoarray=single
<INFO> C COMPILER OPTIONS:
<INFO> LINKER OPTIONS:
<INFO> INCLUDE DIRECTORIES: []
# Update: build\gfortran_2A42023B310FA28D\sample\libsample.a -> build\lib
# Run: copy "build\gfortran_2A42023B310FA28D\sample\libsample.a" "build\lib"
1 個のファイルをコピーしました。
# Update: build\gfortran_2A42023B310FA28D\sample.mod -> build\include
# Run: copy "build\gfortran_2A42023B310FA28D\sample.mod" "build\include"
1 個のファイルをコピーしました。
# Update: build\gfortran_2A42023B310FA28D\app\sample.exe -> build\bin
# Run: copy "build\gfortran_2A42023B310FA28D\app\sample.exe" "build\bin"
1 個のファイルをコピーしました。
まとめ
パッケージマネージャ兼ビルドツールであるfpmの使い方を説明しました.
fpmにはサブコマンドが用意されており,そのサブコマンド付きで実行する事により,プロジェクトを制御します.
-
fpm new
: プロジェクトを作成する. -
fpm build
: プロジェクトをビルドする. -
fpm run
: ビルドしたアプリケーションを実行する. -
fpm test
: プロジェクトのテストを実行する.
fpmのプロジェクトでは,ライブラリ,アプリケーション,テスト,デモ・サンプルをビルドできます.
fpmはビルドの方法に特徴があり,ビルドのオプションに応じて出力ディレクトリが変化します.そのため,実行,テストでもビルドと同じオプションが必要になります.
fpmのプロジェクトは,fpm.toml
に設定を記述します.設定の書き方はfpm (Fortran Package Manager)の設定ファイルの解説で解説しています.