为什么使用CMake
对于一段高级程序编写的代码,计算机是不能直接拿来运行的,我们需要对其进行预处理——>编译——>汇编——>链接四个步骤,它才能成为计算机可识别的可执行文件。
对于单个程序,我们直接使用gcc/g++编译就可以,一般来说gcc test.c -o test就可以生成可执行文件test。
当然,我们可以添加一些选项,比如链接静态库、动态库啥的
gcc test.c -o test -L./myPath -lstaticLib gcc test.c -o test -L./myPath -ldynamicLib # -L :添加库文件搜索路径。例如,-L./myPath会让链接器在/my/path下查找库文件 # -l :链接库文件,链接器会在指定的路径下查找库文件。 # 编译器会根据目录中是否有对应的.a或.so文件进行选择,两者都存在时优选.so动态库
对于少数文件我们可以直接在终端输入上述命令进行编译,但是,一旦我们的文件比较多,又有很多的编译选项,这时在命令行逐个输入就很麻烦了,此时我们可以将这些命令按一定的语法写在一个文件里,这个文件就叫Makefile,此时我们只需要执行Makefile这一个文件就可以编译整个项目了。
但是,Makefile的语法相对来说比较复杂,越大的项目,使用Makefile来管理就越复杂
CMake的作用是自行生成Makefile,相比直接写Makefile,CMake配置文件的编写更简洁和易于理解,更容易扩展,此外还能够跨平台支持(Makefile是特定于某个平台的),因此,CMake目前使用比较广泛。
下面分享CMake配置文件CMakeLists.txt中一些最常见的命令。
常见指令分类与汇总
| 类别 | 命令 | 含义 | 参数说明 | 
|---|---|---|---|
| 基础 | cmake_minimum_required (VERSION 2.8) | CMake的最低版本要求 | |
| 基础 |  project (learn_cmake) | 项目的工程名 | |
| 辅助 | aux_source_directory(dir SRC_LIST) | 将dir下的源文件添加到变量SRC_LIST中 | 源文件的目录 源文件集合变量 | 
| 辅助 | set(SRC_LIST main.c testFunc.c) | 设置变量的值 | 变量名称 变量的值 | 
| 辅助 | ${SRC_LIST} | 变量引用语法,取SRC_LIST变量代表的值 | |
| 辅助 | message(STATUS "The SRC_LIST is: ${SRC_LIST}") | 输出信息到终端 | 消息类型 要输出的字符串 | 
| 辅助 | option(MYDEBUG "enable debug compilation" OFF) | 定义变量用于条件编译 | 变量名 描述 变量值 | 
| 辅助 | set(CACHE MY_GLOBAL_STRING "simple") | 使变量MY_GLOBAL_STRING在整个CMake项目可见 | 将变量设置为CACHE缓存变量 | 
| 可执行文件 | add_executable(main ${SRC_LIST}}) | 生成可执行文件main | 可执行文件 源文件列表 | 
| 头文件搜索 | include_directories(dir1 dir2) | 引入头文件的搜索路径 | 头文件搜索路径 | 
| 多级目录 | add_subdirectory(src) | 编译时添加子目录src中的CMakeLists.txt | |
| 库文件 | add_library(libNameShared SHARED ${SRC_LIST}) | 生成库 | 库名称 静态/动态 源文件 | 
| 库文件 | find_library(MY_LIB_PATH myLib searchPath) | 查找myLib库文件 | 变量名 查找的库 查找路径 | 
| 库文件 | target_link_libraries(execute_file ${MY_LIB_PATH}) | 指定可执行文件链接哪些库 | 可执行文件 待链接的库 | 
| 其它 | set_target_properties(libNameShared PROPERTIES OUTPUT_NAME "libName") | 设置最终生成的库的一些属性 | 库名称 属性的开始 目标文件名称(键) 库新名称(值) | 
| 其它 | add_compile_options(-std=c++11) | 添加全局编译选项 | |
| 补充 | |||
| 库函数 | find_package(OpenCV REQUIRED) | 查找OpenCV库,并能自动处理库的依赖项 | find_package适用于大多数第三方库和复杂的库配置;find_library适用于自定义库或简单的库配置 | 
