Última atualização:2026-10-12
Construir projetos C++ com Meson¶
Recentemente, ao usar alguns projetos de código aberto, percebi que todos adotaram a forma de compilação meson+ninja, abandonando o CMake e os Makefiles. Este artigo introduz o Meson, desde a instalação inicial até a escrita completa de um projeto meson.
Vamos ao conteúdo principal.
1.Instalação do Meson¶
O Meson está disponível no PyPi, portanto pode ser instalado com pip3 install meson. Certifique-se de usar o comando pip correto em cada sistema e use sempre o pip da versão Python 3.
Se preferir, também é possível instalar localmente com o comando Python padrão:
Para compilar usando o Ninja, você pode baixá-lo diretamente da página de releases do Ninja no GitHub ou por meio do PyPi:
Para mais informações sobre a instalação do Meson build, consulte o site oficial do Meson abaixo.
2. Meson Vs CMake¶
Já que todo mundo usa CMake, por que usar Meson? Quais são as vantagens e desvantagens de cada um?
Em termos de desempenho, o Meson é geralmente conhecido pela rapidez de suas compilações. O Meson foi projetado para otimizar a velocidade de compilação e se destaca especialmente nas compilações incrementais. O Meson usa o sistema de compilação Ninja como backend padrão, e o Ninja, por si só, também é reconhecido por ser rápido e eficiente.
Em comparação, a velocidade de compilação do CMake pode ser afetada pelo tamanho do projeto, especialmente em projetos grandes. O CMake usa vários geradores (como Makefiles), e o desempenho pode variar entre os diferentes geradores.
É claro que também é possível usar CMake + Ninja para melhorar a velocidade de compilação.
Na perspectiva dos projetos de código aberto, o Meson tem muitos casos de uso, por exemplo: PostgreSQL, QEMU, GNOME Software, GTK+, entre outros
2.1 Vantagens e desvantagens do Meson¶
1.Vantagens
- Baseado em Python, fácil de usar
- Suporta compilação cruzada
- Todos os objetos são fortemente tipados: como os objetos são entidades como 'dependency', 'include directory', entre outras, é difícil cometer erros de substituição de strings.
- Muito conveniente para referenciar bibliotecas de terceiros
- Muito, muito rápido, especialmente em compilações incrementais.
- Documentação n vezes melhor que a do cmake.
2.Desvantagens
- Pode não ser tão maduro quanto o CMake
- Tem dependência de Python3 + Ninja
- Geradores de projetos: o suporte de IDEs ao Meson é inferior ao do CMake
- suporte no VS Code
- https://github.com/mesonbuild/vscode-meson
- Módulos disponíveis limitados
- É necessário enviar por conta própria os projetos que não são meson para o wrapdb
- https://mesonbuild.com/Wrapdb-projects.html
2.2 Vantagens e desvantagens do CMake¶
1.Vantagens
- Bom suporte de IDEs, mais amigável para o trabalho em equipe
- Maduro, tornou-se praticamente o padrão para projetos C++
2.Desvantagens
- Compilação cruzada é difícil
- Velocidade de compilação relativamente lenta
3. Meson WrapDB¶
Como o googletest não é um projeto meson, como fazer o meson depender dele?
Da mesma forma, grpc e abseil-cpp têm uso semelhante.
Aqui é preciso primeiro introduzir o WrapDB: o Meson WrapDB é um componente do sistema de compilação Meson, usado para gerenciar e fornecer arquivos de descrição de compilação de projetos de terceiros, geralmente chamados de arquivos "wrap". Esses arquivos wrap contêm as informações necessárias para configurar e compilar projetos de terceiros, de modo que possam ser integrados facilmente a outros projetos que usam o sistema de compilação Meson.
É possível consultar bibliotecas de terceiros por meio do comando search ou do site abaixo.
https://mesonbuild.com/Wrapdb-projects.html#meson-wrapdb-packages
Tomemos o uso do gtest como exemplo:
- Buscar o gtest
Se esse comando retornar o nome do projeto empacotado, você pode passar à próxima etapa:
- Criar o diretório subprojects no seu próprio projeto e instalar o gtest via install
Neste ponto, todas as bibliotecas de terceiros das quais o seu projeto depende já estão instaladas no diretório subprojects.
Isso gerará o gtest.wrap, cujo conteúdo incluirá o seguinte.
Observação: este arquivo é gerado pelo install acima; recomenda-se não modificá-lo.
[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. Como escrever um projeto meson?¶
A seguir, a parte prática: como escrever um projeto meson?
Usaremos como exemplo um pequeno projeto de teste de divisão a/b com testes de unidade usando o gtest.
4.1 Escrever o código¶
Coloque o .h e o .cc no diretório src:
Em seguida, crie o diretório test no mesmo nível.
4.2 Gerenciamento do projeto meson¶
Adicione o arquivo meson.build na raiz do projeto, com o seguinte conteúdo:
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)
Como se pode ver, esse conteúdo é praticamente idêntico à sintaxe do Python; para quem conhece Python, esse código é muito fácil de entender. Aqui destacamos as partes mais importantes acima.
- Introduzir bibliotecas de terceiros
Por exemplo: suponha que o projeto da biblioteca de terceiros que você introduziu chame-se gtest, como segue:
Assim, é possível obter esse project por meio de subproject e, em seguida, obter as informações de dependência do gtest com gtest_proj.get_variable; por exemplo, no googletest a declaração é a seguinte:
gtest_main_dep = declare_dependency(
include_directories : gtest_incdir,
sources : [gtest_libsources, gtest_mainsources],
dependencies : dependency('threads')
)
- executable
O executable é muito semelhante ao add_executable do cmake, gerando o executável division_test.
- test
Sintaxe dos testes de unidade:
Pode-se usar meson test ou ninja test; ao final da execução, o log de testes é gerado em:
4.3 Compilar e executar o projeto Meson¶
Com as operações acima, um projeto meson está pronto. Agora, vamos compilar e executar esse projeto.
4.3.1 Configurar o diretório de compilação¶
Isso é semelhante ao mkdir build && cmake .. do cmake.
A execução é a seguinte:
➜ 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
Neste ponto, podemos ver o projeto gtest em cache no subprojects.
4.3.2 Compilar¶
Podemos usar os dois comandos a seguir; o primeiro:
Log de execução:
➜ 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
O segundo:
Esses dois comandos são essencialmente iguais: ambos compilam com o ninja. Naturalmente, também é possível omitir o -C para especificar o diretório; nesse caso, use cd build && ninja ou cd build && meson compile.
4.3.3 Executar e testar¶
Neste ponto, o executável division_test é gerado; a execução é a seguinte:
➜ 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.
Como o teste de unidade test foi adicionado no meson.build, podemos usar
Ou:
Se for especificar o diretório:
Log de execução:
➜ 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
Tópicos relacionados¶
- Construindo projetos C++ com Bazel | C++那些事
- Depuração conjunta de Bazel e LLDB | C++那些事
- CMake: introdução e prática | C++那些事
- Introdução ao gerenciamento de pacotes C++ com Conan | C++那些事
- C++ Insights: observação em tempo de compilação | C++那些事
- C++ interativo com Jupyter Notebook | C++那些事
- Converter string para int em C++ | C++那些事
- Macro de depuração dbg-macro em C++ | C++那些事
- Opções de compilação do GCC em detalhes | C++那些事
- Depuração de programas C++ com GDB | C++那些事