You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Ubuntu下链接libc++时Google Benchmark的CMake导出错误

在CMake中链接libc++时Google Benchmark的export错误解决方案

问题背景

在Ubuntu的C++项目中,通过CMake的add_subdirectory引入llvm-project的runtimes模块构建libc++,并通过link_libraries让所有目标链接cxx_shared和cxxabi_shared。但引入Google Benchmark时,因为其src/CMakeLists.txt中的无条件export语句,导致报错:

CMake Error in external/benchmark/src/CMakeLists.txt:
export called with target "benchmark" which requires target "cxx_shared"
that is not in any export set.

CMake Error in external/benchmark/src/CMakeLists.txt:
export called with target "benchmark" which requires target "cxxabi_shared"
that is not in any export set.

该export语句未包含在BENCHMARK_ENABLE_INSTALL条件块中,而用户已设置BENCHMARK_ENABLE_INSTALL=OFF。


1. 是否有办法让CMake忽略项目中的所有导出集合?

没有直接对应CMAKE_SKIP_INSTALL_ALL_DEPENDENCY的全局忽略export的选项,但可以通过两种实用方法屏蔽Benchmark的export行为:

  • 方法一:临时覆盖export函数
    在add_subdirectory(benchmark)之前定义空的export函数,屏蔽该子目录内的所有export调用:
    # 在add_subdirectory(benchmark)前添加
    function(export)
      # 空函数覆盖默认export命令
    endfunction()
    add_subdirectory(external/benchmark EXCLUDE_FROM_ALL SYSTEM)
    # 恢复默认export函数
    unset(export)
    
  • 方法二:预修改Benchmark的导出目标列表
    创建benchmark_fix.cmake脚本:
    set(targets_to_export "")
    
    然后在主CMakeLists中指定预包含脚本,清空Benchmark要导出的目标:
    set(CMAKE_PROJECT_benchmark_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/benchmark_fix.cmake)
    add_subdirectory(external/benchmark EXCLUDE_FROM_ALL SYSTEM)
    

2. 是否应向Google Benchmark反馈修改export为条件执行?

完全合理。该export语句原本属于BENCHMARK_ENABLE_INSTALL块,后来被移出属于逻辑回归:

  • 当BENCHMARK_ENABLE_INSTALL=OFF时,导出的cmake配置文件没有实际用途,因为不会被安装或供外部项目引用。
  • 其他主流依赖(如abseil、fmt等)的export语句均包含在安装条件块中,符合CMake常规实践。
  • 可以提交Issue或PR,建议将export语句放回if(BENCHMARK_ENABLE_INSTALL)块内,或新增BENCHMARK_ENABLE_EXPORT开关变量默认与安装开关联动。

3. 是否应向llvm-project反馈为libcxx目标定义导出集合?

不建议。libcxx作为LLVM运行时库,其构建系统的设计目标是独立构建或作为LLVM整体构建的一部分,而非作为CMake子项目被其他项目导出复用:

  • cxx_shared等目标是本地构建产物,依赖特定的路径和配置,不具备跨项目导出的通用性。
  • 强行添加导出集合会导致其他项目引入时出现路径、版本不匹配的问题,违背libcxx的使用场景。

4. 是否可以自行为libcxx目标定义导出集合?

可以,但维护成本高,不推荐作为长期方案:

  • 手动导出需要处理绝对路径等问题,示例代码如下:
    add_subdirectory(external/llvm-project/runtimes EXCLUDE_FROM_ALL SYSTEM)
    # 导出libcxx目标到临时文件
    export(TARGETS cxx_shared cxxabi_shared FILE ${CMAKE_BINARY_DIR}/libcxx_export.cmake)
    # 导入导出的目标供后续项目使用
    include(${CMAKE_BINARY_DIR}/libcxx_export.cmake)
    
    这种方法会让导出文件包含本地构建的绝对路径,无法在其他环境复用,且libcxx配置(如调试、sanitizer)变化时需要重新导出。

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 15:02:52