自由なソフトウェアのビルドにはGNUのautoconf
やautomake
などを用いたビルドシステム(configure
というシェルスクリプトを実行するもの)や、OSごとのビルド環境に対応したクロスプラットフォームなCMakeなどが広く用いられているが、GNOME系のソフトウェアを中心としてMesonというビルドシステムの利用が広がっている。
開発自体は2012年末から個人のプロジェクトとして始まったものだが、本記事公開時点では、既に多数の貢献者に支えられる規模となり、普及についても、Mesa, systemd, X.OrgのサーバなどGNU/Linuxのデスクトップ用途で欠かせないプロジェクトでのビルドに使用できるようになっており、Mesonのみにしか対応しないプロジェクトも出てきている。
Mesonは高レベルなビルドシステムで、前述した他のビルドシステムも含めて “メタビルドシステム” と分類されることもある。
特徴
ビルドのみを行うユーザと開発者の両方からみた特徴
- CMakeと同様、OSごとのビルド環境に合わせた挙動をするため、クロスプラットフォームなソフトウェアの開発にも適する
autoconf
/automake
などのツール群(“autotools” とも呼ばれる)によるビルドシステムとは異なり(またCMakeと同様)、シェルを呼び出すことはなく、チェックやビルド設定の処理は高速で短時間で終了する- ソースツリーが大規模なプロジェクトでは
configure
スクリプト内の色々な処理、特に多数のMakefile
をMakefile.in
からそれぞれ生成するあたりの段階でかなり時間を食うが、そのような長い待ち時間はない - プロジェクトによっては開発版のソースを取得した場合などに
autogen.sh
などの名前のシェルスクリプトを通してautoconf
などを実行する必要がある場合があり、時間がかかる上に古いプロジェクトだとツールのバージョンの違いでエラーが出たりすることもあるが、そのようなことはない[1]
- ソースツリーが大規模なプロジェクトでは
- GNU/Linuxではビルド時に
make
より処理が速い低レベルビルドシステムNinjaがバックエンドとして用いられ、複数のCPUコアがある場合に既定ではその数に応じて同時に動かすプロセスの数が調整される- Ninjaは、ソースツリーが大規模なプロジェクトにおいてあるファイルが変更された後に必要な部分のみをビルドしようとするのに時間がかかるのを防ぐ設計なので、そのような意味での恩恵もある
- ただしNinjaをバックエンドとして用いる機能はCMakeも搭載しており、
-G Ninja
オプションを付ければCMakeを用いたプロジェクトでもビルドに使えるため、後述の “Unity build” 機能を使用しなければCMakeと比べてビルド時間が大幅に短くなるとは考えにくい - ビルド時に使用されるバックエンドとしてはmacOSやWindows向けのビルドツールにも対応しているが、各OS向けにビルドされたNinjaを用いることが推奨される
- Python 3で書かれており、
pip3
でインストールできる- Python標準付属のモジュールのみで書かれているため、Python用のパッケージの依存関係が問題になることはなく、インストール自体もPythonが入っていればすぐに終わる
- PyPyのPython 3互換バージョンでも動作可
- Windowsでは環境変数PATHにPythonとそのスクリプト用の2つのディレクトリを追加して
pip3
でmeson
を指定してインストールするが、公式配布の.msiパッケージ(Ninjaも付属)をインストールしてPATHにインストール先を指定してmeson.exe
を実行する形の使い方もできる
- 複数のソースファイル群から成るターゲットのビルドにおいて、個別のファイルをコンパイルする代わりに一連のソースファイル群をまとめた中間ソースファイルを作ってそれをコンパイルすることで、ビルド時間の短縮やコンパイラのソースファイル単位の最適化の効果を出しやすくする “Unity build” と呼ばれる機能があり、標準では無効(
--unity=on
オプションで有効になる)- 後からソースを変更したときの追加コンパイルされる量が増えるため、開発者がソースを編集する段階で使用するのには向かない
- ビルド時の必要メモリ量が増加するため、システムのメモリ量とプログラムの規模によってはメモリ使用量が多くなり過ぎて問題になる可能性がある
- 同じ名前の変数や関数などが複数ファイルにそれぞれ存在した場合にそれらの衝突(再定義)によるビルドエラーなどの問題が発生する可能性がある
- Unity buildが有効で正常に動作することが十分に確認されているプロジェクトでは問題はなく、使用が推奨される場合もある
- CMakeでも手動でUnity buildの実装を行うこと自体は可能で、Web上にサンプルもあるが、書くのに手間がかかる上に記述量も多くなる
- ビルド時に機能を有効もしくは無効にするなどの設定の定義は専用のファイルに書かれており、プログラムの利用者はそのファイルを参照するだけで設定可能項目について把握でき、開発者にとっても扱いやすい
- クロスコンパイル用の定義ファイルを用意し、それを
meson
コマンドに対して--cross-file
オプションで指定することで、クロスコンパイルの実行が簡単に行える(クロスコンパイラは別途用意する) ccache
が利用可能な場合に自動的に使用する機能がある
PyPyについては
を参照。
ソフトウェアの開発者からみた特徴
Mesonを用いているプロジェクトはソースツリーにmeson.build
というファイルがあり、サブディレクトリの処理にも対応しているため、開発者はこの名前のファイルを複数記述することになる。以下はそのファイルの内容の記述についての特徴。
- 依存パッケージなどのチェック処理の部分とビルドやインストールに関係する記述の部分のいずれも読み書きがしやすく、シンプルに書けて読む人にも分かりやすい
- 特定のGUIツールキットやOSに固有の、プログラムのビルドに関係した操作を楽に扱うモジュール群が存在し、それらに関係する記述をシンプルにできる
- 書き方を全く習得していない状態では、公式のドキュメントや既存のプロジェクトのファイルなどを参考にして調べる必要がある
- ただし、autotoolsでの記述を新しく習得するのに比べればかなり楽
ビルドの流れ
- ソースツリーの最上位ディレクトリで
meson
コマンドを実行 - 必要に応じて再設定を行う
- 指定済みのビルドディレクトリの中でビルド用のコマンドを実行してビルドとインストールを行う
- ビルド用ディレクトリが必要なくなったらこれを消す
はじめに、このビルドシステム固有のコマンドmeson
を実行する。ここでは各種チェックやビルド時の設定などの処理が行われ、エラーがなければシェルに戻った後で続けてビルド用のコマンド(既定ではninja
)を実行する。このような流れはautotoolsによるビルドシステムやCMakeと近い。
Mesonはビルド用の一時ディレクトリを必須とし、
- ソースツリーの最上位ディレクトリ内でビルド用ディレクトリの場所を引数に指定
- 空のビルド用ディレクトリ内でソースツリーの最上位ディレクトリの場所を引数に指定
- それら両方のディレクトリの場所を示す2つの引数を(先にソースツリーの最上位ディレクトリが来る順番で)指定
のいずれかの形でmeson
コマンドを実行する。ビルド用のディレクトリとして引数に指定した場所がまだ存在しなければmeson
が自動的にその場所にディレクトリを作るため、事前に手動で作成する必要はない。
ビルド作業の例
GNU/Linux上でビルドを行う典型的な流れとしては下のようになり、下の例ではソースツリーの最上位ディレクトリから新しく作成するビルド用ディレクトリの場所を指定する形をとっている。
(ビルドの準備) $ meson --prefix=/opt/program_name _build (ビルド) $ ninja -C _build (管理者権限でインストール) $ sudo ninja -C _build install
meson
実行時の作業ディレクトリと引数の指定には複数の方法があるということは既に書いているが、下の例では空のビルド用ディレクトリの中からソースツリーの最上位ディレクトリの場所を指定する形をとっている(手動でのディレクトリ作成があるため、おすすめはしない)。
(ビルド用ディレクトリを作成) $ mkdir _build && cd _build (ビルドの準備) [_build]$ meson --prefix=/opt/program_name .. (ビルド) [_build]$ ninja (管理者権限でインストール) [_build]$ sudo ninja install
設定の確認と再設定
既存のビルド用ディレクトリを引数に指定してサブコマンドconfigure
を実行することで、現在の設定の状態と設定可能な項目の一覧を確認することができる。更に-Dname=value
(名前と値のペア)形式のオプションを付け加えてこれを実行することでそのビルド用ディレクトリにおける設定を後から変更することもできる。もちろん、このようなオプションは最初にmeson
コマンドを実行したときに設定することもできる。
一覧では
- オプションの設定名
- 現在の値
- 設定可能な値(特定の値のみ受け付ける場合)
- 説明文
のセットが種類ごとに並んで表示される。将来のバージョンでこれが見やすくなる可能性はあるが、1行がかなり長くなるため、端末の横が80桁の環境ではとても見づらい。その場合は必要な応じて端末ソフトを一時的に最大化して出力を確認してから元に戻すなどする。
(現在の設定を確認) $ meson configure _build | less (コンパイラの警告レベルを指定するwarning_levelを2に変更) $ meson configure -Dwarning_level=2 _build
ビルド時の挙動を制御する
ビルドの種類の指定
--buildtype
オプションを指定することで、デバッグ用やリリース用のオプション指定が自動的に設定される。よく使われるのが以下。プロジェクトによっては既定値としてdebugoptimized
が設定されている。
buildtype=debugoptimized
: 広く使われる最適化レベルとデバッグ情報生成の指定buildtype=release
: 高めの最適化レベル指定buildtype=plain
: 最適化レベルやデバッグ情報生成に関するコンパイラオプションを付けない
コンパイラやオプションなどを変更する環境変数
コンパイラやそのオプションなどをビルド時に変更したい場合にはautotoolsによるビルドシステムにおけるconfigure
スクリプトの実行時と同様にmeson
コマンドの実行時に特定の環境変数を指定する。
buildtype=plain
オプションとこれらを同時に指定するとオプション指定のカスタマイズに役立つ。
(コンパイラ関係の環境変数を指定する例) $ CC="gcc" CFLAGS="-O2 -march=native" LDFLAGS="-Wl,-O1" meson --buildtype=plain _build
下の一覧は一部で、対応する全ての環境変数を示すものではない。CCやCXXはccache
の使用を回避するのにも使える。
環境変数 | 説明 |
---|---|
CC | Cコンパイラのコマンド名もしくは絶対パス |
CXX | C++コンパイラのコマンド名もしくは絶対パス |
CFLAGS | Cコンパイラに付けるオプション |
CXXFLAGS | C++コンパイラに付けるオプション |
VALAFLAGS | Valaコンパイラに付けるオプション |
CPPFLAGS | プリプロセッサのオプション |
LDFLAGS | リンカに付けるオプション |
ディストリのパッケージをビルドするときなどに使われるDESTDIRはninja install
の実行時に環境変数として指定することでMeson内のコードがbuild.ninja
経由で呼び出されてこれが処理され、この値のディレクトリをルートディレクトリとしてその下の階層にファイルが配置される。
(DESTDIRを指定してインストール処理を行う例) $ DESTDIR=~/temp/dest ninja install
プロジェクトごとのビルド設定をオプションで指定する
プロジェクトによっては-Dname=value
(名前と値のペア)形式のオプション指定でプロジェクトに固有な機能の有効/無効などの設定をビルド前に行うことができる。
指定する名前や指定可能値, 既定値, 説明はmeson_options.txt
というファイルに記述される。Meson自体もこのファイルを参照して必要な処理を行っている。
Mesaはバージョン18.1系時点でMesonとautotoolsの両方に対応しており、
でMesa 18.1.x系のソースツリーでIntel用のVulkanドライバのみのビルドを行う作業があるが、これをMesonで行うと下のようになる(将来のバージョンでは指定の形式が変わる可能性があるため、オプション指定の形を示す例として載せる)。
[mesa-18.1.x]$ meson -Dgbm=false -Dshared-glapi=false -Ddri3=true -Degl=false -Dglx=disabled -Dopengl=false -Dgles1=false -Dgles2=false -Dgallium-drivers= -Ddri-drivers= -Dvulkan-drivers=intel _build [mesa-18.1.x]$ ninja -C _build
インストール先などの指定
autotoolsに基づいたビルドシステムと同様、インストール先(prefix)の標準は/usr/local/
(WindowsではCドライブ直下)以下となっており、--prefix
オプションを付けることでその場所を変更することができる。
オプション | 説明 |
---|---|
--prefix | インストール先(基本的にファイルはこのディレクトリ以下に配置される) |
--bindir | 実行ファイルの配置場所(通常は--prefix のディレクトリの下のbin ) |
--libdir | そのソフトウェアが提供するライブラリの配置場所 |
--libdir
については、基本的には--prefix
のディレクトリの下のlib/
などとなるが、ディストリによってバリエーションがあり、Debian系ではlib/[アーキテクチャ名]-linux-gnu/
のような形となっており、ディストリに合った既定のディレクトリを検出できる。
同様の他のオプションはmeson --help
で確認できる。
開発者向けの機能
gettextによる国際化に対応したプロジェクトにおける処理
gettextによる国際化に対応したプロジェクトでは、Mesonはintltoolではなく新しめのバージョン(0.19.7以上)のgettextのツール群の機能を用いてpo/POTFILES
に並べたファイルの翻訳可能文字列を取り出して.potファイル[2]を更新し
- *.appdata.xml.in
- *.desktop.in
などのテンプレートの形の翻訳可能ファイルはi18n.merge_file()
という関数を呼び出す記述がmeson.build
にあれば、ビルド時にmsgfmt
の機能によってテンプレートファイル(*.in)と.poファイル群から翻訳の含まれた出力ファイルが生成される。
Ninja使用時の特殊なターゲット指定
ビルド段階で生成されたファイルを削除
プログラムのソースをコンパイルした結果生成されるオブジェクトファイルなどの削除で、autotoolsによるビルドシステムにおけるmake clean
に相当するもの。Mesonはビルド用ディレクトリが必須なこともあり、(そのディレクトリ以下を消すことで生成されるファイルが全て消せるため)この操作の出番は少ないかもしれない。
meson.build
内にconfigure_file()
の記述がある場合はmeson
コマンドの実行時にファイルが生成され、以下の操作を行ってもビルドディレクトリ内に残る。config.h
が生成されるプロジェクトにおける同ファイルはその典型的な例。
(ビルド段階で生成されたファイルを削除) $ ninja -C _build clean
gettextによる国際化への対応を統合したプロジェクトで.potファイルや.poファイルを更新
gettextによる国際化への対応を統合(i18n.gettext()
のおかげで必要な記述自体は非常に少ない)したプロジェクトにおいて、翻訳可能文字列を取り出して.potファイルを更新するには[プロジェクト名]-pot
を、その更新を各.poファイルに適用するまでを行うには[プロジェクト名]-update-po
のターゲットを指定する。
プロジェクト名部分に指定するのは実際のプロジェクト名ではなく、ソースツリー最上位ディレクトリのmeson.build
でproject()
の最初の引数に指定されている内部的な名前の文字列。
下は例だが、projname
の部分を実際のプロジェクトのものに置き換える。
(翻訳可能文字列を取り出して.potファイルを更新) $ ninja -C _build projname-pot (上に加えてmsgmergeによる各.poファイルの更新も行う) $ ninja -C _build projname-update-po
配布用のソース書庫ファイルを作成
GitやMercurialのリポジトリのソースツリーから作成したビルド用ディレクトリの中でdist
というターゲットを指定すると、バージョン管理システム関係のファイルやディレクトリを除いた配布用のソース書庫ファイル(.tar.xz形式)が自動的に[ビルドディレクトリ]/meson-dist/
以下に作成される。書庫に所有者のユーザ名やグループ名が入るのが気になる場合はfakeroot
と組み合わせる。
このファイルはPythonの機能のみで作成されるため、書庫の作成のための外部コマンドは不要。
(ソース書庫ファイルを作成) $ fakeroot ninja -C _build dist
- Meson 0.47.2