如何仅在Meson的Debug构建中启用Sanitizers?
问题描述
我希望仅在Debug构建中启用Sanitizers,且不想手动添加编译标志(手动添加无法实现跨平台/跨编译器兼容)。但使用以下配置时,Meson将b_sanitize=address,undefined当作文件路径传递给编译器,导致报错。当前环境为Linux Fedora Asahi Remix,使用Meson v1.3.1。
错误配置代码
project( 'Foo', 'c', version: '0.0.1', license: 'GPL-3.0-or-later', meson_version: '>= 0.64.0', default_options: [ 'c_std=c2x', 'warning_level=everything', ], ) # 问题代码段:尝试仅在Debug构建启用Sanitizer,Release构建启用-Werror if get_option('buildtype').startswith('debug') message('Building a debug release') add_project_arguments('b_sanitize=address,undefined', language: 'c') else add_project_arguments(['werror=true'], language: 'c') endif foo_sources = files('main.c') executable( meson.project_name().to_lower(), foo_sources, )
错误输出
$ LC_MESSAGES=C meson compile --verbose -C builddir INFO: autodetecting backend as ninja INFO: calculating backend command to run: /usr/bin/ninja -C /home/jan/Projekte/Own/Tmp/builddir -v ninja: Entering directory `/home/jan/Projekte/Own/Tmp/builddir' [1/2] ccache cc -Ifoo.p -I. -I.. -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Wpedantic -Wcast-qual -Wconversion -Wfloat-equal -Wformat=2 -Winline -Wmissing-declarations -Wredundant-decls -Wshadow -Wundef -Wuninitialized -Wwrite-strings -Wdisabled-optimization -Wpacked -Wpadded -Wmultichar -Wswitch-default -Wswitch-enum -Wunused-macros -Wmissing-include-dirs -Wunsafe-loop-optimizations -Wstack-protector -Wstrict-overflow=5 -Warray-bounds=2 -Wlogical-op -Wstrict-aliasing=3 -Wvla -Wdouble-promotion -Wsuggest-attribute=const -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure -Wtrampolines -Wvector-operation-performance -Wsuggest-attribute=format -Wdate-time -Wformat-signedness -Wnormalized=nfc -Wduplicated-cond -Wnull-dereference -Wshift-negative-value -Wshift-overflow=2 -Wunused-const-variable=2 -Walloca -Walloc-zero -Wformat-overflow=2 -Wformat-truncation=2 -Wstringop-overflow=3 -Wduplicated-branches -Wcast-align=strict -Wsuggest-attribute=cold -Wsuggest-attribute=malloc -Wattribute-alias=2 -Wanalyzer-too-complex -Warith-conversion -Wbidi-chars=ucn -Wopenacc-parallelism -Wtrivial-auto-var-init -Wbad-function-cast -Wmissing-prototypes -Wnested-externs -Wstrict-prototypes -Wold-style-definition -Winit-self -Wc++-compat -Wunsuffixed-float-constants -std=c2x -O0 -g b_sanitize=address,undefined -MD -MQ foo.p/main.c.o -MF foo.p/main.c.o.d -o foo.p/main.c.o -c ../main.c FAILED: foo.p/main.c.o ccache cc -Ifoo.p -I. -I.. -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Wpedantic -Wcast-qual -Wconversion -Wfloat-equal -Wformat=2 -Winline -Wmissing-declarations -Wredundant-decls -Wshadow -Wundef -Wuninitialized -Wwrite-strings -Wdisabled-optimization -Wpacked -Wpadded -Wmultichar -Wswitch-default -Wswitch-enum -Wunused-macros -Wmissing-include-dirs -Wunsafe-loop-optimizations -Wstack-protector -Wstrict-overflow=5 -Warray-bounds=2 -Wlogical-op -Wstrict-aliasing=3 -Wvla -Wdouble-promotion -Wsuggest-attribute=const -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure -Wtrampolines -Wvector-operation-performance -Wsuggest-attribute=format -Wdate-time -Wformat-signedness -Wnormalized=nfc -Wduplicated-cond -Wnull-dereference -Wshift-negative-value -Wshift-overflow=2 -Wunused-const-variable=2 -Walloca -Walloc-zero -Wformat-overflow=2 -Wformat-truncation=2 -Wstringop-overflow=3 -Wduplicated-branches -Wcast-align=strict -Wsuggest-attribute=cold -Wsuggest-attribute=malloc -Wattribute-alias=2 -Wanalyzer-too-complex -Warith-conversion -Wbidi-chars=ucn -Wopenacc-parallelism -Wtrivial-auto-var-init -Wbad-function-cast -Wmissing-prototypes -Wnested-externs -Wstrict-prototypes -Wold-style-definition -Winit-self -Wc++-compat -Wunsuffixed-float-constants -std=c2x -O0 -g b_sanitize=address,undefined -MD -MQ foo.p/main.c.o -MF foo.p/main.c.o.d -o foo.p/main.c.o -c ../main.c cc: warning: b_sanitize=address,undefined: linker input file unused because linking not done cc: error: b_sanitize=address,undefined: linker input file not found: No such file or directory ninja: build stopped: subcommand failed.
解决方案
问题根源是把Meson内置选项字符串直接传给了add_project_arguments——该函数用于传递编译器原生命令行参数,而b_sanitize、werror是Meson的全局配置选项,需用set_option()设置,Meson会自动将这些选项转换为对应编译器的正确标志,实现跨平台兼容。
修改后的配置代码:
project( 'Foo', 'c', version: '0.0.1', license: 'GPL-3.0-or-later', meson_version: '>= 0.64.0', default_options: [ 'c_std=c2x', 'warning_level=everything', ], ) # 根据构建类型设置对应全局选项 if get_option('buildtype').startswith('debug') message('Building a debug release') # 设置Sanitizer,Meson自动适配编译器/链接器标志 set_option('b_sanitize', 'address,undefined') else # 发布构建启用Werror set_option('werror', true) endif foo_sources = files('main.c') executable( meson.project_name().to_lower(), foo_sources, )
补充说明
set_option()是Meson修改全局配置选项的官方方式,支持所有内置选项(如b_sanitize、werror、lto等),能自动处理不同编译器的差异(比如GCC和Clang的Sanitizer标志差异)。- 若需为特定目标而非全项目启用Sanitizer,可使用编译器对象的
get_sanitization_flags()方法,示例:
这种方式需手动处理编译和链接阶段的标志,适合局部启用场景,全局c_compiler = meson.get_compiler('c') sanitizer_flags = c_compiler.get_sanitization_flags(['address', 'undefined']) executable( 'foo', foo_sources, c_args: sanitizer_flags, link_args: sanitizer_flags, )set_option()则更简洁高效。
内容的提问来源于stack exchange,提问作者user23276701
相关产品推荐
相关产品推荐

