Linux下CMake总结
Linux下CMake总结
Hoshea ZhangCMake是开源、跨平台的构建工具,可以让我们通过编写简单的配置文件去生成本地的Makefile,这个配置文件是独立于运行平台和编译器的,这样就不用亲自去编写Makefile了,而且配置文件可以直接拿到其它平台上使用,无需修改,非常方便。
本文主要讲述在Linux下如何使用CMake来编译我们的程序。
安装CMake
实验机器用的是Ubuntu16.04
我们安装完CMake后,看一下cmake版本为3.24
简单样例
文件准备
我们新建一个文件夹,在里面创建一个hello.cpp
1 |
|
再编写一个CMakeLists.txt,内容如下:
1 | cmake_minimum_required (VERSION 2.8) |
第一行意思是表示cmake的版本最低要求是2.8
第二行意思是表示本工程信息,即工程名叫demo
第三行,表示要生成的elf文件的名字叫main,使用的源文件是main.c
操作
切到main.c所在目录下,执行
cmake .
命令,构建系统是需要指定CMakeFLists.txt所在路径的,因为此时正好在本目录下,只需要.
即可,有些会创建一个build文件夹在里面cmake,那么路径就是..
生成了Makefile以及其他自动生成的文件
输入make,回车
成功生成了main
同一目录下多个源文件
接下来进入稍微复杂的例子:在同一个目录下有多个源文件。
在之前的目录下添加2个文件,testFunc.c和testFunc.h。
testFunc.c内容如下,
1 | /* |
testFunc.h内容如下,
1 | /* |
修改main.c,调用testFunc.h里声明的函数func(),
1 |
|
修改CMakeLists.txt,在add_executable的参数里把testFunc.c加进来
1 | cmake_minimum_required (VERSION 2.8) |
操作还是一样,成功生成了main
将指定目录下所有源文件存储在一个变量中
在上文基础上,再加上一个头文件和一个源文件:
1 | /* |
1 | /* |
修改CMakeLists.txt
1 | cmake_minimum_required (VERSION 2.8) |
aux_source_directory也有弊端,可能会把不需要的源文件也加进来,所以也可以使用set
1 | cmake_minimum_required (VERSION 2.8) |
不同目录下多个源文件
考虑如图所示的代码结构,我们修改CMakeLists.txt
1 | cmake_minimum_required (VERSION 2.8) |
除了第六行都比较好理解,第六行是为了main.c的头文件,因为main.c包含了两个头文件,所以要指定头文件所在位置,不然找不到
正规一点的组织结构
正规一点来说,一般会把源文件放到src目录下,把头文件放入到include文件下,生成的对象文件放入到build目录下,最终输出的elf文件会放到bin目录下,这样整个结构更加清晰。让我们把前面的文件再次重新组织下,代码结构如图所示:
方法一
写两个MakeLists.txt
最外层
1
2
3
4
5cmake_minimum_required (VERSION 2.8)
project (demo)
add_subdirectory (src)这里出现一个新的命令add_subdirectory(),这个命令可以向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制的存放位置,具体用法可以百度。
这里指定src目录下存放了源文件,当执行cmake时,就会进入src目录下去找src目录下的CMakeLists.txt,所以在src目录下也建立一个CMakeLists.txt
src层
1
2
3
4
5
6
7aux_source_directory (. SRC_LIST)
include_directories (../include)
add_executable (main ${SRC_LIST})
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)这里又出现一个新的命令set,是用于定义变量的,EXECUTABLE_OUT_PATH和PROJECT_SOURCE_DIR是CMake自带的预定义变量,其意义如下,
EXECUTABLE_OUTPUT_PATH :目标二进制可执行文件的存放位置
PROJECT_SOURCE_DIR:工程的根目录
所以,这里set的意思是把存放elf文件的位置设置为工程根目录下的bin目录。(cmake有很多预定义变量,详细的可以网上搜索一下)
在build目录下,输入cmake ..,再make,切到bin目录下main成功生成
方法二
只写一个CMakeLists.txt
1 | cmake_minimum_required (VERSION 2.8) |
动态库静态库
后面用到的时候再补充
添加编译选项
有时编译程序时想添加一些编译选项,如-Wall,-std=c++11等,就可以使用add_compile_options来进行操作。
这里以一个简单程序来做演示,main.cpp如下
1 |
|
添加控制选项
有时希望在编译代码时只编译一些指定的源码,可以使用cmake的option命令,主要遇到的情况分为2种:
本来要生成多个bin或库文件,现在只想生成部分指定的bin或库文件
对于同一个bin文件,只想编译其中部分代码(使用宏来控制)
- 假设我们现在的工程会生成2个bin文件,main1和main2,现在整体结构体如下,
外层的CMakeLists.txt内容,如下
1 | cmake_minimum_required(VERSION 3.5) |
这里使用了option命令,其第一个参数是这个option的名字,第二个参数是字符串,用来描述这个option是来干嘛的,第三个是option的值,ON或OFF,也可以不写,不写就是默认OFF。
然后编写src目录下的CMakeLists.txt,如下:
1 | cmake_minimum_required (VERSION 3.5) |
然后cd到build目录下输入cmake .. && make就可以只编译出main1,如果想编译出main2,就把MYDEBUG设置为ON,再次输入cmake .. && make重新编译。
每次想改变MYDEBUG时都需要去修改CMakeLists.txt,有点麻烦,其实可以通过cmake的命令行去操作
我们先把MYDEBUG设置为OFF,先cd到build目录,然后输入cmake .. -DMYDEBUG=ON