6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

meson 資料集

Last updated at Posted at 2022-12-28

縦に長くて更新しづらくなったので github に整理しました 👇

旧記事

機能は cmake よりいいと思うのだけど、必要な情報がドキュメントのどこに書いてあるか見つけづらいのでここに整理する。

最近バージョンが 1.0.0 になってた。

install

pip install meson

ninja も pip でいける

pip install ninja

meson は Python3 に依存する

pip install meson

必須

  • compiler
  • Ninja

pip install ninja でも OK

dependency 解決は2段構え

dependency('hoge') もしくは subproject('hoge') で依存を記述する。
まず System を探索し、無ければ Subprojects にフォールバックする。

System ライブラリーの探索

/usrWindowsKits からの探索。

  • pkg-config
  • cmake

などが使われるようだ。
また、gl, boost など探索方法がハードコーディングされたライブラリもある。

Subproject へのフォールバック

project_root/subprojects フォルダの内容を使う。

  • project_root/subprojects/zlib/meson.build のようなソースコードをフォルダに展開して meson.build を配置したもの
  • project_root/subprojects/zlib.wrap のようなソースコードのダウンロード手順を示したもの

基本

meson.build
project('tutorial', 'cpp')

demo_inc = include_directories('include')
executable('demo', 'main.cpp',
include_directories: demo_inc)
meson setup buildir
ninja -C builddir

もしくは

meson setup buildir
meson compile -C builddir # 直接 ninja するのとの違いは未確認。meson.build, subproject などの meson の変更を反映する能力が違うかもしれない

もしくは

meson setup buildir --prefix FULL_PATH_TO_INSTALL
meson install -C builddir

install までやれば exe と dll が PREFIX/bin に集まるので扱いやすい場合がある。

慣習

変数名に _inc, _lib, _dep を付けて型を表す

例えば hoge という project の場合、

meson.build
project('hoge', ['c', 'cpp'])
hoge_inc = include_directories('include')
hoge_lib = library('hoge', [
  'src/hoge.cpp',
],
  include_directories: hoge_inc,
)
hoge_dep = declare_dependency(
  include_directories: hoge_inc,
  link_with: hoge_lib,
)
meson.build
hoge_dep = dependency('hoge') # dep として参照される
# もしくは
hoge = subproject('hoge') # subproject として参照される
hoge_dep = hoge.get_variable('hoge_dep') # 変数として取り出し

executable('fuga', ['main.cpp'],
  dependencies: [hoge_dep],
)

meson setup の状態を確認する

meson configure builddir

.gitignore

.gitignore
/.cache/
/build/
/builddir/
/subprojects/*
!/subprojects/packagefiles
!/subprojects/some.wrap # 👈 *.wrap でだいたい OK だが、wrap-reidrect をコミットすると動かなくなる場合あり。依存の依存を浅い階層にコピーしている?

commandline

setup

configure 的。

meson setup builddir --prefix prefix_full_path

reconfigure

meson setup builddir --prefix prefix_full_path --reconfigure
meson setup builddir --prefix prefix_full_path --wipe

build

meson compile -C buildir

-C buildir を省略するとカレントディレクトリを使う。

install

meson install -C builddir

-C buildir を省略するとカレントディレクトリを使う。

vscode 例

.vscode/tasks.json
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "configure",
            "type": "shell",
            "command": "meson setup builddir --prefix ${workspaceFolder}/prefix",
            "problemMatcher": [],
        },
        {
            "label": "configure(wipe)",
            "type": "shell",
            "command": "meson setup --wipe builddir --prefix ${workspaceFolder}/prefix",
            "problemMatcher": [],
        },
        {
            "label": "build",
            "type": "shell",
            "command": "meson install -C builddir",
            "problemMatcher": {
                "owner": "meson-msvc",
                "fileLocation": [
                    "autoDetect", // 👈 absolute  relative 両方
                    "${workspaceFolder}/builddir",
                ],
                "pattern": {
                    "kind": "location",
                    "regexp": "^(.*)\\((\\d+)\\): (fatal error|\\w+) (\\w+): (.*)$",
                    "file": 1,
                    "line": 2,
                    "severity": 3,
                    "code": 4,
                    "message": 5,
                }
            },
        },
    ]
}

meson は compile_commands.json を自動的に生成するので、 clangd で参照する。

.vscode/settings.json
{
    "clangd.arguments": [
        "--compile-commands-dir=${workspaceFolder}/builddir"
    ],
}

ビルドディレクトリが cmake と被らないように builddir を使う。

https://marketplace.visualstudio.com/items?itemName=mesonbuild.mesonbuild

がデフォルトで builddir を使う。
task も builddir にしておいた。

project

先頭に定義。
名前、使う言語(c, cpp...)、コンパイラの全体設定(c++20)など。

meson.build
project('hello', ['c', 'cpp'],
version: '1.0.0',
default_options: [
    'cpp_std=c++20',
])

root project は暗黙裡に this として参照されている感じぽい?

default_options

project 全体の設定を変更する。

project の default_options 変更時は meson setup --wipe が必要

ninja, meson compile するだけでは反映されないので注意。
また meson setup --reconfigure ではだめ。

default_library

static と shared を選択する。デフォルトは shared ?

meson.build
project(
default_options: ['default_library=static']
)

のように指定できる。

project init

空プロジェクトの生成

compile options

include

デフォルトでカレントフォルダが -I に追加される。
危ない。
システムのヘッダと同名のファイルがローカルに存在した場合に、意味不明な大量のエラーが出る可能性がある。
stdint.h がシャドウされるなど変なことが起きうる。

https://mesonbuild.com/Reference-manual_functions.html#library_implicit_include_directories

必要に応じて implicit_include_directories: false を明示する。

link

meson.build
# winmm.lib にリンクする
c_compiler = meson.get_compiler('c')
winmm_lib = c_compiler.find_library('winmm', required: true)
executable('hello', [
  'main.cpp'
],
  dependencies: [winmm_lib],
)

条件式

if host_machine.system() == 'windows'
endif

config.h を生成する

project(
    'App',
    'cpp',
    version: '1.4.0',
    license: 'MIT',
    default_options: [],
)

cdata = configuration_data()
cdata.set_quoted('PACKAGE', meson.project_name())
cdata.set_quoted('PACKAGE_VERSION', meson.project_version())
configure_file(
    output: 'config.h',
    configuration: cdata,
)

# build_dir に config.h は出力される
# include できるようにするには下記のようにする
# '.' は build_dir を指すぽい。
config_inc = include_directories('.')

生成された config.h

/*
 * Autogenerated by the Meson build system.
 * Do not edit, your changes will be lost.
 */

#pragma once

#define PACKAGE "App"

#define PACKAGE_VERSION "1.4.0"

GIT の情報を埋め込む例

meson and git information

target

executable

executable('hello', [
    'main.cpp'
],
)

winmain

executable('hello', [
    'main.cpp'
],
    win_subsystem: 'windows',
)

gui_app: true は deprecated

rc: windows resource

windows = import('windows')
executable('app', [
    windows.compile_resources('app.rc',
      include_directories: wtl_inc), # 必要に応じて
    main.cpp
])

library

some_lib = library('some', [ # default_library により shared か static が決まる。デフォルトは static
    'some.cpp',
],
)
  • static_library
  • shared_library
  • both_libraries 👈 static と shared の両方をビルドさせる

dependency

meson は project 内に変数として target などがある。
subproject から get_variable で変数(subproject, dep, target) などが得られる。

target が dep に依存する。dep の中に別の target がある。

dependency を使う

以下の記述をする。

meson.build
freetype2_dep = dependency('freetype2')
meson.build
# default_options は、project の default_options, meson_options.txt などの変更ができる
some_dep = dependency('some', deafult_options: ['default_library=static'])

# 👇
# dependency は subproject に対して get_variable するのと同等
fmt_dep = subproject('fmt', default_options: ['default_library=static']).get_variable('fmt_dep')

この記述により、dependency関数dep 型のオブジェクトを返す。
dep 型なので _dep と名付ける慣習。
dependency は 引数のキーに、pkg-config などでシステムのライブラリをサーチして、
無かったら subprojects フォルダにフォールバックするという動作をする。
Unix系では、pkg-config で見つかることが多くて、Windows では subprojects
使うことが多くなると思われる。

dependency名?

dependency() は project 名でなくて、dependency名? で解決されるポイ。
project の中に複数の dependency名 を内包することができる。

dependency名は以下のいずれかの方法で宣言できる。

subprojects/ogg/meson.build
meson.override_dependency('ogg', ogg_dep) # 👈 ogg が dependency名

もしくは、

subprojects/ogg.wrap
[provide]
ogg = ogg_dep # 👈 ogg が dependency名

dependency の伝搬

some_inc = include_drectories(.)
some_lib = library('some', [],
include_drectories: some_inc # 👈 伝搬しない(CMake の target_include_directories PRIVATE)
some_dep = declare_dependency(
    include_derectories: some_inc, # 👈 伝搬する(CMake の target_include_directories PUBLIC)
)

wrap redirect

ネストした subprojects の wrap ファイルが上位階層にコピーされる。
これは .gitignore する必要がある。

subprojects\expat.wrap
[wrap-redirect]
filename = fontconfig-2.14.1\subprojects\expat.wrap

システムライブラリ(pkg-configなど)を無視して subprojects を使うには?

TODO:

dependency の include 警告が出ないようにする

directxmath_dep = dependency('directxmath', include_type: 'system')

dependency を作る

declare_dependency

meson.build
project('some', 'cpp')
some_lib = library('some', ['some.cpp'])
some_dep = declare_dependency(
    link_with some_lib
)

以下のように project が namespace になる。

  • some(project)
    • some_lib(build target)
    • some_dep(dependency)

subprojects に展開する

Intel TBB を展開する例。

project('tbb', 'cpp')

cc = meson.get_compiler('cpp')

if get_option(
    'buildtype',
).startswith('debug') # debug or debugoptimized
    tbb_lib = cc.find_library(
        'tbb_debug',
        dirs: meson.current_source_dir() + '/lib/intel64/vc14',
    )
else
    tbb_lib = cc.find_library(
        'tbb',
        dirs: meson.current_source_dir() + '/lib/intel64/vc14',
    )
endif

tbb_dep = declare_dependency(
    include_directories: include_directories('include'),
    dependencies: tbb_lib,
)
meson.override_dependency('tbb', tbb_dep)

使用するには、

tbb_dep = subproject('tbb').get_variable('tbb_dep')
# もしくは
tbb_dep = dependency('tbb') # meson.override_dependency が対応する

wrap file

subprojects/some.wrap のように配置する。

下記の [provide] が必須で左辺が、 dependency('ogg') のように名前を決めている。

[provide]
ogg = ogg_dep
  • wrap-file, wrap-git などしたり直接 subprojects にファイルを配置したりできる。
  • subprojects/hoge.wrap と subprojects/packagefiles/hoge/meson.build がペアになる。

wrap-file

zip や tar.gz を download する

subprojects/openxr_loader.wrap
[wrap-file]
directory = openxr_loader
source_url = https://github.com/KhronosGroup/OpenXR-SDK/releases/download/release-1.0.26/OpenXR.Loader.1.0.26.nupkg
source_filename = OpenXR.Loader.1.0.26.zip
source_hash = ae874fd20e77abc2de4bc8a75ccc9a1217799a6e81cf76eee6a1cd599de45a93
patch_directory = openxr_loader
lead_directory_missing = true # 👈 展開すると bin, include, lib のようひとつの root フォルダが無い場合

[provide]
openxr_loader = openxr_loader_dep
subprojects/packagefiles/openxr_loader/meson.build
project('openxr_loader', 'c')

cc = meson.get_compiler('c')
lib_dir = meson.current_source_dir() + '/native/x64/release/lib'
libs = []
libs += cc.find_library('openxr_loader', dirs: lib_dir)

openxr_loader_dep = declare_dependency(
    include_directories: include_directories('include'),
    dependencies: libs,
    compile_args: ['-DXR_USE_PLATFORM_WIN32'],
)

install_data('native/x64/release/bin/openxr_loader.dll', install_dir: 'bin')

wrap-git

git を clone する。

subprojects/ktx.wrap
[wrap-git]
url = https://github.com/KhronosGroup/KTX-Software
revision = v4.0.0
depth = 1
patch_directory = ktx

[provide]
ktx = ktx_dep
subprojects/packagefiles/ktx/meson.build
project('ktx', 'c')
ktx_inc = include_directories('include')
ktx_dep = declare_dependency(
    include_directories: ktx_inc,
)
# TODO

subprojects/hoge.wrapsubprojects/hoge に clone される。
ファイル名重要

patch_directory

このフォルダのファイルを、
wrap-file や wrap-git で展開したソースディレクトリに対して上書きコピーする。

subprojects/
  packagefiles/
    some/ # some.wrap の `patch_directory = some` で指定する
      meson.build # 自前の meson.build
  some.wrap # wrap-file や wrap-git でソースファイルを得る
  some/ # ソースファイルのフォルダ 
      meson.build # meson setup 時に some フォルダが作成されたあとで、一度だけ package_directory/some からコピーされる。
subprojects/some.wrap
patch_directory = some # packagefiles 下のフォルダ名

meson.build が無い場合、config.h を決め打ちにする場合などに使える。

diff_files

meson setup 時に wrap file により subprojects/some フォルダが作成されるときに、一度だけ diff_files が適用される。

再実行するには subprojects/some を消して、 meson setupmeson compile する。

# ひとつだけファイルを修正する例
subprojects/some$ diff -up meson.build.orig meson.build > ../packagefiles/some/meson.build.patch
subprojects/some.wrap
diff_files = some/meson.build.patch # subprojects/packagefiles からの相対パス

git diff

subprojects/hoge$ git diff > ../packagefiles/hoge.patch
subprojects/hoge.wrap
diff_files = hoge.patch # subprojects/packagefiles からの相対パス

wrap db

  • wrap ファイルをダウンロードして、subprojects/some.wrap に配置

コマンドラインでできる。

meson wrap install sdl2

他にもいろいろコマンドあり。

meson wrap list
  • meson.build に some_dep = dependency('some') と記述する
  • target に dependencies: [some_dep] と記述する

wrap file 例

subprojects/{name}.wrapsubprojects/packagefiles/{name}/meson.build の2つを作ることが多い。

stb(header only)

subprojects/stb.wrap
[wrap-git]
url = https://github.com/nothings/stb
revision = master
depth = 1
patch_directory = stb

[provide]
stb = stb_dep
subprojects/packagefiles/stb/meson.build
project('stb')
stb_dep = declare_dependency(
    include_directories: include_directories('.'),
)

plog(header only)

subprojects/plog.wrap
[wrap-git]
url = https://github.com/SergiusTheBest/plog
revision = master
depth = 1
patch_directory = plog

[provide]
plog = plog_dep
subprojects/packagefiles/plog/meson.build
project('plog')
plog_inc = include_directories('include')
plog_dep = declare_dependency(
    include_directories: plog_inc,
)

違うコンパイラを使う

setup 時に引数 --native-file NATIVE_FILE もしくは --cross-file CROSS_FILE を使うことで
違うコンパイラを選択できる。
NATIVE_FILE と CROSS_FILE の内容はだいたい同じで、フォーマットは ini ファイル。
コンパイラに clang や mingw 明示したいときに --native-file を使い、
さらに違うプラットフォーム向けにビルドするときに --cross-file を使う。
native と cross をあべこべにしても動くかもしれないがよくわからない。
変更を反映するには、 meson setup のやりなおしが必要。

--native-file

clang-16 と libc++

Ubuntu-22.04

# std::expected 使えた
[constants]
toolchain = '/usr/lib/llvm-16'

[built-in options]
cpp_args = ['-std=c++2b', '-stdlib=libc++']
cpp_link_args = cpp_args

[binaries]
c= toolchain / 'bin/clang'
cpp= toolchain / 'bin/clang++'
c_ld = toolchain / 'bin/ld.lld'
cpp_ld = toolchain / 'bin/ld.lld'

--cross-file

emscripten

# wasm.ini
[constants]
args = []

[binaries]
c = 'emcc'
cpp = 'em++'
ar = 'emar'

[built-in options]
c_args = []
c_link_args = args
cpp_args = []
cpp_link_args = args
default_library = 'static'

[host_machine]
system = 'emscripten'
cpu_family = 'wasm'
cpu = 'wasm'
endian = 'little'
meson setup builddir --cross-file wasm.ini

boost

header only の場合

アーカイブを展開して環境変数 BOOST_ROOT を指定する。
ビルドが必要な部分は試していない。

# 例。D:\boost\boost_1_82_0 に解凍した
BOOST_ROOT=D:\boost\boost_1_82_0
boost_dep = dependency('boost')

とする。

cmake との対応

機能 cmake meson 備考
project project project トップレベル。visual studio の sln に相当する
exe add_executable executable
lib add_library library
lib(static) add_library(some STATIC) static_library
lib(shared) add_library(some SHARED) shared_library
target cflags target_compile_options library, executable(c_args:, cpp_args:), declare_dependency(c_args:, cpp_args:)
target cpp std
target definition target_compile_definitions cflags と区別なし
target include target_include_derectories library, executable, declare_dependency(include_derectories:)
target link target_link_libraries library, executable(dependencies:), declare_dependency(link_with:)
target libdir
global cflags ADD_COMPILE_OPTIONS project(default_options: ['c_args=cflags', 'cpp_args=cxxflags'])
global cpp std project(default_options: ['cpp_std=c++20'])
global definition add_definitions cflags と区別なし
global include add_includes
global link
global libdir
install library, executable(install : true)
subdir add_subdirectory, subdirs subdir('dirname')
option
prefix
toolchain
current ${CMAKE_CURRENT_LIST_DIR} meson.current_source_dir()

vscode

この拡張でシンタックスハイライトなどが有効になる。
formatter を有効にするには、

をビルドして関連設定をする。
Windows でも msys ならビルドできた。
msys/usr/binmuon.exe を copy するとよさそう。

settings.json
{
    "mesonbuild.muonPath": "C:/msys64/usr/bin/muon.exe",
    "mesonbuild.formatting.enabled": true,
    "mesonbuild.linter.muon.enabled": true,
    "mesonbuild.linting.enabled": true,
}

c++2b など新しいフラグに未対応

  • 1.0
  • 1.1rc2

未対応。

.local/lib/python3.10/site-packages/mesonbuild/compilers/cpp.py

の該当個所に 'c++2b' を追加してしまった。
gcc-12 で std::expected 動いた。

meson + msvc on github-action

vcvars64.bat 的な対策

参考

2022

2018

2016

6
2
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
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?