Meson 入门指南之一

前言

Meson 介绍

Meson 的简介

Meson(The Meson Build System)是个项目构建系统,类似的构建系统有 MakefileCMakeautomake …。 Meson 是一个由 Python 实现的开源项目,其思想是,开发人员花费在构建调试上的每一秒都是浪费,同样等待构建过程直到真正开始编译都是不值得的。因此,Meson 的设计目的是在用户友好的同时不损害性能,Meson 提供客户语言(custom language)作为主要工具,用户可以使用它完成项目构建的描述。客户语言的设计目标是简单(simplicity)、清晰(clarity)、简洁(conciseness),其中很多灵感来源于 Python 语言。Meson 的另个一主要设计目的是为现代编程工具提供优秀的支持和最好的实现。这包括一些特性如:单元测试(unit testing)、代码覆盖率报告(code coverage reporting)、头文件预编译(precompiled headers)。用户不需要寻找第三方宏指令(third party macros)或编写 Shell 脚本来实现这些特性,Meson 可以开箱即用。Meson 相比 CMake 来说,不仅仅支持 C/C++,还支持多种编程语言。如今,很多项目都由 CMake 转向到了 Meson,例如 DPDKMapnik

Ninja 的简介

项目开发中一般将 Meson 和 Ninja 配合使用,Meson 负责构建项目依赖关系,Ninja 负责编译代码。Ninja 是一个轻量的构建系统,主要关注构建的速度。它与其他构建系统的区别主要在于两个方面:一是 Ninja 被设计成需要一个输入文件的形式,这个输入文件则由高级别的构建系统生成;二是 Ninja 被设计成尽可能快速执行构建的工具。

Meson 的特性

  • 支持多种平台,包括 Linux、macOS、Windows、GCC、Clang、Visual Studio 等
  • 支持多种编程语言,包括 C/C++、D、Fortran、Java、Rust
  • 支持在一个非常可读和用户友好的非图灵完整 DSL 中构建定义
  • 支持很多操作系统和裸机进行交叉编译
  • 支持极快的完整和增量构建而优化,而不牺牲正确性
  • 支持与发行版包一起工作的内置多平台依赖提供程序

Meson 的依赖

Meson 是依赖 Python 与 Ninja 实现的,依赖的版本如下:

  • Python (version 3.6 or newer)
  • Ninja (version 1.8.2 or newer)

Meson 安装

Windows 平台

  • a)在 Meson GitHub Releases 网站下载 Windows 版的安装程序,如 meson-0.60.3-64.msi
  • b)双击 meson-0.60.3-64.msi 安装程序,按默认选项直接安装 Meson
  • c)在系统的 开始菜单栏 里,找到 Visual Studio 开发人员工具(Native Tools Command Prompt for VS xxxx),双击运行后,在 CMD 窗口内执行以下命令查看 Meson 和 Ninja 的版本
    1
    2
    3
    4
    5
    > meson --version
    0.60.3

    > ninja --version
    1.10.2

Debian/Ubuntu

1
# apt install -y meson ninja-build

Fedora/CentOS

1
2
3
4
5
# yum install -y meson ninja-build

# 或者

# dnf install -y meson ninja-build

通过 PyPi 安装

Meson 可以直接通过 PyPi 安装,但必须确保使用的是 Python3 的 pip,安装命令如下:

1
# pip3 install meson ninja

或者使用标准的 Python 命令安装 Meson

1
2
3
4
5
# 安装meson
# python3 -m pip install meson

# 安装ninja
# python3 -m pip install ninja

Meson 运行

注意

若使用的是 Windows 平台,则需要在 Visual Studio 开发人员工具(Native Tools Command Prompt for VS xxxx)里执行 Meson 的命令,这是因为 C/C++ 编译器只会在该工具上运行。

  • 通过 Mesonn 初始化新的 C/C++ 项目,并使用 Meson 构建项目
1
2
3
4
5
6
7
8
9
10
11
# 创建一个新目录来保存项目文件
$ mkdir meson_project

# 进入项目目录
$ cd meson_project

# 使用Meson初始化并构建一个新的C/C++项目,会自动生成"meson.build"配置文件和C/C++源文件
$ meson init --name meson_project --build

# 项目构建完成后,默认的构建目录是build,可以直接运行构建生成的可执行文件
$ build/meson_project
  • 当项目代码发生变更后,可以进入 build 目录重新构建代码
1
2
3
4
5
# 进入build目录
$ cd build

# 重新构建代码
$ meson compile
  • Meson 项目的顶层目录结构如下
1
2
3
4
meson_project
├── build # Meson的构建目录
├── meson.build # Meson的配置文件
└── meson_project.c # C/C++源文件

Meson 指定编译参数

通过 meson configure 命令可以查看 Meson 内置的编译参数、默认值以及可选值

1
2
3
4
5
# 进入Meson项目的根目录
$ cd meson_project

# 查看Meson的编译参数
$ meson configure

Meson 项目可以通过 meson_options.txt 配置文件来增加项目特有的编译参数,如:

1
2
3
4
option('tests', type: 'boolean', value: true,
description: 'build unit tests')
option('use_hpet', type: 'boolean', value: false,
description: 'use HPET timer in EAL')

Meson 还支持在生成项目编译配置时,通过 -D 指定编译参数

1
2
3
4
5
6
7
8
9
10
11
# 进入Meson项目的根目录
$ cd meson_project

# 指定编译参数,生成输出目录
$ meson build -Dprefix=/usr -Dtests=disabled

# 进入输出目录
$ cd build

# 编译代码
$ ninja -j8

Meson 打印编译信息

通过 --verbose 参数,Messon 和 Ninja 可以打印详细的编译信息,包括编译项目时,执行的所有命令

1
2
3
4
5
6
7
8
9
10
# 进入输出目录
$ cd build

# 编译代码
$ meson compile --verbose

# 或者

# 编译代码
$ ninja --verbose

Meson 实战应用案例

构建可执行项目

注意

若使用的是 Windows 平台,则需要在 Visual Studio 开发人员工具(Native Tools Command Prompt for VS xxxx)里执行 Meson 的命令,这是因为 C/C++ 编译器只会在该工具上运行。

第一步:创建项目,目录结构如下,点击下载完整的案例代码

1
2
3
meson_demo
├── main.c
└── meson.build

main.c 的文件内容

1
2
3
4
5
6
#include <stdio.h>

int main(int argc, char *argv[]) {
printf("Hello World!\n");
return 0;
}

meson.build 的文件内容

1
2
project('meson_demo', 'c')
exe = executable('main', 'main.c')
  • 第二步:构建项目
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 进入项目目录
$ meson_demo

# 生成构建目录,build是构建目录的名称,可以自定义
$ meson build # 或者 meson setup build

# 进入构建目录
$ cd build

# 编译项目代码
$ ninja

# 运行可执行文件
$ ./main

Meson 配置文件(meson.build)的说明如下:

  • project('meson_demo', 'c'):指定项目名称和编程语言的类型
  • exe = executable('main', 'main.c'):指定可执行文件的文件名和入口源文件

构建静态库项目

注意

若使用的是 Windows 平台,则需要在 Visual Studio 开发人员工具(Native Tools Command Prompt for VS xxxx)里执行 Meson 的命令,这是因为 C/C++ 编译器只会在该工具上运行。

  • 第一步:创建静态库的项目,目录结构如下,点击下载完整的案例代码
1
2
3
4
5
static_lib_project
├── meson.build
└── src
├── static_lib.c
└── static_lib.h

static_lib.h 的文件内容

1
2
3
4
5
6
#ifndef _THIRD_LIB_
#define _THIRD_LIB_

void info_print();

#endif

static_lib.c 的文件内容

1
2
3
4
5
6
7
#include <stdio.h>
#include "static_lib.h"

void info_print()
{
printf("hello static library\n");
}

meson.build 的文件内容

1
2
project('static_lib_project', 'c')
static_library('static_lib', 'src/static_lib.c')
  • 第二步:构建项目
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 进入项目目录
$ cd static_lib_project

# 生成构建目录,build是构建目录的名称,可以自定义
$ meson build # 或者 meson setup build

# 进入构建目录
$ cd build

# 编译项目代码
$ ninja

# 项目成功编译后,会生成静态库文件"libstatic_lib.a“
$ ls -al
drwxr-xr-x. 6 clay clay 4096 08月 12 21:05 .
drwxr-xr-x. 4 clay clay 46 08月 12 10:13 ..
-rw-r--r--. 1 clay clay 2972 08月 12 10:13 build.ninja
-rw-r--r--. 1 clay clay 430 08月 12 10:13 compile_commands.json
-rw-r--r--. 1 clay clay 3564 08月 12 21:05 libstatic_lib.a
drwxr-xr-x. 2 clay clay 31 08月 12 21:05 libstatic_lib.a.p
drwxr-xr-x. 2 clay clay 4096 08月 12 10:13 meson-info
drwxr-xr-x. 2 clay clay 26 08月 12 10:13 meson-logs
drwxr-xr-x. 2 clay clay 4096 08月 12 10:13 meson-private
-rw-r--r--. 1 clay clay 808 08月 12 21:05 .ninja_deps
-rw-r--r--. 1 clay clay 152 08月 12 21:05 .ninja_log

Meson 配置文件(meson.build)的说明如下:

  • project('static_lib_project', 'c'):指定项目名称和编程语言的类型
  • static_library('static_lib', 'src/static_lib.c'):指定静态库文件的文件名和入口源文件

构建加载第三方静态库的可执行项目

注意

若使用的是 Windows 平台,则需要在 Visual Studio 开发人员工具(Native Tools Command Prompt for VS xxxx)里执行 Meson 的命令,这是因为 C/C++ 编译器只会在该工具上运行。

  • 第一步:创建静态库的项目,目录结构如下,点击下载完整的案例代码
1
2
3
4
5
6
7
8
load_static_lib_project
├── meson.build
└── src
├── include
│   └── static_lib.h
├── lib
│   └── libstatic_lib.a
└── main.c

static_lib.h 的文件内容

1
2
3
4
5
6
#ifndef _THIRD_LIB_
#define _THIRD_LIB_

void info_print();

#endif

main.c 的文件内容

1
2
3
4
5
6
7
#include <stdio.h>
#include "static_lib.h"

int main(int argc, char *argv[]) {
info_print();
return 0;
}

meson.build 的文件内容

1
2
3
project('load_static_lib_project', 'c')
libs=meson.get_compiler('c').find_library('static_lib', dirs : join_paths(meson.source_root(),'src/lib'))
executable('load_static_lib', 'src/main.c', dependencies : libs, include_directories : 'src/include')
  • 第二步:构建项目
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 进入项目目录
$ cd load_static_lib_project

# 生成构建目录,build是构建目录的名称,可以自定义
$ meson build # 或者 meson setup build

# 进入构建目录
$ cd build

# 编译项目代码
$ ninja

# 运行可执行文件
$ ./load_static_lib

Meson 配置文件(meson.build)的说明如下:

  • 第一行:指定项目名称和编程语言的类型
  • 第二行:指定静态库文件的名称和所在目录的路径,文件名称不需要加”lib” 前缀
  • 第三行:指定可执行文件的文件名、入口源文件、静态库的头文件所在目录的路径

参考博客