对cmake编译框架的思考

对cmake编译框架的思考

范吉民

大型项目编译的复杂性

简单开发时,基本不太注重编译过程。特别是没有交叉编译或者在Windows下开发,直接使用一个gcc命令或者是点击一下build按钮就好了。对于大型项目,可能存在下面的一些问题需要考虑:

  • 可能涉及很多的编译工具链。可能有ARM的,也可能会涉及riscv的工具链,还可能涉及普通的Linux下的工具链,甚至Windows下的工具链。
  • 可能涉及很多个相对独立又相互关联的项目。
  • 可能需要进行复杂的预处理。很多配置相关的数据,直接写死在代码里会使得代码越来越难维护。
  • 可能需要进行复杂的后处理。很多场景需要多次编译,一次编译的结果是后续编译的某些数据输入。
  • 可能涉及很多编译场景,需要良好的灵活性。并非每次编译都是为了最终的产品,不同的目的对编译的需求也不一样。例如调试的时候,可能对内存消耗这些就不很关心,相反内存消耗不能成为限制调试的原因。调优的时候,可能并不期望将很多与关注模块无关的代码和数据引入到生成的镜像中。
  • 需要良好的扩展性。每添加一个功能模块就需要考虑整个工程如何编译,显然是不太合理的。

CMake的基本工作原理

CMake当下还是十分流行的。它的作用是生成和编译(宿主机)平台相符合的Makefile文件,其本身并不直接对源文件进行编译。所以简单来说,它的工作或者作用是:

  • 确定编译器和编译参数
  • 确定哪些源文件要被编译
  • 确定头文件的位置
  • 确定所需要的库的位置
  • 确定输出的形式,即静态库,动态库还是可执行文件等

CMake在确定上述信息之后,就可以生成对应的Makefile文件了。需要注意的是,CMake有一个试错编译,也就是说在为用户的Project生成Makefile之前,会先使用户指定的编译器和编译参数编译其自身的一些demo源文件,只有这些源文件编译通过之后,才会为用户的项目工作。这一特点可能会使得交叉编译时遇到一些奇怪的错误,特别是不是gcc工具链。因此CMake还有一个重要的工作是:

  • 初步检验设定的编译器和编译参数是否可行

大型项目的CMake模型

在此,我并不打算写出来一个通用的CMake结构,因为要做到通用实在是太难了。然而,给出一个总体上的步骤(思维模型),我相信对具体处理这类问题还是很有帮助的。

  • 树状三段式结构:
  1. 顶层的CMake负责处理配置。为具体项目做准备,但是绝对不涉及具体项目的源文件。大型的预处理和也可以放在这里。
  2. 底层CMake负责收集需要编译的源文件。这是模块层面,决定要编译哪些源文件。
  3. 中层的CMake则完成对链接的处理。这是最终的输出层面,决定将收集到的文件,或者收集到的库等等如何处理。后处理也可以放到这里。

随着子项目的增多,中层CMake会增多,随着功能模块的增多,底层CMake会增多。随着工具链或者编译场景的增多,顶层CMake会变得越来越复杂。

这是一个建立CMake工程的思维模型,并不是每个层次的CMake都必须要有明确的对应文件,这是一个思维上的分层。

2022年7月

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值