ENABLE_ASAN 开启但本机缺少 libasan 时,CMake 会误报找不到 Threads
问题概述
在 Fedora + GCC 15 环境下执行:
CMake 配置阶段可能会失败,并报错:
Could NOT find Threads (missing: Threads_FOUND)
但实际问题并不是系统缺少 pthread。查看
build_debug/CMakeFiles/CMakeConfigureLog.yaml 后可以发现,真正的链接错误是
AddressSanitizer 运行库不可用:
/usr/bin/ld: 找不到 /usr/lib64/libasan.so.8.0.0: 没有那个文件或目录
collect2: 错误:ld 返回 1
MiniOB 默认开启 ENABLE_ASAN,并且在调用
find_package(Threads REQUIRED) 之前,就把 -fsanitize=address 添加到了
CMAKE_C_FLAGS / CMAKE_CXX_FLAGS 中。因此 CMake 内部用于检测 Threads 的
try-compile 也会带上 ASAN 参数。
如果当前系统的 GCC/ASAN 运行库不匹配,或者缺少对应的 libasan 文件,
Threads 检测就会因为 ASAN 链接失败而失败,最终给用户展示成一个比较误导的
Threads_FOUND 错误。
环境信息
操作系统:Fedora Linux
CMake:3.31.11
GCC/G++:15.2.1
构建命令:bash build.sh
构建类型:debug
ENABLE_ASAN:ON
复现步骤
直接执行:
观察到的输出:
-- Instrumenting with Address Sanitizer
-- CMAKE_CXX_FLAGS is -Wall -Werror -Wno-error=sign-compare -DDEBUG -g -O0 -fno-omit-frame-pointer -fsanitize=address -fsanitize-address-use-after-scope
-- Using replxx for line reading
CMake Error at /usr/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:233 (message):
Could NOT find Threads (missing: Threads_FOUND)
Call Stack (most recent call first):
/usr/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:603 (_FPHSA_FAILURE_MESSAGE)
/usr/share/cmake/Modules/FindThreads.cmake:226 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
CMakeLists.txt:178 (FIND_PACKAGE)
而 build_debug/CMakeFiles/CMakeConfigureLog.yaml 中的真实错误是:
/usr/bin/ld: 找不到 /usr/lib64/libasan.so.8.0.0: 没有那个文件或目录
期望行为
如果当前编译器环境无法正常链接 AddressSanitizer,CMake 应该给出更直接的
ASAN 相关提示,而不是误报 Could NOT find Threads。
例如可以提示:
Address Sanitizer is not available with the current compiler setup.
Please install the matching libasan package or configure with -DENABLE_ASAN=OFF.
或者在检测到 ASAN 不可用时,自动关闭 ENABLE_ASAN 并继续配置。
可能的修复方式
可以在真正把 -fsanitize=address 追加到全局编译参数之前,先用一个最小程序
检测当前编译器是否能够正常编译并链接 ASAN:
IF (ENABLE_ASAN)
INCLUDE(CheckCXXSourceCompiles)
SET(CMAKE_REQUIRED_FLAGS_SAVED "${CMAKE_REQUIRED_FLAGS}")
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fsanitize=address")
CHECK_CXX_SOURCE_COMPILES("int main() { return 0; }" COMPILER_SUPPORTS_ASAN)
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS_SAVED}")
ENDIF()
IF (ENABLE_ASAN AND NOT COMPILER_SUPPORTS_ASAN)
MESSAGE(WARNING "Address Sanitizer is not available with the current compiler setup. Disable ENABLE_ASAN or install the matching libasan package.")
SET(ENABLE_ASAN OFF CACHE BOOL "Enable build with address sanitizer" FORCE)
ENDIF()
这样当 ASAN 不可用时,用户可以看到明确的 ASAN 提示;同时
find_package(Threads REQUIRED) 不会因为继承了不可用的 ASAN 参数而失败。
ENABLE_ASAN开启但本机缺少libasan时,CMake 会误报找不到 Threads问题概述
在 Fedora + GCC 15 环境下执行:
CMake 配置阶段可能会失败,并报错:
但实际问题并不是系统缺少 pthread。查看
build_debug/CMakeFiles/CMakeConfigureLog.yaml后可以发现,真正的链接错误是AddressSanitizer 运行库不可用:
MiniOB 默认开启
ENABLE_ASAN,并且在调用find_package(Threads REQUIRED)之前,就把-fsanitize=address添加到了CMAKE_C_FLAGS/CMAKE_CXX_FLAGS中。因此 CMake 内部用于检测 Threads 的try-compile 也会带上 ASAN 参数。
如果当前系统的 GCC/ASAN 运行库不匹配,或者缺少对应的
libasan文件,Threads 检测就会因为 ASAN 链接失败而失败,最终给用户展示成一个比较误导的
Threads_FOUND错误。环境信息
复现步骤
直接执行:
观察到的输出:
而
build_debug/CMakeFiles/CMakeConfigureLog.yaml中的真实错误是:期望行为
如果当前编译器环境无法正常链接 AddressSanitizer,CMake 应该给出更直接的
ASAN 相关提示,而不是误报
Could NOT find Threads。例如可以提示:
或者在检测到 ASAN 不可用时,自动关闭
ENABLE_ASAN并继续配置。可能的修复方式
可以在真正把
-fsanitize=address追加到全局编译参数之前,先用一个最小程序检测当前编译器是否能够正常编译并链接 ASAN:
这样当 ASAN 不可用时,用户可以看到明确的 ASAN 提示;同时
find_package(Threads REQUIRED)不会因为继承了不可用的 ASAN 参数而失败。