12
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

FortranAdvent Calendar 2021

Day 13

fpm (Fortran Package Manager)の使い方

Last updated at Posted at 2021-12-12

概要

fpm(Fortran Package Manager) 0.5.0(執筆時点での最新バージョン)の使い方について解説します.

fpmの使い方について,これまでにQiitaに3本の記事を書いてきました.

使い方はそれほど変わっていませんが,色々と機能が追加されているので,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 ビルドプロファイル
    ビルドプロファイルを選択します.現状では,debugreleaseが用意されています.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 runfpm testで実行ファイルを実行するにも,これらのディレクトリ名を認識する必要があります.そのため,fpm runfpm 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 testfpm 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 runfpm 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)の設定ファイルの解説で解説しています.

12
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?