CMake—优雅地构建软件项目实践(1)

  • 交叉编译: 变量,
  • 不会递归包含子目录,仅包含指定的dir目录
  • 子模块的编译,可以将子文件夹中或者指定外部文件夹下CMakeLists.txt执行相关编译工作。
  • 编译一个动/静态库或者模块,设定的名字需在整个工程中是独一无二的,而且在整个同一个工程中,跟父子文件夹路径无关,我们便可以通过依赖该模块。
  • 添加和宏定义。

2 我们要优雅做到的构建

对于一个较大的软件项目,我们会依赖很多第三方的项目,包括源码依赖或者库依赖,然后完整的构建自己的软件项目,则需要去构建依赖项目或者找到我们所需要库;另外,软件项目会考虑到可移植性,即能够在不同的平台上也能够很好友的去构建项目以及将项目转移到另一个开发环境时能够快速的开始构建。

除了上面所说的,我们还需要考虑我们实际软件项目的架构结构,源码结构,可以让开发人员更清晰的、更快速的了解整个项目。

除此之外,C/C++ 程序员长期以来手动管理依赖,即手动查找、安装依赖,再配置构建工具(如 cmake)使用依赖。 cmake 还提供了一系列 find_package 方法帮助简化配置依赖, cmake 还支持多项目/模块管理,如果依赖源码同时被 cmake 管理构建,那么情况会简单很多,这种方式称为源码级依赖管理。 随着代码管理工具 git 出现并被广泛使用,git submodule 提供了一种不错的源码级依赖管理办法。

综上,优雅的构建软件项目,我们实现:

  • 软件项目源码依赖第三方项目
  • 软件项目库依赖第三方项目
  • 软件项目结构清晰
  • 软件项目构建在转换新环境下快速实现构建
  • 软件项目构建过程中的信息友好展示
  • 软件项目构建完成后打包发布
  • 软件项目支持跨平台构建
  • 软件项目支持交叉构建
  • git submodule & cmake管理/构建源码级依赖

另外,我们还实现一个可复用的C/C++最小开发框架(这个到后续文章中讲述):

  • 支持日志记录
  • 支持任务池/线程池
  • 支持常用相关基础操作组件
    • 时间日期操作
    • 文件读写操作
  • 支持valgrind内存泄露检查工具
  • 支持静态代码检查
  • 支持项目文档自动化

3 优雅的软件项目结构模板

3.1 模板一

一个独立的应用,应用模块之间是相互联系的,彼此难以分开,这样简单的将所有源文件放一起,头文件放一起,这个对于不是很复杂的应用是很快速的去开始构建和源文件修改操作:

3.2 模板二

源文件与头文件分功能模块存放,这种方式是比较简单,但是如果成为其他项目的3rdparty,则需要在安装上将头文件分离出来,不能很方便的被其他项目直接引用,个人觉得适用于App类项目,而非SDK项目(比如nanomsg这个开源消息中间件库就是将头文件和源文件放一起,但是作为SDK供外部链接就不是很直接、很方便了,需要做install操作之后才可以或者是将头文件搜索范围设置到依赖项目的src级别,且src目录下模块分类很明确):

3.3 模板三

4 优雅的软件项目结构模板CMake实现

这里我们只去实现模板二,其他模板大同小异。如上面模板章节所述,我们

4.1 目录结构确定

4.2 项目版本的管理

不管是SDK或者是APP项目,都会有一个版本,用来记录软件发布的每个节点。软件版本可以方便用户或者自己清楚的知道每个版本都有哪些内容的更新,可以对版本做出使用的选择或者解决版本中遇到的bug。实现版本的管理,需要能够在编译过程中清楚的体现当前版本 ,在软件中也能够获取版本 。这里版本编 的管理使用常见的格式,major是最大的版本编 ,minor为其次,patch对应着小版本里的补丁级别。当有极大的更新时,会增加major的版 ,而当有大更新,但不至于更新major时,会更新minor的版 ,若更新比较小,例如只是bug fixing,则会更新patch的版 。版本 格式示例: 、等。

在优雅的构建软件模板中,我们将版本信息放置于文件中:

注:所有的文件路径都是相对项目根目录而言。

在CMakeLists模块文件中我们去解析该文件获取版本 到CMake变量中,在添加宏函数:

在根目录CMakeLists中调用版本宏:

在后面的动静态库生成中就可以设定SOVERSION了,如:

这样就会生成一个的库和相关软链接。不过这个操作谨慎使用,因为在android平台jni依赖带版本的库是无法找到的。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年2月17日
下一篇 2020年2月17日

相关推荐