如何在 Meson 中执行 X?
此页面列出了常见任务的代码片段。这些代码片段主要使用 C 编译器编写,但相同的方法应该适用于几乎所有其他编译器。
设置编译器
首次运行 Meson 时,将其设置为环境变量。
$ CC=mycc meson <options>
请注意,在交叉编译中,像 CC
这样的环境变量只引用主机平台。也就是说,CC
指的是用于编译最终安装项目的机器上运行的程序的编译器。用于构建在构建机器上运行的程序的编译器可以使用 CC_FOR_BUILD
指定。你可以在交叉编译中使用它。
请注意,环境变量从来都不是使用 Meson 的习惯方式。最好使用本地文件和交叉文件。在交叉编译中,主机平台的工具只能用交叉文件指定。
这里有一个支持的所有环境变量的表格 在这里
设置链接器
新功能:0.53.0
与编译器类似,链接器是通过 <compiler variable>_LD
环境变量或通过本地文件或交叉文件中的 <compiler entry>_ld
条目来选择的。你必须注意你是使用一个自己调用链接器的编译器(大多数编译器,包括 GCC 和 Clang),还是一个直接调用的链接器(在使用 MSVC 或像 MSVC 那样的编译器(包括 Clang-Cl)时)。对于前者,c_ld
或 CC_LD
应该是传递给编译器特殊参数的值(比如 clang 和 gcc 中的 -fuse-ld
),而对于后者,它应该是一个可执行文件,比如 lld-link.exe
。
注意 在 Meson 0.53.0 中,交叉/本地文件中的 ld
条目和 LD
环境变量被使用,这导致了大量的回归,并在 0.53.1 中更改为 <lang>_ld
和 <comp variable>_LD
。
$ CC=clang CC_LD=lld meson <options>
或者
$ CC=clang-cl CC_LD=link meson <options>
或在交叉文件或本地文件中
[binaries]
c = 'clang'
c_ld = 'lld'
这里有一个支持的所有环境变量的表格 在这里
设置默认的 C/C++ 语言版本
project('myproj', 'c', 'cpp',
default_options : ['c_std=c11', 'cpp_std=c++11'])
语言版本也可以在每个目标的基础上设置。
executable(..., override_options : ['c_std=c11'])
启用线程
很多人似乎通过 cc.find_library('pthread')
或类似的方法手动执行此操作。不要这样做。它不可移植。相反,请这样做。
thread_dep = dependency('threads')
executable(..., dependencies : thread_dep)
从外部设置额外的编译器和链接器标志(例如,在构建发行版包时)
该行为与其他构建系统相同,在第一次调用时使用环境变量。当你需要重新构建源代码时,不要使用它们。
$ CFLAGS=-fsomething LDFLAGS=-Wl,--linker-flag meson <options>
仅对特定编译器使用参数
首先检查要使用的参数。
if meson.get_compiler('c').get_id() == 'clang'
extra_args = ['-fclang-flag']
else
extra_args = []
endif
然后在目标中使用它。
executable(..., c_args : extra_args)
如果你想在所有目标上使用这些参数,那么请这样做。
if meson.get_compiler('c').get_id() == 'clang'
add_global_arguments('-fclang-flag', language : 'c')
endif
将命令的输出设置为配置
txt = run_command('script', 'argument', check: true).stdout().strip()
cdata = configuration_data()
cdata.set('SOMETHING', txt)
configure_file(...)
从文件生成配置数据
fs 模块 提供了 read
函数,它支持将任意文件的内容添加到配置数据(以及其他用途)
fs = import('fs')
cdata = configuration_data()
copyright = fs.read('LICENSE')
cdata.set('COPYRIGHT', copyright)
if build_machine.system() == 'linux'
os_release = fs.read('/etc/os-release')
cdata.set('LINUX_BUILDER', os_release)
endif
configure_file(...)
使用 configure_file
生成可运行的脚本
configure_file
保留元数据,因此,如果你的模板文件具有执行权限,则生成的也将具有执行权限。
生成覆盖率报告
首先使用以下命令初始化构建目录。
$ meson setup <other flags> -Db_coverage=true
然后发出以下命令。
$ meson compile
$ meson test
$ ninja coverage-html (or coverage-xml)
覆盖率报告可以在 meson-logs 子目录中找到。
新功能:0.55.0 llvm-cov 支持与 clang 一起使用
在调试版本中添加一些优化
默认情况下,调试版本不使用任何优化。这通常是理想的方法。但是,某些项目从启用一些次要优化中受益。GCC 甚至为此有一个特定的编译器标志 -Og
。要启用其使用,只需发出以下命令。
$ meson configure -Dc_args=-Og
这会导致所有后续构建都使用此命令行参数。
使用地址清理器
Clang 和 gcc 附带了一系列分析工具,比如 地址清理器。Meson 通过 b_sanitize
选项原生支持这些工具。
$ meson setup <other options> -Db_sanitize=address
之后,只需编译代码并运行测试套件。地址清理器将中止具有错误的可执行文件,因此它们会显示为测试失败。
使用 Clang 静态分析器
安装 scan-build 程序,然后执行以下操作
$ meson setup builddir
$ ninja -C builddir scan-build
你可以使用 SCANBUILD
环境变量来选择 scan-build 可执行文件。
$ SCANBUILD=<your exe> ninja -C builddir scan-build
你可以通过创建一个脚本(例如)来使用它传递参数给 scan-build 程序
#!/bin/sh
scan-build -v --status-bugs "$@"
然后通过变量传递它(记住使用绝对路径)
$ SCANBUILD=$(pwd)/my-scan-build.sh ninja -C builddir scan-build
使用配置文件引导的优化
使用 GCC 进行配置文件引导的优化是一个两阶段操作。首先,我们使用启用了配置文件测量功能的项目设置来编译它。
$ meson setup <Meson options, such as --buildtype=debugoptimized> -Db_pgo=generate
$ meson compile -C builddir
然后,我们需要使用一些具有代表性的输入来运行程序。此步骤取决于你的项目。
完成后,我们更改编译器标志以使用生成的信息并重新构建。
$ meson configure -Db_pgo=use
$ meson compile
经过这些步骤后,生成的二进制文件将得到完全优化。
添加数学库 (-lm
) 可移植性
某些平台(例如 Linux)具有独立的数学库。其他平台(几乎所有其他平台)都没有。如何指定 m
仅在需要时使用?
cc = meson.get_compiler('c')
m_dep = cc.find_library('m', required : false)
executable(..., dependencies : m_dep)
将可执行文件安装到 libexecdir
executable(..., install : true, install_dir : get_option('libexecdir'))
使用现有的 Find<name>.cmake
文件
如果安装了 CMake,Meson 可以使用 CMake 的 find_package()
生态系统。要使用自定义 Find<name>.cmake
查找依赖项,请将 cmake_module_path
属性设置为项目中存储 CMake 脚本的路径。
cmake
子目录中 FindCmakeOnlyDep.cmake
的示例
cm_dep = dependency('CmakeOnlyDep', cmake_module_path : 'cmake')
cmake_module_path
属性仅适用于自定义 CMake 脚本。系统范围内的 CMake 脚本会自动被找到。
更多信息可以在这里找到 这里
获取默认的未找到依赖项?
null_dep = dependency('', required : false)
这可以在你想要默认值但可能稍后覆盖它的情况下使用。
# Not needed on Windows!
my_dep = dependency('', required : false)
if host_machine.system() in ['freebsd', 'netbsd', 'openbsd', 'dragonfly']
my_dep = dependency('some dep', required : false)
elif host_machine.system() == 'linux'
my_dep = dependency('some other dep', required : false)
endif
executable(
'myexe',
my_sources,
deps : [my_dep]
)
从 unity 构建中排除文件
如果你的项目支持 unity 构建,你应该修复在源文件连接在一起时出现的任何错误。但是,有时这是不可能的,例如,如果源文件是生成的。
在这种情况下,你可以将它们放在一个单独的静态库构建目标中,并覆盖 unity 设置。
generated_files = ...
unityproof_lib = static_library('unityproof', generated_files,
override_options : ['unity=off'])
main_exe = executable('main', main_sources, link_with : unityproof_lib)
要将静态库链接到另一个库目标,你可能需要使用 link_whole
而不是 link_with
。
搜索结果为