概要
本記事では,fpmのインストールと,簡単な使い方を解説します.
fpm (Fortran Package Manager)は,Fortran-langプロジェクトの一環として開発されているパッケージマネージャです.将来的には,リモートにあるリポジトリを取得して,ビルド,インストールするところまでを目指しています.また,ユーザがビルドシステムの設定で悩まないよう,プロジェクトの構造を標準化することも目指しています.
Fortran-langプロジェクトがFortranに関するプロジェクトの調査をしていますが,パッケージマネージャとして機能するのはしばらく先になりそうです.一方,fpmの機能を確認すると,プロジェクトのビルドや実行を短いコマンドで実現できる,Builder兼Runnerとしては使えることが判りました.
追記:
バージョン0.5.0での使い方を別記事にまとめました.
- fpm (Fortran Package Manager)の使い方
- fpm (Fortran Package Manager)の設定ファイルの解説
- fpm (Fortran Package Manager)のプロジェクトの作成例
環境
- Ubuntu 18.04
- fpm prototype version
- gfortran 7.5
- Haskell stack 2.3.1
- git 2.17.1
fpmのインストール
fpmはHaskellで記述されており,インストールにもHaskell (Haskell Stack)が使われます.
インストール手順は公式のREADMEに大体書いてあるのですが,必要なライブラリについては漏れがあるので,それも含めたインストール手順を記します.
fpmのインストール時にはgitを使うので,gitは事前にインストールしておいてください.また,fpmはプロジェクトのビルドにgfortranを利用するので,gfortranについても事前にインストールしておいてください.
- GNU Multiple Precision Arithmetic Library Developers Toolsのインストール
- Haskell Stackのダウンロードと展開
- fpmのインストール
fpmのREADMEには,必要なソフトウェアの要件が書かれていませんが,GNU Multiple Precision Arithmetic Library (GMP)がないとHaskell Stackのインストール時にエラーが出るので,予めインストールしておきます.
Linking /home/hoge/.stack/setup-exe-cache/x86_64-linux/tmp-Cabal-simple_mPHDZzAJ_2.4.0.1_ghc-8.6.5 ...
/usr/bin/ld.gold: エラー: -lgmp が見つかりませ
GNU Multiple Precision Arithmetic Library Developers Toolsのインストール
GMP Developers Toolsのインストールをインストールします.
Ubuntuを利用している場合は,apt
で簡単にインストールできます.
$ sudo apt install libgmp-dev
Haskell Stackのダウンロードと展開
Haskell Stackのtar.gz
ファイルをダウンロードし,展開した後,パスを通しておきます.著者は,ホームディレクトリの下にlib
フォルダを作り,そこにダウンロードして展開しました.
$ cd ~
$ mkdir lib
$ cd lib
$ wget https://get.haskellstack.org/stable/linux-x86_64-static.tar.gz
$ tar xaf linux-x86_64-static.tar.gz
$ cd linux-x86_64-static
$ export PATH=$PATH:`pwd`
fpmのインストール
GitHubからfpmのリポジトリをクローンし,stackを利用してbuildします.このとき,GHC (The Glasgow Haskell Compiler)のダウンロードも行われるので,かなり時間がかかります.気長に待ちましょう.
$ cd ~/lib
$ git clone https://github.com/fortran-lang/fpm
$ cd fpm
$ stack build
fpmのビルドが完了すると,実行ファイルは異様に長いパスに置かれます.それを使いやすい場所にコピーするために,次のコマンドを実行します.
$ stack install
実行すると,以下のようなメッセージが出力され,ビルドされたfpmの実行ファイルが,~/.local/bin
にコピーされた事が判ります.
Copied executables to /home/hoge/.local/bin:
- fpm
このフォルダにもパスを通しておきます.
$ export PATH=$PATH:~/.local/bin
これでインストールは完了です.
fpmによるビルドと実行
fpmのパッケージングレイアウト
fpmでは,用途に応じて3通りのパッケージングの方法を提供しています.
- アプリケーション(実行ファイルのみを生成)
- ライブラリ(静的ライブラリのみを生成)
- アプリケーションとライブラリ
これらは,ディレクトリ構造が異なるだけです.
また,パッケージ情報をfpm.toml
ファイルに記述します.
fpm.toml
ファイルには,プログラムの名前やバージョン,ライセンス情報などを記述できます.プログラム名(コンパイルした際の実行ファイルの名前)は必須ですが,それ以外は必須ではありません.
name = "hello"
詳しくは,公式のPreparing your package for FPMを読んでください.
アプリケーション
アプリケーションは,下記のようなディレクトリ構造で管理されます.
project dir
├── app
│ └── main.f90
└── fpm.toml
必要なのは,main.f90
とfpm.toml
のみです.プロジェクトのディレクトリ直下にapp
ディレクトリとfpm.toml
を置き,ソースファイルをapp
ディレクトリ直下に置きます.このとき,ソースファイル名は,必ずmain.f90
です.
公式のサンプルと同様にhello worldを作ってみると,下記のようになります.
hello
├── app
│ └── main.f90
└── fpm.toml
name = "hello"
program main
implicit none
print *, "hello, world"
end program main
プログラムのビルドは,プロジェクトのディレクトリで次のコマンドを実行します.
$ fpm build
# gfortran (for build/gfortran_debug/app/main.o)
# gfortran (for build/gfortran_debug/app/hello)
プロジェクトをビルドすると,プロジェクトディレクトリ直下にbuild\gfortran_debug\app
ディレクトリが作られ,その中に実行ファイルが作成されます.実行ファイルの名前は,fpm.toml
のname
で指定した名前です.
ビルドしたプログラムは,fpm run
で実行できます.
$ fpm run
hello, world
ライブラリ
ライブラリの場合はディレクトリ構造が若干変わります.
project dir
├── fpm.toml
└── src
└── module source files
このとき,fpm.toml
に書いた名前は,静的ライブラリ(*.a
ファイル)の名前(頭にlibが追加されます)として使われます.
const
├── fpm.toml
└── src
└── math_constants.f90
name = "const"
module math_constants
use, intrinsic :: iso_fortran_env
implicit none
real(real64),parameter :: PI = acos(-1d0)
end module math_constants
ビルドはアプリケーションの場合と同様に,プロジェクトのディレクトリでfpm build
を実行します.
$ fpm build
# gfortran (for build/gfortran_debug/const/math_constants.o build/gfortran_debug/const/math_constants.mod)
# ar (for build/gfortran_debug/const/libconst.a)
ar: build/gfortran_debug/const/libconst.a を作成しています
プロジェクトディレクトリ直下にbuild\gfortran_debug\const
(fpm.toml
のname
で指定した名前の)ディレクトリが作られ,lib+nameで指定した名前.a
の静的ライブラリが作成されました.
アプリケーションとライブラリ
別ファイルでモジュールを作成し,メインルーチンからそれらを読み込む場合には,このディレクトリ構造を用います.これは非常に単純で,アプリケーションとライブラリのディレクトリ構造を合わせた構造です.
project dir
├── app
│ └── main.f90
├── fpm.toml
└── src
└── module source files
このとき,fpm.toml
のname
で指定するのは実行ファイルの名前ですが,静的ライブラリの名前にも使われます.
公式に類似した,以下のようなサンプルを作ってみました.
app_and_lib
├── app
│ └── main.f90
├── fpm.toml
└── src
└── math_constants.f90
name = "app_and_lib"
program main
use :: math_constants, only: PI, PI05, PI2
implicit none
print *, "application and static library demo"
print *, "π = ", PI
print *, "π/2 = ", PI05
print *, "2π = ", PI2
end program main
module math_constants
use, intrinsic :: iso_fortran_env
implicit none
real(real64),parameter :: PI = acos(-1d0)
real(real64),parameter :: PI2 = PI * 2.0_real64
real(real64),parameter :: PI05 = PI * 0.5_real64
end module math_constants
ビルドと実行は,アプリケーションのときと何も変わりません.
$ fpm build
# gfortran (for build/gfortran_debug/app_and_lib/math_constants.o build/gfortran_debug/app_and_lib/math_constants.mod)
# ar (for build/gfortran_debug/app_and_lib/libapp_and_lib.a)
ar: build/gfortran_debug/app_and_lib/libapp_and_lib.a を作成しています
# gfortran (for build/gfortran_debug/app/app_and_lib)
$ fpm run
application and static library demo
π = 3.1415926535897931
π/2 = 1.5707963267948966
2π = 6.2831853071795862
階層化されたモジュール
複数のモジュールが関係し,モジュールに階層構造がある場合は,モジュール名に独自のルールが設けられます.
multi_level_module
├── app
│ └── main.f90
├── fpm.toml
└── src
├── math_constants
│ ├── derived.f90
│ └── fundamental.f90
└── math_constants.f90
name = "multi_level_module"
module math_constants
use :: math_constants_fundamental, only: PI
use :: math_constants_derived, only: PI05, PI2
end module math_constants
module math_constants_fundamental
use, intrinsic :: iso_fortran_env
implicit none
real(real64),parameter :: PI = acos(-1d0)
end module math_constants_fundamental
module math_constants_derived
use, intrinsic :: iso_fortran_env
use :: math_constants_fundamental, only: PI
implicit none
real(real64),parameter :: PI2 = PI * 2.0_real64
real(real64),parameter :: PI05 = PI * 0.5_real64
end module math_constants_derived
main.f90
は前の例と同じです.
モジュールの名前付けにはルールがあり,math_constants.f90
ではモジュール名をmath_constants
とします.
src/math_constants/derived.f90
とfundamental.f90
は,それぞれモジュール名をmath_constants_derived
とmath_constants_fundamental
にしなければなりません.
src
ディレクトリのサブディレクトリに置かれたモジュールの名前は,src
以下のサブディレクトリ名をアンダースコア_
で順次つないでいき,最後にファイル名で終わります.
モジュールをsrc/a/b/c/d.f90
で定義するとき,モジュール名はa_b_c_d
になるということです.
公式のサンプルとほとんど同じなのですが,これをビルドしてみるとエラーが出ます.
$ fpm build
# gfortran (for build/gfortran_debug/multi_level_module/math_constants_derived.o build/gfortran_debug/multi_level_module/math_constants_derived.mod)
# gfortran (for build/gfortran_debug/multi_level_module/math_constants.o build/gfortran_debug/multi_level_module/math_constants.mod)
# gfortran (for build/gfortran_debug/multi_level_module/math_constants_fundamental.o build/gfortran_debug/multi_level_module/math_constants_fundamental.mod)
src/math_constants.f90:3:10:
use :: math_constants_fundamental, only: PI
1
Fatal Error: Can't open module file ‘math_constants_fundamental.mod’ for reading at (1): そのようなファイルやディレクトリはありません
compilation terminated.
恐らく,依存性解析に失敗し,必要なモジュールのmod
ファイルが作られる前に,別のモジュールのコンパイルを行おうとして,失敗したと考えられます.もう一度実行すると,ビルドに成功します.1回目のビルドでいくつかのmod
ファイルが作られるので,2回目は既に作られたmod
ファイルを参照してコンパイルできるからです.
$ fpm build
# gfortran (for build/gfortran_debug/multi_level_module/math_constants_fundamental.o build/gfortran_debug/multi_level_module/math_constants_fundamental.mod)
# gfortran (for build/gfortran_debug/multi_level_module/math_constants_derived.o build/gfortran_debug/multi_level_module/math_constants_derived.mod)
# gfortran (for build/gfortran_debug/multi_level_module/math_constants.o build/gfortran_debug/multi_level_module/math_constants.mod)
# ar (for build/gfortran_debug/multi_level_module/libmulti_level_module.a)
ar: build/gfortran_debug/multi_level_module/libmulti_level_module.a を作成しています
# gfortran (for build/gfortran_debug/app/main.o)
# gfortran (for build/gfortran_debug/app/multi_level_module)
$ fpm run
multi-level module demo
π = 3.1415926535897931
π/2 = 1.5707963267948966
2π = 6.2831853071795862
モジュールの参照エラーであれば,何回かfpm build
を実行すればそのうち成功するでしょう.
まとめ
fpmはまだまだ開発途上ですが,簡単なプログラムのビルドおよび実行に使えることは判りました.
ビルドの補助ツールとしてはcmakeもありますが,CMakeLists.txt
はfpm.toml
ほど気軽には書けませんし,Makefileを作ったあとにmakeも必要になります.簡単な設定とコマンドで実行できるfpmは,Builder兼Runnerとしては非常に手軽で魅力的です.
今後の進展が楽しみです.fpmの進展を待つだけでなく,プロジェクトの構造についても,この機会に見直したいと思います.