1 前言

考虑到命令行界面下编译程序并不如在 IDE 那么直观,再考虑到各位队友对 Linux 并不熟悉,如何大幅度地减轻整个项目的开发复杂度就是一个很重要的问题。

在 Linux 下有个很古老但很有用的自动化构建系统:make,它会读取当前目录下的Makefile(或其它名字)作为配置文件,并依照规则全自动完成相应的构建命令。但是有个坏处是:它相对来说比较难编写,不那么容易上手。因此又产生了大量的构建出Makefile的软件,如automakepremakecmake等等。

本人在 Linux 下使用的 IDE 是 Clion,它是基于 cmake 来管理整个工程的。而使用 cmake 并不需要安装 Clion,对于其他人来说有很大的自由度。因此,本人将花时间编写各个CMakeLists.txt等配置文件,最终达到一个命令完成构建的效果。

2 需求分析

首先,根据本人对本项目的文件结构设计(见这篇博文),配置文件必须要能够让 cmake 生成各种模块以及可执行文件。

其次,为了减少重复编译,应当生成多个相对独立的库文件,然后在最后才链接成最终的可执行文件。

最后,由于有第三方库的存在,如 Xenomai 开发库、CppUnit 单元测试库等,且安装路径不一定是固定的,故需要 cmake 通过一定的规则确定库文件的具体位置,缩小 debug 过程中问题的查找范围。

3 CMakeLists.txt 文件编写

3.1 根目录的CMakeLists.txt

该文件(见源代码)主要用于设置输出文件位置、C++语言标准、预定义符号等全局性的设置。

在配置完相关内容后,使用 add_subdirectory(src) 进入到源代码目录进行编译。

3.2 src/CMakeLists.txt

该文件(见源代码)主要用于编译项目入口。流程如下:

  1. 首先使用 find_package() 来寻找必须的第三方库的位置,如 Xenomai 开发库等。然后引入相应的引用路径和链接库路径。这一步需要编写相应的 Findxxxx.cmake 文件。
  2. 再进入 src/interpolation 等子模块目录中进行模块的编译。
  3. 最后将相应的文件用 add_executable() 命令生成主程序,并将子模块用 target_link_libraries 链接上去,完成编译。
  4. 再对单元测试进行相似的处理。

3.3 src/<子模块>/CMakeLists.txt

子模块中的编译要求较为简单,只需要目录下所有源代码文件使用 add_library() 命令编译成相应的静态链接库文件即可。

3.4 modules/Findxxxx.cmake

这是供 cmake 专用的文件,本身不直接用于构建。在本项目中位于根目录的 modules 文件夹下,详见Github 仓库。工作流程如下:

  1. 使用 find_path() 命令确定模块里面某个特有的文件所在的路径,间接定位库所在的路径。需要提供可能出现的位置来辅助查找。
  2. 判断是否找到,若找到,定义相应的变量,如 xxxx_INCLUDE_DIRSxxxx_LIBRARIES_DIRS等。

4 编译&运行

4.1 编译

由于配置文件已经做好了大部份工作,因此,我们只需要在项目的根目录(即有 README.md 的目录)下运行以下命令即可。

cmake .              # 生成 Makefile 文件
make # 使用 make 进行构建

但是,cmake 本身会产生一些如 CMakeCache.txt 等临时文件,若不想污染整个目录,建议进行如下操作:

mkdir build          # 创建 build 文件夹。build 目录已经被 git 忽略了,见 .gitignore
cd build # 进入工作文件夹
cmake .. # 注意,需要提供根目录的位置
make # 使用 make 进行构建

若无报错,则会在工作目录下的 ./build 文件夹中得到生成的二进制文件。文件结构示例如下:

build

​ | air_hockey # 主程序

​ | unit_test # 单元测试程序

​ | libinterpolation.a # 插值算法静态库

​ | libtasks.a # 任务实现静态库

...

4.2 运行

4.2.1 单元测试

单元测试程序运行如下

./build/unit_test <测试集名>

该程序有一可选参数<测试集名>,若不指定,则会运行未命名测试集(在本项目中则为所有测试);若指定,则只运行对应的测试集。

4.2.2 主项目

主项目运行如下

./build/air_hockey

在标准输入输出中可见日志信息。

最新文章

  1. Java空白final
  2. JavaWeb学习笔记——Web开发模式:Mode I和Mode II
  3. ApacheServer-----关于443端口被占用的解决方法
  4. linux 文件删除原理
  5. 在 Visual Studio 2013 中使用 Grunt, Bower 和 NPM
  6. 自定义PopupWindow 怎么设置PopupWindow的宽度充满全屏宽度
  7. 【bzoj3110】[Zjoi2013]K大数查询
  8. RS232转RS485电路图分析
  9. USACO 2.2 Party Lamps 派对灯 (lamps)
  10. Extjs打开window窗口自动加载html网页
  11. ado.net数据库操作(1)
  12. SSIS从理论到实战,再到应用
  13. 看AngularJS
  14. Vue2学习(1)
  15. php file()函数
  16. helm 部署 使用 记录
  17. Ehcache配置参数示例
  18. linux下编译C/C++ 程序
  19. 类的无参方法和Doc注释
  20. 传输模型, tcp socket套接字

热门文章

  1. msisdn与imsi简介
  2. NUTCH Exception in thread &quot;Thread-12751&quot; java.lang.OutOfMemoryError: PermGen space
  3. Hibernate 一对多自身双向关联关系 用于类别表的实现
  4. 关于安装完Node.js 出现node is not dedined 问题
  5. Android 应用程序窗口化
  6. RxJava学习(一)
  7. C++11 中的线程、锁和条件变量
  8. AOP 实现的原理简析
  9. BZOJ_1778_[Usaco2010_Hol]_Dotp_驱逐猪猡_(期望动态规划+高斯消元+矩阵)
  10. Memcached‘process_bin_delete’函数安全漏洞