CMake基本操作
CMake安装和版本
1 | sudo apt install cmake |
编译单个文件
例如编译源文件main.c
, 在相同目录下编写CMakeLists.txt文件,内容为:
1 | cmake_minimum_required (VERSION 2.8) |
第一行表示CMake最低版本为2.8;第二行表示项目名为demo
;第三行add_executable()
第一个参数为最终生成的elf文件名称为main
,
使用的源文件为main.c
。
在main.c目录下输入以下命令运行CMake:
cmake .
可以看到目录下生成了MakeFile
最后再运行make
命令,完成编译,其中main
文件为可执行文件。
编译同一目录下的多个文件
CMakeLists文件编写如下:
1 | cmake_minimum_required (VERSION 2.8) |
其实就是add_executable()
中后面的参数将所有源文件添加进去。
当目录中的源文件过多的时候,上述写法就不可行了。可以使用以下命令将某个目录下所有源文件存入一个变量中:
1 | aux_source_directory(dir var) |
其中dir
参数为指定目录,var
参数为存储源文件的变量名称。对于编译上述同一目录中多个文件的CMakeLists.txt可以编写为:
1 | cmake_minimum_required (VERSION 2.8) |
有时不想将目录中的所有源文件都添加进来,这时可以使用set()
命令来新建变量,该命令可以指定添加的文件。
1 | cmake_minimum_required (VERSION 2.8) |
编译不同目录下的多个源文件
程序源文件较多时,可能会放在多个子目录下,如:
此时CMakeLists.txt写法可以为:
1 | cmake_minimum_required (VERSION 2.8) |
一般项目结构下的编译
通常,将源文件放到src
目录中,头文件放到include
目录中,生成的对象文件放到build
目录下,最终输出的elf文件放到bin
目录下。结构为:
其中有两个CMakelists.txt文件,工程根目录下CMakeLists.txt文件的内容为:
1 | cmake_minimum_required (VERSION 2.8) |
其中add_subdirectory()
命令添加一个子目录并构建该子目录,第一个参数为子目录,该目录下包含了CMakeLists.txt文件和源文件。可以是绝对路径或者相对路径。当执行cmake
时,会进入src目录下找CMakeLists.txt文件。
内层的CMakeLists.txt文件的内容为:
1 | aux_source_directory (. SRC_LIST) |
其中命令set()
中的参数为CMake预定义的变量,含义为:
- EXECUTABLE_OUTPUT_PATH:目标二进制可执行文件的存放位置
- PROJECT_SOURCE_DIR:工程根目录
因此,上述set()
命令含义是将存放elf文件的位置设置为工程根目录下的bin目录。
编写完成之后切换至build目录,执行cmake ..
然后在build目录下执行make
完成编译,可以看到在bin目录下产生了可执行文件main。
在build
目录下执行cmake的原因是:使cmake运行时产生的编译文件存放于build
目录,免得其与程序其它部分混在一起造成污染。
使用一个CMakeLists.txt
前面的方法外部CMakeLists.txt使用add_subdirectory()
命令来引导其它目录中的CMakeLists.txt,实际上也可以整个使用一个CMakeLists.txt来组织编译过程。其写法为:
1 | cmake_minimum_required (VERSION 2.8) |
动态库和静态库编译
有时只编译动态库和静态库,此时项目结构如下:
编写CMakeLists.txt文件如下:
1 | cmake_minimum_required (VERSION 3.5) |
其中:
add_library()
命令用于生成动态库或者静态库,第一个参数为生成库的名字,第二个参数指定生成动态库还是静态库,第三个参数指定生成库所用到的源文件。
set_target_properties()
命令用于为一个目标设置属性,上面将两个库的输出名称属性设置为“testFun”,使用该命令能使两者输出名称相同,只是后缀不同(.a和.so)。
最后的LIBRARY_OUTPUT_PATH为库文件的默认输出路径,这里设置为lib目录。
之后进入build目录下分别执行cmake ..
和make
命令,可以看到在lib目录下生成了.a和.so静态和动态库。
使用动态库和静态库
若需要使用生成的库或别人的库,即以下项目中lib下的库:
其中main.cpp
使用了#include "te.h"
工程目录下的CMakeLists.txt内容如下:
1 | cmake_minimum_required (VERSION 3.5) |
共有两个新命令:
find_library()
:在指定的目录下查找库,第一个参数为变量名称,第二个参数是库名称,第三个参数为HINTS,第四个参数为库路径。
target_link_libraries()
:把目标文件和库文件进行链接。
使用find_library
能够提前发现错误,不必等到链接时报错。 在build目录下执行cmake ..
和make
,在bin目录中可以看到最后生成的可执行main文件。
注:在lib目录下有testFun的静态库和动态库,find_library默认查找动态库,若需要指定使用动态库还是静态库,可以直接指定:find_library(TESTFUN_LIB, libtestFun.so ...)
。
添加编译选项
添加编译选项可以使用add_compile_options
来进行操作。例如:
1 | cmake_munimum_required (VERSION 2.8) |