十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MongoDB 仓库内置 Abseil:从 add_subdirectory 到传统安装的 CMake 构建全指南

MongoDB 仓库内置 Abseil:从 add_subdirectory 到传统安装的 CMake 构建全指南 MongoDB 仓库内置 Abseil从 add_subdirectory 到传统安装的 CMake 构建全指南【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo导读Abseil 是 Google 开源的 C 公共库集合MongoDB 以源码形式将其内置在src/third_party/abseil-cpp/dist目录下。Abseil 随仓库自带一套完整的 CMake 构建脚本入口为 CMakeLists.txt可在 Linux、macOS、Windows 等广泛平台上使用这也是 CMake 中 C 代表 cross-platform跨平台的由来。本文基于 Abseil 官方构建文档 CMake/README.md系统讲解两种主流接入方式——嵌入子目录add_subdirectory与传统安装build install find_package并逐项拆解全部 CMake 配置开关及其在源码中的真实实现帮助你在一小时内把 Abseil 正确接入自己的 CMake 工程并跑通测试。一、两种接入方式怎么选Abseil 的 CMake 构建脚本会在配置期根据当前工程形态自动决定行为这一点在 CMakeLists.txt 中有直接体现# when absl is included as subproject (i.e. using add_subdirectory(abseil-cpp)) # in the source tree of a project that uses it, install rules are disabled. if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) option(ABSL_ENABLE_INSTALL Enable install rule OFF) else() option(ABSL_ENABLE_INSTALL Enable install rule ON) endif()即当 Abseil 作为子项目被add_subdirectory()引入时ABSL_ENABLE_INSTALL默认自动关闭只有当 Abseil 本身就是顶层工程时才默认开启安装规则。出于API/ABI 兼容性的考虑官方强烈建议把 Abseil 构建在你的项目子目录中或作为嵌入式依赖而不是单独安装后全局使用。原因在于Abseil 的编译选项、absl::base/options.h中的 ABI 开关会随编译环境变化独立安装的 Abseil 与被调用的代码可能因编译标准不一致而产生 ABI 撕裂。因此使用场景推荐方式中小型应用、希望快速上手拷贝或 git submodule 到子目录add_subdirectory引入大型工程、多项目共享同一版本传统安装模式install 后find_package(absl)二、方式一通过 add_subdirectory 嵌入项目2.1 四个步骤准备测试依赖如果想构建 Abseil 自带的测试需要先把 Google Test 集成进 CMake 工程若不需要测试配置时传-DBUILD_TESTINGOFF或-DABSL_BUILD_TESTINGOFF即可。放置源码把 Abseil 下载后拷贝进 CMake 工程的子目录或以 git submodule 方式挂载MongoDB 仓库即采用内置源码目录的等价形态位于src/third_party/abseil-cpp/dist。引入目标用 CMake 命令add_subdirectory(abseil-cpp)把 Abseil 直接包含进当前工程。链接库把要使用的absl::目标加入可执行文件或库的target_link_libraries()段。2.2 应用工程完整示例以下 CMakeLists.txt 是官方文档给出的应用工程示例可直接复制使用cmake_minimum_required(VERSION 3.16) project(my_app_project) # Pick the C standard to compile with. # Abseil currently supports C17 and C20. set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_subdirectory(abseil-cpp) add_executable(my_exe source.cpp) target_link_libraries(my_exe absl::base absl::synchronization absl::strings)需要注意CMake 3.16 是 Abseil 官方支持的最低版本CMakeLists.txt 第 19 行即写有cmake_minimum_required(VERSION 3.16)C 标准方面Abseil 目前支持 C17 与 C20。absl::前缀目标并非手工创建的占位名而是在 AbseilHelpers.cmake 中通过别名机制统一导出add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME})所以absl::base、absl::strings、absl::synchronization等名字与源码中的实际 target 一一对应链接时不会产生重名冲突。2.3 库开发者把 C 标准决策权留给顶层应用如果你开发的是一个面向其他客户端使用的库则不应在库内直接设置全局CMAKE_CXX_STANDARD而应把它留空或仅在作为顶层工程构建时才设置并把最低 C 标准约束在 target 层面。官方文档给出的标准做法如下cmake_minimum_required(VERSION 3.16) project(my_lib_project) # Leave C standard up to the root application, so set it only if this is the # current top-level CMake project. if(CMAKE_SOURCE_DIR STREQUAL my_lib_project_SOURCE_DIR) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) endif() add_subdirectory(abseil-cpp) add_library(my_lib source.cpp) target_link_libraries(my_lib absl::base absl::synchronization absl::strings) # Enforce that my_lib requires C17. Important to document for clients that they # must set CMAKE_CXX_STANDARD to 17 or higher for proper Abseil ABI compatibility # (since otherwise, Abseil library targets could be compiled with a lower C # standard than my_lib). target_compile_features(my_lib PUBLIC cxx_std_17) if(CMAKE_CXX_STANDARD LESS 17) message(FATAL_ERROR my_lib_project requires CMAKE_CXX_STANDARD 17 (got: ${CMAKE_CXX_STANDARD})) endif()其中的关键点在最后几行通过target_compile_features(my_lib PUBLIC cxx_std_17)把 C17 要求传播给所有下游使用者同时用CMAKE_CXX_STANDARD LESS 17做显式校验防止 Abseil 库目标被编译成比my_lib更低的标准从而规避 ABI 不兼容。这一设计的底层支撑是ABSL_PROPAGATE_CXX_STD选项默认 ON。在 AbseilHelpers.cmake 中每个 Abseil 库目标都会执行if(ABSL_PROPAGATE_CXX_STD) # Abseil libraries require C17 as the current minimum standard. When # compiled with a higher standard (either because it is the compilers # default or explicitly requested), then Abseil requires that standard. target_compile_features(${_NAME} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE}) endif()即每个absl::目标都带PUBLIC的编译特性要求会把所需 C 标准自动传播给链接它的上层目标。因此只要上层应用设置一个足够高且一致的CMAKE_CXX_STANDARD整条依赖链的编译标准就是统一的。三、运行 Abseil 自带测试3.1 启用测试使用-DABSL_BUILD_TESTINGON即可构建 Abseil 的测试但前提是BUILD_TESTING也必须为 ON默认即为 ON。在 CMakeLists.txt 中可看到option(ABSL_BUILD_TESTING If ON, Abseil will build all of Abseils own tests. OFF) option(ABSL_BUILD_TEST_HELPERS If ON, Abseil will build libraries that you can use to write tests against Abseil code. This option requires that Abseil is configured to use GoogleTest. OFF)注意ABSL_BUILD_TESTING默认是 OFF与ABSL_BUILD_TEST_HELPERS构建可供你编写针对 Abseil 代码测试的辅助库相互独立。3.2 提供 Google Test 依赖的两种方式官方提供了两条路任选其一-DABSL_USE_GOOGLETEST_HEADON在 CMake 配置阶段自动把最新版 Google Test 源码下载到构建目录并与 Abseil 测试一起编译。背后的实现是 DownloadGTest.cmake它先configure_file生成外部工程再execute_process完成配置与构建最后add_subdirectory引入gtest、gtest_main等目标。手动集成 Google Test参照 Googletest 官方 CMake 使用说明把 Googletest 作为依赖接入你的构建。需要留意的是这两个选项存在互斥校验在 CMakeLists.txt 中若同时设置了ABSL_USE_GOOGLETEST_HEAD和ABSL_GOOGLETEST_DOWNLOAD_URL配置阶段会直接FATAL_ERROR报错。3.3 只跑 Abseil 测试的最小脚本官方文档提供了如下可直接执行的完整脚本cd path/to/abseil-cpp mkdir build cd build cmake -DABSL_BUILD_TESTINGON -DABSL_USE_GOOGLETEST_HEADON .. make -j ctest按此流程make -j会同时编译 Abseil 库与其测试二进制ctest则执行全部注册的测试用例并输出汇总结果。需要说明的适用前提是目前 Abseil 团队仅在 Linux 环境下通过 CMake 跑测试其他平台的支持仍在推进中。四、方式二传统 CMake 安装流程build install find_package对于更大的工程官方推荐分离构建的传统模式先单独构建、安装 Google Test 与 Abseil再让使用方通过find_package消费。4.1 第一步构建并安装 Google Testcmake -S /source/googletest -B /build/googletest -DCMAKE_BUILD_TYPERelease -DCMAKE_INSTALL_PREFIX/installation/dir -DBUILD_GMOCKON cmake --build /build/googletest --target install4.2 第二步配置并构建 Abseil配置时必须同时开启ABSL_USE_EXTERNAL_GOOGLETEST、ABSL_FIND_GOOGLETEST与ABSL_ENABLE_INSTALLcmake -S /source/abseil-cpp -B /build/abseil-cpp -DCMAKE_PREFIX_PATH/installation/dir -DCMAKE_INSTALL_PREFIX/installation/dir -DABSL_ENABLE_INSTALLON -DABSL_USE_EXTERNAL_GOOGLETESTON -DABSL_FIND_GOOGLETESTON cmake --build /temporary/build/abseil-cpp参数含义CMAKE_PREFIX_PATH指定 Google Test 已安装的位置CMAKE_INSTALL_PREFIX指定 Abseil 的目标安装位置二者可以不同。4.3 第三步跑测试并安装ctest --test-dir /temporary/build/abseil-cpp cmake --build /temporary/build/abseil-cpp --target install--target install执行后Abseil 会把头文件、编译产物与 CMake package 配置安装到安装前缀下。仓库中的集成测试脚本 install_test_project/test.sh 完整复现了这一流程先curl下载指定版本的 Googletest 压缩包并安装再以-DABSL_USE_EXTERNAL_GOOGLETESTON -DABSL_FIND_GOOGLETESTON -DABSL_BUILD_TESTINGON构建安装 Abseil随后ctest验证最后用find_package(absl)编译一个调用absl::strings的simple可执行程序并校验输出。4.4 消费方find_package(absl)安装完成后使用方工程只需cmake_minimum_required(VERSION 3.16) project(absl_cmake_testing CXX) add_executable(simple simple.cc) find_package(absl REQUIRED) target_link_libraries(simple absl::strings absl::config)这正是仓库中 install_test_project/CMakeLists.txt 的实际内容。安装时生成并写入lib/cmake/absl/的abslConfig.cmake模板见 abslConfig.cmake.in会依次完成find_dependency(Threads)、PACKAGE_INIT展开并include对应的abslTargets.cmake从而把absl::strings等带absl::命名空间的目标导出给消费方。值得一提的细节安装流程会生成一份options-pinned.h并替换安装目录下的absl/base/options.h。在 CMakeLists.txt 中CMake 会根据当前编译标准把ABSL_OPTION_USE_STD_*宏从自动检测值 2改写为使用标准库值 1或禁用值 0——这正是保证安装版 ABI 与编译标准一致的关键机制也是官方建议安装版务必保证CMAKE_CXX_STANDARD 17的底层原因。五、CMake 选项速查表综合官方文档与 CMakeLists.txt 源码全部相关开关汇总如下选项默认值作用ABSL_ENABLE_INSTALL顶层工程 ON / 子项目 OFF是否启用安装规则作为子项目被add_subdirectory引入时自动关闭ABSL_BUILD_TESTINGOFF是否构建 Abseil 自身全部测试需与BUILD_TESTINGON默认同时成立ABSL_BUILD_TEST_HELPERSOFF是否构建供外部编写针对 Abseil 代码测试的辅助库ABSL_USE_EXTERNAL_GOOGLETESTOFFON 时假定 GoogleTest 目标已由包含方工程提供适用于add_subdirectory场景ABSL_FIND_GOOGLETEST依赖ABSL_USE_EXTERNAL_GOOGLETEST默认 ONON 时用find_package(GTest)查找已安装的 Google TestABSL_USE_GOOGLETEST_HEADOFFON 时配置阶段自动下载最新 Google Testmain.zip源码到构建目录ABSL_GOOGLETEST_DOWNLOAD_URL空指定从某个 ZIP 地址下载特定版本的 Google TestABSL_LOCAL_GOOGLETEST_DIR/usr/src/googletest前两者均未设置时使用本地已检出的 Google Test 目录ABSL_PROPAGATE_CXX_STDON通过target_compile_features(... PUBLIC/INTERFACE ...)把所需 C 标准传播给链接方ABSL_BUILD_MONOLITHIC_SHARED_LIBSOFF将 Abseil 构建为单一共享库Windows 上始终启用未设置BUILD_SHARED_LIBS时会被忽略并告警ABSL_USE_SYSTEM_INCLUDESOFF把 Abseil 头文件标记为 SYSTEM include 以静默其内部警告ABSL_MSVC_STATIC_RUNTIMEOFF链接静态运行时库MSVC 专用六、可用的 Abseil CMake 公共目标摘录以下为官方文档给出的非穷尽公共目标清单均可直接在target_link_libraries中使用absl::algorithm absl::base absl::debugging absl::flat_hash_map absl::flags absl::memory absl::meta absl::numeric absl::random_random absl::strings absl::synchronization absl::time absl::utility如需完整目标清单可查阅 Abseil 源码各模块下的 CMake 声明每个库模块通过absl_cc_library(...)宏定义并自动生成absl::别名宏定义位于 AbseilHelpers.cmake。MongoDB 工程中也大量使用absl::strings、absl::base等目标读者可直接参考仓库内 src/third_party/abseil-cpp/dist/CMakeLists.txt 观察各目标的组织方式。七、小结应用接入add_subdirectory(abseil-cpp)target_link_libraries(my_exe absl::strings ...)并设置CMAKE_CXX_STANDARD 17/20三步即完成集成。库的接入把 C 标准约束下沉到target_compile_features并校验CMAKE_CXX_STANDARD 17保证 ABI 一致。跑测试-DABSL_BUILD_TESTINGON配合ABSL_USE_GOOGLETEST_HEAD自动下载或外部/本地 Google Test。传统安装依次安装 Google Test 与 Abseil开启ABSL_ENABLE_INSTALL、ABSL_USE_EXTERNAL_GOOGLETEST、ABSL_FIND_GOOGLETEST消费方find_package(absl)即可。排错入口安装版 ABI 由构建期生成的options-pinned.h钉死务必保证全链路的CMAKE_CXX_STANDARD一致互斥选项如ABSL_USE_GOOGLETEST_HEAD与ABSL_GOOGLETEST_DOWNLOAD_URL同开会在配置期直接报错。所有结论均可在 MongoDB 仓库内置的 Abseil 源码 CMake/README.md、CMakeLists.txt、AbseilHelpers.cmake 及 install_test_project/test.sh 中直接验证按上述流程操作即可在本地工程中稳定复现。【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表