首页 > 其他分享 >12k star 项目 cmake-examples 阅读和点评

12k star 项目 cmake-examples 阅读和点评

时间:2024-06-17 21:55:35浏览次数:18  
标签:CMake adoc 12k 例子 examples README cmake

12k star 项目 cmake-examples 阅读和点评

Author: ChrisZZ
Time: 2024.06.17

目录

项目概要

CMake 是 C/C++ 项目的主流工具, 应该有不少 CMake 用户尝试过寻找参考例子。 在 github 上搜索关键字 "cmake examples",搜索结果中排名第一个的是 https://github.com/ttroy50/cmake-examples 这个项目, 目前12.1k star。

今天来简单阅读和点评下这个项目. 整体而言,它给出的例子都比较简单, 覆盖范围也还算比较广泛,考虑到大部分 commit 是9年前和5年前提交,对于初学者而言很多例子很容易看懂, 并且每个子目录搭配了 README 文档解释说明, 整体质量还是可以的。
不过, 类似于 CMake 官方的 CMake Tutorials(至少截止3.30-rc3的版本), cmake-examples 这个仓库也有头重脚轻、详略不当的问题, 在自定义包、 执行安装后导入等方面, 例子太少, Windows 上的 DLL 等情况没覆盖到, RPATH 也没有提及, 只能说尚未覆盖中级 CMake 使用场景, 距离实际 C/C++ 生产, 仍然有不小距离。

下面来具体看下各个目录情况。

01-basic

A-hello-cmake
B-hello-headers
C-static-library
D-shared-library
E-installing
F-build-type
G-compile-flags
H-third-party-library
I-compiling-with-clang
J-building-with-ninja
K-imported-targets
L-cpp-standard
README.adoc

本节有12个子目录,一个顶级目录的文档 README.adoc。 adoc 采用了类似 Markdown 的语法,不过稍显复杂,建议改用 markdown 比较好。

A-hello-cmake

最简单的 CMake 工程, 创建了可执行程序。 作者指定了 cmake_minimum_required(VERSION 3.5), 这是很棒的一点: 在最近的 CMake 版本中, 如果指定的最小版本小于3.5,官方会提示 warning, 即将不再支持。 因此指定 3.5 为最小 cmake 版本, 至少目前来说仍然能保持很好的兼容性。 不过如果想用一些 CMake 高版本的特性, 那还是指定更高版本, 例如3.15是一个重要的里程碑, 也可以考虑指定3.25.

B-hello-headers

以 modern cmake 的方式, 指定头文件搜索目录。

C-static-library

创建静态库, 并链接到可执行程序上。 CMakeLists.txt 里使用了4空格缩进, 差评。 好的 CMakeLists.txt 应当使用2空格缩进。

D-shared-library

一个不完整的例子, 也可以认为有点糟糕的例子。 没有指定 dllimport/dllexport 这些函数符号修饰。

E-installing

安装程序的例子。 在 linux 下可以用, 但是对于 Windows 用不了, 因为被安装的是动态库, 但是 Windows 上的 DLL 本质上和 可执行程序差不多, 算是 runtime, 而不是 library。

既然用 CMake 是为了跨平台, 那应该覆盖 Windows 和 Linux 两大常见系统, macOS 上基本和 Linux 差不多。 那没有覆盖 Windows 还算是跨平台吗? 显然这时候和 Makefile 半斤八两。

F-build-type

在样例代码中提到了 CMAKE_BUILD_TYPE 和 CMAKE_CONFIGURATIONS_TYPES, 但是文档和代码中没有对 CMAKE_CONFIGURATION_TYPES 做设定和说明, 差评。

应当提及这两个变量的区别:分别用于 single-config generator 和 mulit-config generator, 然后引申出 Visual Studio, XCode, Ninja Multi-Config. 在 Linux 上, 也是可以 Ninja Multi-Config 的,为啥不写例子呢?

G-compile-flags

糟糕的例子。应当用 cmake_compile_definitions() 替代。

H-third-party-library

引入了三方库 boost。 是一个糟糕的例子, 这个糟糕体是 CMake 自身负主要责任, 因为 cmake 只是一个胶水, 给用户提供的 find_package() 看似可以指定版本号, 但是这 boost 是 apt-get 安装的, 那么系统里通常只有一个版本, 如果有多个版本, 应该由专门的包管理器, 可以下载比如20个连续的版本, 而不是只能听从 apt-get 官方的安排, 只有零星几个版本可以选择,还未必能选择到最新的版本。

I-compiling-with-clang

例子写复杂了。 其实用 CC 和 CXX 环境变量就行了。

J-building-with-ninja

还行, 终于用上 ninja 了。但是写的太潦草, 应该拿稍微有点重量的项目, 比如 ncnn 或者 opencv, 分别用 make 和 ninja 作为 generator, 比对编译耗时。 不然为什么用户要用 ninja 呢?

K-imported-targets

导入库。糟糕的例子。 其实如果要展示 imported 库, 应该手动设置库和头文件的目录, 也就是自行创建 imported target。 不然这和用 find_package() 没区别。

L-cpp-standard

给了三种写法。注意, -std=c++11 硬编码写法显然是该删除而不应该被展示的。 如果展示, 应该展示失败的案例,例如 -std=c++17 不被 MSVC 编译器识别。

小节

01-basic 的例子其实挺多的, 新人第一次学习 CMake 看这些也还算凑合, 学一下应该能干一些简单的活儿了, 但是细节还是不太行。

02-sub-projects

A-basic
README.adoc

这一节只有一个子目录, 不免让人觉得 “萎了”。 凭啥第一节放10+个例子, 第二节就一个??

这一节只包含了最简单的 add_subdirectory 的使用例子。 仍然需要补充的例子:

  • add_subdirectory 包含的目录, 是外部目录
  • 用 add_subdiretory 的方式, 包含 fmt 源码
  • add_subdiretory 添加的目录, 是包含了 prebuilt(预编译的库和头文件), 然后手写 CMakeLists.txt 文件提供 target 供外部 CMakeLists.txt 使用

03-code-generation

README.adoc
configure-files
protobuf

这一节的两个子目录, 都还是有一定实用价值的。

不过说回来, 找 protobuf 库和编译器, 应该交给一个成熟的包管理器, 不应该依赖系统 apt 安装的。 毕竟在 Windows 上没有 apt, 但是 CMake 自称跨平台, 就不应该依赖 apt 这个特定的系统包管理器。

04-static-analysis

README.adoc
clang-analyzer
clang-format
cppcheck
cppcheck-compile-commands

这一节的内容, 包含了4个子目录, 也还算丰富。是构建完 target 后, 执行一些静态分析, 其实本质是把静态分析工具黏合起来。 在 CI/CD 中可以集成, 本地构建其实还是略显麻烦, 不如让 IDE 自动提示。

举一个更糟糕的例子吧, sonar 扫描。 如果开了 Sonar 扫描, 比如在 VSCode 里安装了插件, 各种 warning 都报告给你, 正经活儿都干不了了。静态扫描的东西,适合一段时间后开启, 不适合日常开发时每次编译都触发。

05-unit-testing

README.adoc
boost
catch2-vendored
google-test-download

包含了三个测试框架的使用例子, 对于5年前的项目来说, 还算丰富。 不过现在(2024年)来看, 建议增加几个别的:

  • catch2, 是 header-only 的
  • doctest

06-installer

README.adoc
deb

显然, 作者只考虑了 Debian/Ubuntu 这样的 Linux 发行版, 没考虑 Windows 用户。 既然使用 CMake, 要做跨平台构建, 还是推荐用 .zip 作为包名。 一定要给 .deb 的例子, 那最好把 .msi, .dmg, .rpm 也放上来。

我对制作 .deb 包没兴趣, 相信大部分 CMake 初学者对于制作 .deb 包也没兴趣。

07-package-management

A-using-system-provide-packages
B-vendoring-code
C-external-project-add
D-conan
README.adoc

这一节提供了4个例子, 对于2024年的cmake入门教程来说显然是不够的, 至少还应该添加:

  • vcpkg
  • CPM

anyway, 聊胜于无。 conan 比较好的一点是, 支持锁定版本或指定版本号范围。

使用系统库,使用 vendor 库, 这都是 CMake 官方没有提供包管理器、只想着胶水黏合的设计理念下的做法, 很容易在各个平台上表现不一样, 并不能稳定的提供跨平台的体验。

external-project-add 使用了网络下载的方式, 通常网络状况不好, 因此实用价值方面有折扣; 如果是改为内网或国内专门的镜像站点, 提供源码, 那应该还算可用。

dokerfiles

作者提供了自己环境的 docker, 包括 ubuntu14.04, 16.04, 还是比较用心的, 值的表扬。

总结

本文对 cmake-examples 仓库中的每个子目录都做了阅读和点评, 从内容分布来看, 你也可以看到“头重脚轻”的问题了。基础内容比较多, 这是 cmake 设计理念导致的; 中级、进阶内容少, 这只能说明 cmake-examples 仓库中还有待改进, 也许作者也没有很丰富的 cmake 使用体验, 那么对于稍微 senior 的 cmake 学习, 就还是另外找其他资料吧!

标签:CMake,adoc,12k,例子,examples,README,cmake
From: https://www.cnblogs.com/zjutzz/p/18253278

相关文章

  • zero-shot-learning-definition-examples-comparison
    1Zero-shotlearning零样本学习。1.1任务定义利用训练集数据训练模型,使得模型能够对测试集的对象进行分类,但是训练集类别和测试集类别之间没有交集;期间需要借助类别的描述,来建立训练集和测试集之间的联系,从而使得模型有效。Zero-shotlearning就是希望我们的模型能够对其从......
  • 【CMake】变量
    1、CMAKE_CXX_STANDARD3.1版本新增target属性CXX_STANDARD的默认值。指定使用的C++规范。可选值如下:98:C++9811:C++1114:C++1417:C++1720:C++2023:C++23如果CXX_STANDARD指定的标准编译器不支持时,则会自动向下调整为编译器支持的版本,如果不想让标准自动调整,可以使用C......
  • CMake Tutorial (3.30-rc3版) 练习和点评
    CMakeTutorial练习和点评Author:ChrisZZTime:2024.06.1623:37:00CMake官方文档提供了CMakeTutorial,目前最新版是CMake-3.30-rc3,有12个Step供用户练习。CMakeTutorial是从CMake3.16版本开始能从官方网页找到,并且每一版都有改进Tutorial内容。作为有实际C/......
  • QtCreator CMakeLists.txt添加模块(Modules)
    修改以下位置,添加模块...set(CMAKE_CXX_STANDARD20)#设置C++标准#查找Qt6find_package(QTNAMESQt6Qt5REQUIREDCOMPONENTSWidgets**Multimedia**)find_package(Qt${QT_VERSION_MAJOR}REQUIREDCOMPONENTSWidgets**Multimedia**)...#链接Qt6模块和库target_l......
  • 用 Visual C++ 2022 和 CMake 编译 CUnit 静态库
    准备工作源代码获取CUnit是知名的C语言单元测框架,其源代码最初发布在sourceforge上,网址为:https://sourceforge.net/projects/cunit/截止到目前为止,最新Release版的版本号是:2.1-3,发布时间是2014年4月24日。有一些Fork自sourceforge的后续改进版本,我们选取的是https://g......
  • 【CMake系列】08-debug release特性设置
    在构建的程序版本中,一共有debugreleaseminisizerelwithDebugInfo四种,其中我们主要使用到就是debugrelease两种,这两种存在着一定的不同,debug版本用于调试,有调试信息,方便调试,体积也更大;release版本用于发布,体积更小;在使用cmake针对debugrelease配置时也存在一定的不......
  • 【CMake系列】07-export与find
    为了将我们的库文件更方便地提供给他人使用,cmake提供了一种方式,通过查找.cmake文件,将库导入项目中。本节学习的内容,就是将我们的库导出一个xxx.cmake文件,以及在项目中导入本专栏的实践代码全部放在github上,欢迎star!!!如有问题,欢迎留言、或加群【392784757】交流x......
  • 【CMake系列】06-项目结构与输出路径管理
    为了对大型项目实现更好的管理【模块化协作开发等等】,cmake提供了很多指令,可以对项目的结构进行调整、管理,便于项目的合理规划。本文我们要学习的就是项目结构的设置,以及构建程序等输出路径的设置本专栏的实践代码全部放在github上,欢迎star!!!如有问题,欢迎留言、或加群......
  • 【CMake系列】05-静态库与动态库编译
    在各种项目类型中,可能我们的项目就是一个库项目,向其他人提供我们开发好的库(windows下的dll/lib;linux下的.a/.so);有时候在一个项目中,我们对部分功能打包成库,方便在不同地方进行调用静态库和动态库对项目实现了不同程度的解耦,静态库,往往会链接时加载,代码会......
  • 【CMake系列】03-cmake 注释、常用指令 message、set、file、for_each、流程控制if
    本文给出了cmake中的一些常用的指令,可以快速了解,为后面的内容深入打点基础。本专栏的详细实践代码全部放在github上,欢迎star!!!如有问题,欢迎留言、或加群【392784757】交流注释#行注释#[[多行注释]]message(""#[[这里也可以注释]]"")message在学习时......