- 构建工具
【免费下载链接】meson
The Meson Build System
Meson 1.2.0 于 2023 年 7 月 17 日发布,是继 1.1 系列之后的又一个大版本。本篇文章以 docs/markdown/Release-notes-for-1.2.0.md 为骨架,结合仓库内的交叉编译配置、解释器/后端源码与测试用例,逐项剖析该版本引入的新功能:新增 Metrowerks 嵌入式工具链支持、--genvslite构建方案、Rust 依赖 crate 重命名、kernel/subsystem机器属性、meson test通配符等。读完本文,你将掌握这些新特性的使用方式、适用场景与底层实现原理。
新增 Metrowerks C/C++ 嵌入式工具链支持
1.2.0 最大的亮点之一是新增了对 NXP Metrowerks 嵌入式工具链的支持,覆盖两个分支:
- Metrowerks Embedded ARM(
mwccarm/mwldarm/mwasmarm) - Metrowerks Embedded PowerPC(
mwcceppc/mwldeppc/mwasmeppc)
官方实现说明中特别强调,该支持目前仍属于实验性质:它在少量项目上测试通过、运行良好,但可能仍存在边界问题。从源码结构看,相关的编译器类定义在 mesonbuild/compilers/c.py、mesonbuild/compilers/cpp.py 与 mesonbuild/compilers/asm.py 中(如MetrowerksCCompilerARM、MetrowerksCCompilerEmbeddedPowerPC、MetrowerksAsmCompilerARM、MetrowerksAsmCompilerEmbeddedPowerPC),公共逻辑则封装在 mesonbuild/compilers/mixins/metrowerks.py 的MetrowerksCompilermixin 中。Ninja 后端还为 Metrowerks 编译器做了特殊处理:其 PCH 包含参数必须位于过程内分析(intraprocedural analysis)参数之后,见 mesonbuild/backend/ninjabackend.py。
仓库自带了可直接参考的交叉编译文件:
- cross/metrowerks-arm.txt(ARM 分支)
- cross/metrowerks-eppc.txt(PowerPC 分支)
- cross/metrowerks.lcf(通用链接脚本)
以 ARM 分支为例:
# This file assumes that the path to your Metrowerks Embedded ARM # toolchain is added to the environment(PATH) variable, so that # Meson can find the binaries while building. [binaries] c = 'mwccarm' c_ld = 'mwldarm' cpp = 'mwccarm' cpp_ld = 'mwldarm' ar = 'mwldarm' as = 'mwasmarm' [built-in options] c_args = ['-lang', 'c99', '-D_NITRO', '-nosyspath'] c_link_args = '@DIRNAME@' / 'metrowerks.lcf' cpp_args = ['-lang', 'c++', '-D_NITRO', '-nosyspath'] cpp_link_args = '@DIRNAME@' / 'metrowerks.lcf' [host_machine] system = 'bare metal' cpu = 'arm' cpu_family = 'arm' endian = 'little'PowerPC 分支结构相同,仅二进制名替换为mwcceppc、mwldeppc、mwasmeppc,host_machine的cpu与cpu_family改为ppc,见 cross/metrowerks-eppc.txt。
几点实操要点:
- 前提条件:工具链二进制必须已加入
PATH环境变量,Meson 才能通过交叉文件中的二进制名找到它们; @DIRNAME@占位符:链接参数中'@DIRNAME@' / 'metrowerks.lcf'会被替换为该交叉文件所在目录的绝对路径,从而引用同目录下的链接脚本;metrowerks.lcf是一个"通用用途"链接脚本,仅用于让工具链能跑通 Meson 的构建/测试流程——它定义的TEST内存区域ORIGIN=0, LENGTH=0并不会链接出真实可运行的固件。实际产品开发需要根据芯片的存储布局自行编写精调的.lcf链接脚本,参见 cross/metrowerks.lcf 中的注释。
使用方式与其他交叉编译一致:
meson setup builddir --cross-file cross/metrowerks-arm.txt meson compile -C builddir语言特性与解释器增强
str.splitlines:字符串按行切分
1.2.0 为字符串对象新增了str.splitlines()方法,可直接将字符串按行拆分为字符串数组。其实现位于 mesonbuild/interpreter/primitives/string.py,直接委托 Python 内建str.splitlines(),并用@FeatureNew('str.splitlines', '1.2.0')标注了版本门控:
lines = 'a\nb\nc'.splitlines() # lines = ['a', 'b', 'c']适用于解析生成文件内容、读取配置片段等场景,例如与fs.read()搭配把多行文本转成数组逐行处理。
generator 链式调用:generator.process(generator.process(...))
此前generator.process()的输入只能来自源文件或configure_file等直接输入,1.2.0 开始允许把另一个 generator 的输出继续喂给下一个 generator:
gen1 = generator(...) gen2 = generator(...) gen2.process(gen1.process('input.txt'))这一改动让构建链可以表达"先做一次代码生成、再做一次变换"的多级流水线,避免为中间产物手工维护 custom target 与依赖关系。
declare_dependency 新增 extra_files 关键字
declare_dependency()新增extra_files关键字,用于把额外文件附加到目标上,主要服务于 IDE 集成(例如让 VS/Xcode 工程树展示这些文件)。相关字段定义在 mesonbuild/build.py,依赖对象侧的实现见 mesonbuild/dependencies/base.py,消费方则是 Xcode 后端 mesonbuild/backend/xcodebackend.py 与 VS 后端 mesonbuild/backend/vs2010backend.py。
dep = declare_dependency( extra_files : ['include/foo.h', 'README.md'], )这些文件不会参与编译或链接,只影响生成工程的文件列表展示。
构建系统与后端
--genvslite:用 VS 解决方案外壳驱动 Ninja 构建
meson setup新增了--genvslite选项(后端名称为vs2022、vs2019等,与 VS 后端一致),目的是让 Visual Studio 用户获得"多构建配置共存于同一解决方案"的熟悉体验,同时仍然使用 Meson 自己的构建引擎。
工作原理:
- 为每个构建类型(buildtype)生成一个独立的、由 Ninja 后端配置的构建目录,目录名带对应的构建类型后缀,如
somebuilddir_debug、somebuilddir_release; - 另外生成一个
_vs后缀目录,内含多构建类型的 Visual Studio 解决方案(.sln); - 在该解决方案中执行构建/清理/重建时,实际上是去启动对应 buildtype 后缀目录下的 Meson 构建(compile),而非调用 Visual Studio 原生的 MSBuild 引擎。
其上下文对象vslite_ctx在各后端之间传递:Ninja 后端与 xcode/none 后端收到vslite_ctx会直接抛出异常(说明它们不参与 genvslite 流程),而 VS 后端则用其按 buildtype 捕获各目标的编译参数,用于 IntelliSense 字段生成,见 mesonbuild/backend/backends.py、mesonbuild/backend/ninjabackend.py 与 mesonbuild/backend/vs2010backend.py。
典型使用流程(参考 mesonbuild/backend/vs2010backend.py 中的示例注释):
meson setup -Dbin_programs=true --genvslite vs2022 builddir_vslite # 打开生成的 builddir_vslite_vs\xxx.sln,按项目构建需要注意的是,在 genvslite 生成的解决方案中,传统的 REGEN(重新生成)被替换为更轻量的 RECONFIGURE 工具,它只校验时间戳与设置是否需要重新运行meson setup --genvslite ...做完整再生成,见 mesonbuild/backend/vs2010backend.py。
vcxproj 工程新增并行生成的 .filters 文件
针对 Visual Studio 工程生成,1.2.0 在生成.vcxproj的同时会并行生成vcxproj.filters文件,使解决方案中的文件可以按其在文件系统上的目录层级展示为文件夹层次结构(默认Filter类别),改善 IDE 中的文件组织体验。相关逻辑位于 mesonbuild/backend/vs2010backend.py 附近的文件汇总处理。
Rust 相关增强
1.2.0 在 Rust 支持上投入颇多,共涉及五处改动。
rust_dependency_map:为依赖自定义 crate 名称
Rust 允许在编译一个依赖时为它定义与编译期实际 crate 名不同的别名。executable()、shared_library()等目标新增rust_dependency_map关键字,将依赖名映射为期望的 crate 名。这在"同一 crate 需要同时链接多个版本"或"想用更短的名字引用长名 crate"时非常有用:
a_dep = dependency('some-very-long-name') my_executable = executable('my-executable', 'src/main.rs', rust_dependency_map : { 'some_very_long_name' : 'a', }, dependencies : [a_dep], )底层实现:rust_dependency_map作为目标字段保存在 mesonbuild/build.py,由 Ninja 后端在生成 rustc 命令行时查表替换--extern中的 crate 名,见 mesonbuild/backend/ninjabackend.py;rust 模块的 crate 对象也提供了同名方法用于生成依赖映射,见 mesonbuild/modules/rust.py。
rust.bindgen 可向 rustc 透传额外参数
rust.bindgen()现在允许把额外参数直接传给 rustc,例如注入额外的cfg或调整警告级别。这避免了为每个 bindgen 调用手写包装脚本。
机器文件 bindgen_clang_arguments:向 clang 注入参数
bindgen 向 clang 代理参数的方式比较特殊:额外参数必须出现在--之后,过去只能通过包装脚本实现,既不优雅也难移植。1.2.0 起可在主机(host)机器文件中写入bindgen_clang_arguments字段,这些参数会被追加到每一次针对 clang 的 bindgen 调用中,特别适合注入--target之类的参数:
# native file / cross file(host 机器部分) [properties] bindgen_clang_arguments = ['--target=armv7-unknown-linux-gnueabihf']解析逻辑见 mesonbuild/envconfig.py:该字段接受单个字符串或字符串数组,否则抛出EnvironmentException。
rust.test() 新增 link_with 关键字
rust.test()现在可以直接通过link_with指定链接对象,此前需要通过declare_dependency()再经dependencies传入,新写法省去了中间层。
Rust 支持 b_ndebug 选项
Rust 目标开始支持全局b_ndebug构建选项,它控制debug_assertionscfg,进而控制debug_assert!()宏。该宏与 C 的assert()类似,可以通过命令行选项开关(-Db_ndebug=true关闭),而不像 Rust 的assert!()那样无法关闭、也不应被关闭。
Python 相关增强
Windows 上定位更精确的 Python 版本
使用 python 模块时,现在可以在 Windows 上用python3.x(x为次版本号)精确定位某个 Python 次版本,例如python3.11。其他平台上由于python3.x本身就是可执行文件名,此前已能正常工作。
-Dpython.bytecompile:一键编译全部纯 Python 字节码
新增内置选项python.bytecompile,可对通过 python 模块安装的所有纯 Python 文件编译字节码。选项定义在 mesonbuild/options.py:
UserIntegerOption('python.bytecompile', 'Whether to compile bytecode', 0, min_value=-1, max_value=2)取值范围:0不编译、1编译(py_compile)、2编译(compileall)。2会把"字节码是否编译"记为一次独立安装步骤,见 mesonbuild/modules/python.py 中的安装逻辑。
meson setup builddir -Dpython.bytecompile=2 meson install -C builddir机器(Machine)属性:kernel 与 subsystem
长期以来 Meson 只提供system属性来判别运行平台,但它不足以可靠地区分如 iOS 与 watchOS 这类同属一族的系统。1.2.0 新增两个机器属性:
kernel:底层内核类型;subsystem:系统子类别。
二者在机器对象上通过machine.kernel()/machine.subsystem()方法访问,见 mesonbuild/interpreter/interpreterobjects.py。交叉文件/本地机器文件中的解析位于 mesonbuild/envconfig.py;mesonbuild/scripts/env2mfile.py 在生成机器文件时也会一并输出system、subsystem、kernel、cpu、cpu_family、endian。
if host_machine.kernel() == 'ios' and host_machine.subsystem() == 'watchos' ... endif注意两个兼容性约束:
- 当前交叉/本地机器文件中不强制定义这两个新属性;但如果机器文件中没有定义、而构建脚本试图访问它们,Meson 会以硬错误(hard error)退出;
- 预计未来某个版本会将新属性的定义变为强制要求,因此在机器文件中主动补上
kernel与subsystem是前瞻性做法。例如 mesonbuild/envconfig.py 的注释就提到:OS400 与 AIX 的system值相同,需要靠不同的kernel值区分。
配置与命令增强
default_options / override_options 支持字典写法
此前default_options与override_options只能写成数组形式['key=value'],1.2.0 起同时支持字典形式:
project('mylib', 'c', default_options : { 'c_std' : 'c11', 'buildtype' : 'release', }, ) executable('app', 'main.c', override_options : { 'b_lto' : true, }, )两者等价,字典写法在选项较多时更清晰、不易写错键值对。
find_program('meson') 指向调用自身的 Meson
很多构建脚本需要拿到"当前调用构建脚本的那个 Meson"命令本身,过去只能各自发明脆弱的临时方案。现在直接:
meson_prog = find_program('meson')返回的外部程序对象指向被调用的 Meson 可执行文件。由于 Meson 内部也通过find_program做程序查找,这个覆盖在以下场景中同样生效:custom_target的command中写'meson'、run_command('meson', ...)、run_target的command中写'meson'。换言之,只要构建脚本里裸写meson字样,都会被解析为调用自身的那个 Meson。
meson test 支持通配符
meson test的测试名参数现在支持通配符匹配:
meson test basic* # 运行所有以 "basic" 开头的测试 meson test 'proj:*' # 运行 proj 套件下的全部测试配套的校验行为:
- 若给定的测试名不匹配任何现存测试,Meson 会报错;
- 若同时给出两个冗余测试名(如同时给
proj:basic与proj:),Meson 会记录警告。
内省(Introspection)数据增强
1.2.0 显著扩充了meson introspect输出的信息量,便于 IDE、语言服务器与自动化工具消费:
intro-compilers.json:现在列出构建中实际使用的所有编译器;intro-machines.json:新增host、build、target三台机器的信息;intro-dependencies.json:现在包含内部依赖,以及依赖之间的相互关系;intro-targets.json:新增依赖(dependencies)、vs_module_defs、win_subsystem以及链接器参数(linker parameters)。
这些字段对 IDE 的 IntelliSense 配置、依赖图可视化等场景价值明显,配合--genvslite的 IntelliSense 参数捕获(见 mesonbuild/backend/vs2010backend.py)可以进一步打通"内省数据 → 编辑器体验"的链路。
小结
Meson 1.2.0 是一份覆盖面很广的增量版本:嵌入式方向引入了实验性的 Metrowerks 工具链支持与配套交叉文件;Rust 方向补齐了 crate 重命名、bindgen 参数透传、b_ndebug等长期缺失的能力;Visual Studio 工作流通过--genvslite与.filters文件更贴近原生体验;同时解释器层面新增str.splitlines()、字典形式的 default/override options,命令层面新增meson test通配符,内省数据也更丰富。对于嵌入式开发者、Rust 用户与 Windows/VS 用户而言,本版本都提供了值得立即试用的实用改进。
如需验证或进一步研究上述特性,可直接阅读:
- 交叉文件:cross/metrowerks-arm.txt、cross/metrowerks-eppc.txt、cross/metrowerks.lcf
- 编译器实现:mesonbuild/compilers/mixins/metrowerks.py、mesonbuild/compilers/c.py、mesonbuild/compilers/asm.py
- 字符串方法:mesonbuild/interpreter/primitives/string.py
- genvslite 后端:mesonbuild/backend/backends.py、mesonbuild/backend/vs2010backend.py
- Rust 依赖映射:mesonbuild/backend/ninjabackend.py、mesonbuild/modules/rust.py
- 字节码编译选项:mesonbuild/options.py、mesonbuild/modules/python.py
- 机器属性:mesonbuild/interpreter/interpreterobjects.py、mesonbuild/envconfig.py
- 构建工具
【免费下载链接】meson
The Meson Build System
相关推荐
RmsNormBackward 算子深度解析:CANN ascend-transformer-boost 中的 RMSNorm 反向实现
RmsNormBackward 算子深度解析:CANN ascend transformer boost 中的 RMSNorm 反向实现 说明:本文以仓库内知识
构建工具radare2 Windows 原生构建指南:从 Meson/Ninja 编译到静态 Blob 与交叉编译
radare2 Windows 原生构建指南:从 Meson/Ninja 编译到静态 Blob 与交叉编译 导读 本文以 doc/windows.md http
逆向工程网络安全smithy-go 运行时与代码生成器全解析:中间件栈、编码包与 GoWriter 模板体系
smithy go 运行时与代码生成器全解析:中间件栈、编码包与 GoWriter 模板体系 导读 本文以 smithy go 仓库的 AGENTS.md ht
构建工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考