我想为我的存储库构建一个测试程序,启用未定义行为清理(至少使用GCC,可能还有clang)。我知道如何手动完成:
- 将
-fsanitize=undefined
添加到编译标志 - 将
-lubsan
添加到链接标志 确保安装了合适的
libubsan
版本。现在,在CMake中,我希望像下面这样的工作:
find_package(ubsan)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR
CMAKE_CXX_COMPILER_ID STREQUAL "Clang" )
target_compile_options(my_test PRIVATE "-fsanitize=undefined")
endif()
target_link_libraries(ubsan::ubsan)
…但没有这样的版本(如CMake 3.21.0-rc2)。那么,我该怎么做呢?找一个FindUBSan。从哪里来的?也许做点别的?
PS -这个问题同样适用于C
所有的编译都需要启用杀毒器(混合和匹配通常是不可能的),并且启用杀毒器是编译器特定的;因此,它是一个工具链选项。
在工具链文件中,包括以下内容:
set(CMAKE_C_FLAGS_INIT "-fsanitize=undefined")
set(CMAKE_CXX_FLAGS_INIT "-fsanitize=undefined")
您也可以在命令行中设置CMAKE_<LANG>_FLAGS
以包含-fsanitize=undefined
。
完整的示例:
alex@alex-ubuntu:~/test$ tree
.
├── CMakeLists.txt
├── main.cpp
└── ubsan.cmake
0 directories, 3 files
alex@alex-ubuntu:~/test$ cat CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project(test)
add_executable(main main.cpp)
alex@alex-ubuntu:~/test$ cat main.cpp
int main () { return 0; }
alex@alex-ubuntu:~/test$ cat ubsan.cmake
set(CMAKE_C_FLAGS_INIT "-fsanitize=undefined")
set(CMAKE_CXX_FLAGS_INIT "-fsanitize=undefined")
alex@alex-ubuntu:~/test$ cmake -G Ninja -S . -B build --toolchain ubsan.cmake
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/build
alex@alex-ubuntu:~/test$ cmake --build build/ -- -v
[1/2] /usr/bin/c++ -fsanitize=undefined -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d -o CMakeFiles/main.dir/main.cpp.o -c /home/alex/test/main.cpp
[2/2] : && /usr/bin/c++ -fsanitize=undefined CMakeFiles/main.dir/main.cpp.o -o main && :
alex@alex-ubuntu:~/test$ ldd build/main
linux-vdso.so.1 (0x00007ffc9dd75000)
libubsan.so.1 => /lib/x86_64-linux-gnu/libubsan.so.1 (0x00007f79a4b52000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f79a4960000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f79a495a000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f79a4937000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f79a4755000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f79a4738000)
/lib64/ld-linux-x86-64.so.2 (0x00007f79a550a000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f79a45e9000)
在CMake中启用UB清理的惯用方法是什么?
没有"惯用的方法"-它是编译器特有的。做的事:
- 将-fsanitize=undefined添加到编译标志
target_compile_options(my_test PUBLIC -fsanitize=undefined)
target_link_options(my_test PUBLIC -fsanitize=undefined)
您可以检查CheckCXXCompilerFlag
是否支持该选项。