Последнее обновление:2026-10-12
Сборка проектов C++ с помощью Meson¶
В последнее время, работая с рядом открытых проектов, я обнаружил, что все они используют сборку meson+ninja, отказавшись от CMake и Makefile; в этой статье мы познакомимся с Meson — от установки до написания полного meson-проекта.
Итак, переходим к сути.
1. Установка Meson¶
Meson можно получить через PyPi, поэтому для установки подойдёт pip3 install meson. В разных системах используйте правильную команду pip — обязательно pip версии Python 3.
При желании можно установить локально стандартной Python-командой:
Для сборки с Ninja сам Ninja можно скачать со страницы релизов Ninja на GitHub или через PyPi: Больше информации об установке Meson build читайте на официальном сайте Meson ниже.2. Meson Vs Cmake¶
Раз все пользуются CMake, зачем нужен Meson и каковы их сильные и слабые стороны?
Что касается производительности, Meson обычно славится высокой скоростью сборки. Meson спроектирован так, чтобы оптимизировать скорость сборки, и особенно хорош в инкрементальных сборках. Meson использует систему сборки Ninja как бэкенд по умолчанию, а Ninja сам по себе известен быстротой и эффективностью.
Для сравнения: скорость сборки CMake может зависеть от размера проекта, особенно в крупных проектах. CMake использует разные генераторы (например, Makefile), и производительность разных генераторов тоже может различаться.
Разумеется, можно использовать CMake + Ninja, чтобы повысить скорость компиляции.
Если смотреть на Meson с точки зрения открытых проектов, сфера его применения очень обширна: PostgreSQL, QEMU, GNOME Software, GTK+ и т.д.
2.1 Преимущества и недостатки Meson¶
1.Преимущества
- Основан на Python, прост в использовании
- Поддерживает кросс-компиляцию
- Все объекты строго типизированы: поскольку объекты — это сущности вроде 'dependency', 'include directory' и т.д., ошибки строковых подстановок почти невозможны.
- Очень удобно подключать сторонние библиотеки
- Очень-очень быстрый, особенно при инкрементальной сборке.
- Документация лучше cmake в n раз.
2.Недостатки
- Возможно, менее зрелый, чем CMake
- Зависимости Python3 + Ninja
- Генераторы проектов, поддержка Meson в IDE хуже, чем CMake
- поддержка vscode
- https://github.com/mesonbuild/vscode-meson
- Ограниченное число доступных модулей
- не-meson-проекты нужно самостоятельно отправлять в wrapdb
- https://mesonbuild.com/Wrapdb-projects.html
2.2 Преимущества и недостатки CMake¶
1.Преимущества
- Дружелюбная поддержка IDE, довольно удобно для командной работы
- Зрелый, практически стал стандартом C++-проектов
2.Недостатки
- Трудности с кросс-компиляцией
- Скорость компиляции относительно невысокая
3. Meson WrapDB¶
Поскольку googletest — не meson-проект, как подключить его через meson?
Аналогично используются grpc, abseil-cpp.
Здесь сначала нужно ввести WrapDB: Meson WrapDB — это компонент системы сборки Meson, предназначенный для управления и предоставления файлов описания сборки сторонних проектов, обычно называемых «wrap»-файлами. Эти wrap-файлы содержат информацию, необходимую для настройки и сборки стороннего проекта, чтобы его можно было легко интегрировать в другие проекты, использующие систему сборки Meson.
искать сторонние библиотеки можно командой search или на сайте ниже.
https://mesonbuild.com/Wrapdb-projects.html#meson-wrapdb-packages
Возьмём для примера использование gtest:
- Поиск gtest
- Создаём в своём проекте каталог subprojects и устанавливаем gtest через install
Внимание: этот файл создаётся после install выше; рекомендуется его не изменять.
[wrap-file]
directory = googletest-1.14.0
source_url = https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz
source_filename = gtest-1.14.0.tar.gz
source_hash = 8ad598c73ad796e0d8280b082cebd82a630d73e73cd3c70057938a6501bba5d7
patch_filename = gtest_1.14.0-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/gtest_1.14.0-1/get_patch
patch_hash = 2e693c7d3f9370a7aa6dac802bada0874d3198ad4cfdf75647b818f691182b50
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/gtest_1.14.0-1/gtest-1.14.0.tar.gz
wrapdb_version = 1.14.0-1
[provide]
gtest = gtest_dep
gtest_main = gtest_main_dep
gmock = gmock_dep
gmock_main = gmock_main_dep
4. Как написать meson-проект?¶
Переходим к практике: как написать meson-проект?
Ниже на примере теста деления a/b — небольшой проект с модульным тестированием через gtest.
4.1 Написание кода¶
.h и .cc кладём в каталог src: Затем на том же уровне создаём каталог test.4.2 Управление meson-проектом¶
Добавляем в корень проекта файл meson.build со следующим содержимым:
project('gtest_div', 'cpp')
gtest_proj = subproject('gtest')
gtest_dep = gtest_proj.get_variable('gtest_main_dep')
div_src = files('src/division.cc')
tests_src = files('test/division_test.cc')
e = executable(
'division_test',
tests_src + div_src,
dependencies : [ gtest_dep],
override_options : ['cpp_std=c++14']
)
# https://mesonbuild.com/Unit-tests.html#testing-tool
test('this is a division test', e)
- Подключение сторонних библиотек
Например: подключённый сторонний проект называется gtest, вот так:
Тогда через subproject можно получить этот project, а затем черезgtest_proj.get_variable — информацию о зависимостях gtest; например, в googletest это объявлено так:
gtest_main_dep = declare_dependency(
include_directories : gtest_incdir,
sources : [gtest_libsources, gtest_mainsources],
dependencies : dependency('threads')
)
executable очень похож на add_executable в cmake — генерирует исполняемый файл division_test.
- test
Синтаксис модульного теста:
Можно использоватьmeson test или ninja test; после выполнения будет создан лог тестирования, находящийся по адресу:
4.3 Сборка и запуск Meson-проекта¶
После описанных выше действий meson-проект готов. Далее соберём и запустим этот проект.
4.3.1 Настройка каталога сборки¶
Это аналогично mkdir build && cmake .. в cmake.
➜ gtest_div meson setup build
The Meson build system
Version: 1.2.3
Source dir: /Users/light/work/practice/gtest_div
Build dir: /Users/light/work/practice/gtest_div/build
Build type: native build
Project name: gtest_div
Project version: undefined
C++ compiler for the host machine: c++ (clang 12.0.5 "Apple clang version 12.0.5 (clang-1205.0.22.11)")
C++ linker for the host machine: c++ ld64 650.9
Host machine cpu family: x86_64
Host machine cpu: x86_64
Downloading gtest source from https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz
Download size: 867764
Downloading: ..........
Downloading gtest patch from https://wrapdb.mesonbuild.com/v2/gtest_1.14.0-1/get_patch
Download size: 2440
Downloading: ..........
Executing subproject gtest
gtest| Project name: gtest
gtest| Project version: 1.14.0
gtest| C++ compiler for the host machine: c++ (clang 12.0.5 "Apple clang version 12.0.5 (clang-1205.0.22.11)")
gtest| C++ linker for the host machine: c++ ld64 650.9
gtest| Run-time dependency threads found: YES
gtest| Dependency threads found: YES unknown (cached)
gtest| Dependency threads found: YES unknown (cached)
gtest| Dependency threads found: YES unknown (cached)
gtest| Build targets in project: 0
gtest| Subproject gtest finished.
Build targets in project: 1
gtest_div undefined
Subprojects
gtest: YES
Found ninja-1.11.1 at /usr/local/bin/ninja
4.3.2 Компиляция¶
Можно использовать две команды ниже, первый вариант:
Журнал выполнения:➜ gtest_div meson compile -C build/
INFO: autodetecting backend as ninja
INFO: calculating backend command to run: /usr/local/bin/ninja -C /Users/light/work/practice/gtest_div/build
ninja: Entering directory `/Users/light/work/practice/gtest_div/build'
[5/5] Linking target division_test
-C, но тогда понадобится cd build && ninja или cd build && meson compile.
4.3.3 Запуск и тестирование¶
При этом будет сгенерирована исполняемая программа division_test; запускаем:
➜ gtest_div ./build/division_test
Running main() from ../subprojects/googletest-1.14.0/googletest/src/gtest_main.cc
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from DivisionTest
[ RUN ] DivisionTest.Divide
[ OK ] DivisionTest.Divide (0 ms)
[ RUN ] DivisionTest.DivideByZero
[ OK ] DivisionTest.DivideByZero (0 ms)
[----------] 2 tests from DivisionTest (0 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (0 ms total)
[ PASSED ] 2 tests.
➜ gtest_div meson test -C build
ninja: Entering directory `/Users/light/work/practice/gtest_div/build'
ninja: no work to do.
1/1 this is a division test OK 0.01s
Ok: 1
Expected Fail: 0
Fail: 0
Unexpected Pass: 0
Skipped: 0
Timeout: 0
Full log written to /Users/light/work/practice/gtest_div/build/meson-logs/testlog.txt
Похожие темы¶
- Сборка проектов C++ с Bazel | C++那些事
- Совместная отладка Bazel и LLDB | C++那些事
- CMake: введение и практика | C++那些事
- Введение в управление пакетами Conan для C++ | C++那些事
- C++ Insights: взгляд на этап компиляции | C++那些事
- Интерактивные C++ Jupyter Notebook | C++那些事
- Преобразование C++ string в int | C++那些事
- Отладочный макрос dbg-macro для C++ | C++那些事
- Подробный разбор опций компиляции GCC | C++那些事
- Отладка программ на C++ с помощью GDB | C++那些事