简介2020 年 8 月 31 日,是 CMake 诞生的 20 周年纪念日。CMake 风靡软件世界数载,至今仍然占据着大半市场。据估计,50% 以上 C++ 项目的构建系统都是 CMake。CMake 3.0 之后的版本,我们称为现代 CMake(类似于 C++ 11 之后的“现代” C++)。本文将讨论使用现代 CMake 的一些技巧。如需更深入了解 CMake 的历史,以及与 Mak e的比较,请查看文章 CMake 与 Make。1. 使用现代 CMake使用现代 CMake 最重要的技巧:如果您的项目仍在使用低于 2. 6的 CMake版本,请花一些时间和精力升级为较新的版本。经验建议使用的 CMake 版本最好在编译器版本之后。2. CMake 不仅限于 C++CMake 支持的语言种类不断增加,如 CMake 3.8 增加了 C# 和 CUDA。此外,CMake 还支持 C/C++、java、Obj/C++、Swift 和 Fortran 等多种语言。3. -std=C++11 标记已经过时与其说这是建议,不如说是告诫。不要手动添加 -STD= C++ 11 到CMAKE_CXX_FLAGS,这是过时的做法。对于现代 CMake,请改用 CXX_STANDARD 和 CXX_STANDARD_REQUIRED 标记。set(CMAKE_CXX_STANDARD 11)set(CMAKE_CXX_STANDARD_REQUIRED True)4.确保没有内部构建可以通过在顶层 CMakelists.txt 文件显式禁止内部构建,避免内部构建中与构建相关的人工产品(Artifacts)污染源目录。你可以用:if ( ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} )message( FATAL_ERROR “In-source builds not allowed! Create a build directory and run CMake from there. ” )endif()5.使用文档化的选项指定源目录和二进制目录在 CMake 中进行推荐的外部构建时,请使用有文档化的 -S 和 -B 标记来指定源代码和构建目录。旧版本使用的是未进行文档化的-H和-B标记。CMake 3.13+ 支持:cmake -S . -B build -G “Visual Studio 16 2019” ,推荐使用。对于较老的 CMake 版本:cmake -H. -Bbuild -G “MSYS Makefiles”,注意标记-B 和文件名称之间没有空格。6.使用构建预设设置,便于使用预设设置是使用文件指定 CMake 选项集合的一种方法。如果需要支持多个平台的复杂项目,最好提供(同时也方便后续使用)CMake 预设文件。预设可以保证不同编译器工具链和包的多个配置一致。预设文件是通过传递 -C 标记来加载和使用的,建议将其放在源目录的 cmake/presets 文件夹中。7.将 Linter 和 Formatter 集成到 CMake使用 linter 检查代码库,报告编译器遗漏的错误,始终是最佳选择。与程序员的 IDE 相比,在中心位置运行 linter 需要将 linting 集成到 CMake。针对 C/C++ 项目,CMake 从第3.7.2版开始支持 clang-tidy(一种静态代码分析框架)。警告将被视为 CI 生成中的错误,以检查技术债务。代码格式有时就像是信仰,开发者各执己见,互不妥协。但是,保证格式一致始终是最妥当的做法,尤其需要多个开发人员共同协作时。在 C++ 项目中,clang 格式可以轻易地集成到 CMake。8. 使用 CMake 将测试集成到构建无论你决定使用 CTest 还是 Google 测试框架,都需要确保测试是作为持续集成进程的一部分。或者可以作为构建的后期步骤(POST_BUILD),在编译时运行测试。9.使用 TARGET_() 声明构建标记和依赖关系使用 include_ directories 并不是过时的做法,或者也可以用target_include_directores 和 target_link_libraries 替代,强化项目的设计。CMake 拥有 PRIVATE, PUBLIC 和 INTERFACE 的关键字是有其充分理由的,正确使用这些关键字是保持项目组件单向分层的关键。10.清楚何时应该使用宏和函数可以使用宏和函数在 CMake 中创建自定义命令。宏不会给变量引入额外的作用域,但函数会。宏对于包装具有输出参数的命令,另外函数在其他情况下也非常使用。11.使用 CMake 将模块依赖关系可视化CMake 支持本机依赖关系的可视化。使用 ZGRViewer 等程序可以很容易地查看输出点文件。12.将 CMake 代码视为生产代码像关注生产代码一样关注 CMakeLists.txt 文件,确保对其进行了充分的注释,并遵循了所有现代 CMake 最佳实践。13. 什么时候使用 PRIVATE,PUBLIC 和 INTERFACE下面的图表很好地解释了什么时候应该在 CMake 使用 PRIVATE,PUBLIC 和 INTERFACE.
依赖关系描述PRIVATE我需要,但是依赖者不需要PUBLIC我和依赖者都需要INTERFACE我不需要,但是依赖者需要14. FindPackage VS PackageConfigFindpackage 是 CMake 或用户提供的搜索脚本,用于查找包文件。现代的包制作方会提供 <package>Config.cmake. 一旦包已安装,PackageConfig 可以向 CMake 传递其详细信息。15.充分利用所有内核加速构建在 CMake 构建过程中,可以选择 pass–parallel 标记,进行并行作业。但是,并不是所有的构建生成器都可以通过并行加速构建,CMake 3.12 之后的版本才支持并行选项。当使用分布式编译来加速 CMake 构建时,例如 Incredibuild,你需要将 –parallel 标记设置成一个非常大的数字,例如 300,指示 CMake 执行多达300个并发执行的任务。Incredibuild 可以向远程闲置内核分发多达 300 个任务,从而高效加快编译速度。16. 永不言弃其实这更像是建议而不是技巧。CMake 是大量实战测试的强大系统,因此如果您决定使用或迁移到 CMake,请不要放弃。
因为对于一个新手来说,CMake 可能并不友好。CMake 是开源的,它的社区非常有用,相关的参考文件也很实用。因此,希望大家不要轻易气馁,各种资源触手可得。最后CMake 是一个伟大的构建系统生成器,支持所有主流平台。Visual Studio 17 支持本机 CMake,Qt 从 Qt6.0 开始支持 CMake,这一切都说明 CMake 是一款成功的产品。希望以上的技巧能对你有所帮助。祝大家工作顺利。
原文:https://www.incredibuild.cn/blog/modern-cmake-tips-and-tricks
0 评论