はしくれエンジニアもどきのメモ

情報系技術・哲学・デザインなどの勉強メモ・備忘録です。

Mesonの使い方メモ

Mesonの使い方メモ

Mesonの情報無さすぎるということでメモ。 触ってみた所感としてcmakeより楽なんだろうけど、どのbuitinオプションがどの引数を制御してるかなどがわかりにくい.. (ver0.61なので今後変わりそうですが)

The Meson Build system

mesonではビルド方法を2種類に分けている

  • native build: build machineとhost/target machineが同じ
  • cross build: build machineとhost/target machineが別

今回はnative buildを中心にまとめる。

環境・事前準備

今回はDocker上にMesonをインストールした状況を想定してる。 Mesonはpipからインストールできる。

$ pip3 install meson
  • Windows10 64bit
    • WSL2
    • DockerDesktop 4.5.1 (74721)
      • base image: Debian 11
        • Meson 0.61.2

Mesonって何?

Autotools(automake)やCMakeのようなビルディングツール。 python製。

ビルドツールの歴史として以下を三大巨頭とすると

  • 1990年頃:Autotools(automake)
  • 1999年頃:Cmake
  • 2013年頃:Meson

その中でも、Mesonは特にユーザーフレンドリーを意識して開発されている。 (ドキュメントの解説が機能別になりすぎていたり、サンプルも少ないので、わかりにくいことも多いが)

ただし実際にMesonはfrontend側の処理をしておりビルド処理を担当してるのはNinjaになる。 まとめると、

  • frontend: Meson: autoconfやautomake側に近い
  • backend: Ninja: ビルド処理を担当、make側に近い

(正直、Ninjaだけでは駄目なのかよくわかってない)

設定ファイルの関係をまとめると

tool ビルドの設定ファイル
make/automake Makefile
Cmake CMakeLists.txt
Meson meson.build

Mesonを使う流れ

主な流れをまとめる。

開発者側:プロジェクト用ディレクトリ作成からビルドまで

$ mkdir <project dir>
$ cd <project dir>
$ meson init # meson.buildファイルが作成される

meson initにオプションをつけることで使う言語など指定できる。

Project templates

IDEやらエディタやらでソースコードをプロジェクトフォルダ内に作成または追加して, meson.buildにビルド用の設定を追加する。

$ meson setup <build dir>
$ cd <build dir>
$ meson compile # or ninja build

これでソースコードの変更があればmeson compileだけで済むようになる。

Release版などをインストールするユーザ側:基本的にautotoolsの流れに近い

$ cd <project dir> # meson.buildのある場所に移動
$ meson setup <build dir> # ./configure に相当
$ cd <build dir>
$ meson compile # make に相当
$ meson install # make install に相当

meson installについて: Installing

meson.build(設定ファイル)の書き方

mesonを使うにはmeson.buildファイルが必須になる。 ディレクトリ内に存在しないとエラーになる。

公式Tutorialに最低限の書き方がある。

Tutorial

最低限必要なのは以下2行になる。

project('project name', 'language')
executable('実行ファイル名', ['source code path'])

if文やforreach文なんかも使える。 if文が使えるので指定のコンパイラだったら特定の引数を追加するような書き方もできる。 (あまり複雑な条件設定にするとカオスになりそうだが)

他に使える構文: Syntax

pythonライクに書けて変数設定もできるが、予約された識別子と自分が設定した変数なのかがわかりにくくなるので注意。

また、built-in optionや変数の値を確認するにはmessage関数が使える。built-in optionはget_option関数でアクセスできる。

project('project name', 'language')
flag=false
executable('実行ファイル名', ['source code path'])

message(flag)
message('b_asneeded: ', get_option('b_asneeded'))

これらのmessagemeson setupしたときに表示される。

引数設定のススメ

ビルドツールを使うということは、コンパイラやリンカの引数設定をするはずなのでその方法についてまとめる。

引数指定方法は主に3つある。

  • nativeファイル内で指定してmesonコマンドのときに上書きする
  • meson.buildファイル内で指定
  • meson側で読み込む環境変数を使う

おすすめは一番上のカスタム用のnativeファイルを作成してそこで指定しておくやり方である。 これだと元のmeson.buildファイルを基本いじらずにnativeファイルから上書きして設定できる。

実際にコンパイラやリンカにどの引数が指定されてビルドされているかを確認するには

$ meson compile --verbose

nativeファイルの書き方・使い方

nativeファイルの書き方: Cross and Native File reference

※ただし、 meson側のbuilt-in optionにより勝手に設定されるコンパイラやリンカへの引数がわかりにくい(特に明示がない)ので注意。 built-in optionの一覧は Built-in optionsで確認できる。

毎度検索するのは大変なのでtemplateファイルを残す。

native_template.ini

## native file

## "constants" that can be used on .ini files
### 🔗 https://mesonbuild.com/Machine-files.html#constants
[constants]


## "Properties" that is key value pairs accessed using the meson.get_external_property(), or meson.get_cross_property().
### 🔗 https://mesonbuild.com/Machine-files.html#properties
[properties]
# cmake_toolchain_file='' #  specifies an absolute path to an already existing CMake toolchain file that will be loaded with include() as the last instruction of the automatically generated CMake toolchain file from Meson. (new in 0.56.0)
# cmake_defaults='' # is a boolean that specifies whether Meson should automatically generate default toolchain variables from other sections (binaries, host_machine, etc.) in the machine file. Defaults are always overwritten by variables set in the [cmake] section. The default is true. (new in 0.56.0)
# cmake_skip_compiler_test='' # is an enum that specifies when Meson should automatically generate toolchain variables to skip the CMake compiler sanity checks. This only has an effect if cmake_defaults is true. Supported values are always, never, dep_only. The default is dep_only. (new in 0.56.0)
# cmake_use_exe_wrapper='' # is a boolean that controls whether to use the exe_wrapper specified in [binaries] to run generated executables in CMake subprojects. This setting has no effect if the exe_wrapper was not specified. The default value is true. (new in 0.56.0)
# java_home=''


## Project specific options
### Being able to set project specific options in a cross or native file can be done using the [project options] section of the specific file (if doing a cross build the options from the native file will be ignored)
### ⚠ require to define options in `meson_option.txt`
### able to set -Doption when using `meson` command on terminal
### able to access using `get_option()` in `meson.build`file
### 🔗 https://mesonbuild.com/Machine-files.html#project-specific-options
[project options]


## Binaries
### 🔗 https://mesonbuild.com/Machine-files.html#binaries
[binaries]
# c = 'gcc'
# c_ld='ld'
# cpp='g++'
# cpp_ld='ld'
# ar='ar'
# sed = 'sed'
# llvm-config = '/usr/lib/llvm-11/bin/llvm-config'


## Builtin-options
### 🔗 https://mesonbuild.com/Builtin-options
[built-in options]
### Compiler options 🔗 https://mesonbuild.com/Builtin-options.html#compiler-options
# c_args=[] # C compile arguments to use
# c_link_args=[] # C link arguments to use
# c_std='none' # 'none'/'c89'/'c99'/'c11'/'c17'/'c18'/'c2x'/'gnu89'/'gnu99'/'gnu11'/'gnu17'/'gnu18'/'gnu2x' # C language standard to use
# c_winlibs=[] # see below  free-form comma-separated list # Standard Windows libs to link against
# c_thread_count=4 #integer value ≥ 0 # Number of threads to use with emcc when using threads
# cpp_args=[] # free-form comma-separated list # C++ compile arguments to use
# cpp_link_args=[] # free-form comma-separated list # C++ link arguments to use
# cpp_std='none' # none/c++98/c++03/c++11/c++14/c++17/c++20/c++2a/c++1z/gnu++03/gnu++11/gnu++14/gnu++17/gnu++1z/gnu++2a, gnu++20, vc++14, vc++17, vc++latest    C++ language standard to use
# cpp_debugstl=false # true/false # C++ STL debug mode
# cpp_eh='default' # none/default/a/s/sc # C++ exception handling type
# cpp_rtti=true # true/false # Whether to enable RTTI (runtime type identification)
# cpp_thread_count=4 # integer value ≥ 0 # Number of threads to use with emcc when using threads
# cpp_winlibs=[] # see below free-form comma-separated list # Standard Windows libs to link against
# fortran_std='none' # [none, legacy, f95, f2003, f2008, f2018] # Fortran language standard to use
# cuda_ccbindir='' # filesystem path # CUDA non-default toolchain directory to use (-ccbin) (Added in 0.57.1)

### Universal options 🔗 https://mesonbuild.com/Builtin-options.html#universal-options
#### Directories
# prefix='/usr/local' # prefix defaults to 'C:/' on Windows, and '/usr/local' otherwise. # Installation prefix
# bindir='bin' # Executable directory
# datadir='share' # Data file directory
# includedir='include' # Header file directory
# infodir='share/info' # Info page directory
# libdir='' # `libdir` is automatically detected based on your platform, it should be correct when doing "native" (build machine == host machine) compilation. For cross compiles Meson will try to guess the correct libdir, but it may not be accurate, especially on Linux where different distributions have different defaults. Using a cross file, particularly the paths section may be necessary. # Library directory
# libexecdir='libexec' # Library executable directory
# localedir='share/locale' # Locale data directory
# localstatedir='var' # Localstate data directory
# mandir='share/man' # Manual page directory
# sbindir='sbin' # System executable directory
# sharedstatedir='com' # Architecture-independent data directory
# sysconfdir='etc' # Sysconf data directory

### Core options 🔗 https://mesonbuild.com/Builtin-options.html#core-options
# auto_features='auto' # {enabled, disabled, auto} # Override value of all 'auto' features
# backend='ninja' # {ninja, vs, vs2010, vs2012, vs2013, vs2015, vs2017, vs2019, vs2022, xcode} # Backend to use
# buildtype='debug' # {plain, debug, debugoptimized, release, minsize, custom}  # Build type to use
# debug=true # Debug
# default_library='shared' # {shared, static, both} # Default library type
# errorlogs=true # Whether to print the logs from failing tests.
# install_umask='022' # {preserve, 0000-0777} # Default umask to apply on permissions of installed files    no  no
# layout='mirror' {mirror,flat} # Build directory layout
# optimization='0' # {0, g, 1, 2, 3, s} # Optimization level
# pkg_config_path='' # {OS separated path} # Additional paths for pkg-config to search before builtin paths
# cmake_prefix_path=[] # Additional prefixes for cmake to search before builtin paths   yes no
# stdsplit=true # Split stdout and stderr in test logs
# strip=false # Strip targets on install
# unity='off' # {on, off, subprojects} # Unity build
# unity_size=4 # {>=2} # Unity file block size   no  no
# warning_level=1 # {0, 1, 2, 3}  Set the warning level. From 0 = none to 3 = highest   no  yes
# werror=false # Treat warnings as errors
# wrap_mode='default' {default, nofallback, nodownload, forcefallback, nopromote} # Wrap mode to use    no  no
# force_fallback_for=[] # Force fallback for those dependencies no  no

### Base option 🔗 https://mesonbuild.com/Builtin-options.html#base-options
# b_asneeded=true # true/false # Use -Wl,--as-needed when linking
# b_bitcode=false # true/false # Embed Apple bitcode, see below
# b_colorout='always' # auto/always/never # Use colored output
# b_coverage=false # true/false # Enable coverage tracking
# b_lundef=true # true/false # Don't allow undefined symbols when linking
# b_lto=false # true/false # Use link time optimization
# b_lto_threads=0 # Any integer* # Use multiple threads for lto. (Added in 0.57.0)
# b_lto_mode='default' # default/thin # Select between lto modes, thin and default. (Added in 0.57.0)
# b_ndebug=false # true/false # if-release  Disable asserts
# b_pch=true # true/false # Use precompiled headers
# b_pgo='off' # off/generate/use # Use profile guided optimization
# b_sanitize='none' # see below Code sanitizer to use
# b_staticpic=true # true/false # Build static libraries as position independent
# b_pie=false # true/false # Build position-independent executables (since 0.49.0)
# b_vscrt='from_buildtype' #none/md/mdd/mt/mtd/from_buildtype/static_from_buildtype # VS runtime library to use (since 0.48.0) (static_from_buildtype since 0.56.0)

上書き方法は

$ meson setup <build dir> --native-file <native>.ini

例:nativeファイルからコンパイラをclangに変える

graph BT
    subgraph "--native-file native_clang.ini"
        c["c: clang"]
        subgraph "default native"
            c_d["c: gcc"]
        end
        c_d -..-> c
    end

native_clang.iniファイルを作る。

[binaries]
c='clang'
cpp='clang++'
$ meson setup <build_dir> --native-file native_clang.ini

C compilerがclangになってれば設定できている。

f:id:cartman0:20220324212852j:plain
result: meson setup

meson.buildファイル内に書く

override_optionsは実行ファイル生成時にのみ引数が有効になり、mesageget_optionでアクセスしたときには有効にならないので使わないほうがいい。

環境変数を使うケース

環境変数を使うやり方はCMakeのように扱える。

meson側が参照する予約されている環境変数一覧:

mesonbuild.com

この一覧の大文字で表されてるのが環境変数になる。各言語のコンパイラやリンカはここの環境変数でも設定できる。

※ただし、mesonでは環境変数の設定がmeson.buildファイル上でできない?ぽい。つまり設定ファイル上で制御できない。 実用するならsetup用のシェルスクリプトを書いたほうが扱いやすい。

例: 環境変数を使ってgccでなくclangでビルドする場合

なのでこれらにclang, clang++を設定すればいい。

command:

$ CC=clang CXX=clang++ meson setup <build dir>

一応事前にset CC=clangのようにも書いておけるが上のように書けば、 環境変数後のコマンドが子プロセス扱いで環境変数が引き継がれるのでこっちの書き方推奨。