cmake 教程
cmake 与make
make是一个工具,它控制可执行程序和程序源文件中非源码文件的生成。“make” 工具需要清楚地知道如何构建程序。通过"makefile"文件知晓如何构建你的程序。这个文件列出了所有非源码文件以及如何由别的文件来计算它。当你编写一个程序时,你应该为它写一个makefile文件,这样才有可能通过make来构建你的程序。简而言之,就是自动化项目编链过程,及控制生成最终的目标文件。
CMake支持跨平台Make。cmake辨别使用哪种编译器去编译给出的源码种类,为每一种类型的目标平台按照正确的顺序调用命令。
cmake与make对比具有以下优点:
- 自动发现跨平台系统库。
- 自动发现和管理的工具集。
- 更容易将文件编译进共享库,以一种平台无关的方式或者比make更容易使用的生成方式。
CMake 比 make更复杂。从长远来看,最好能够学会使用它。
CMake 简介
基本操作流程
cmake .. # 根据CMakeLists.txt生成Makefile文件。保证在CMakeLists.txt所在目录。
make # make 命令
CMake的执行就是这么简单,其难点在于如何编写CMakeLists.txt文件。
CMakeLists.txt
CMake 的所有的语句都写在一个叫 CMakeLists.txt 的文件中。当 CMakeLists.txt 文件确定后,可以用 ccmake 命令对相关 的变量值进行配置。这个命令必须指向 CMakeLists.txt 所在的目录。配置完成之后,应用 cmake 命令生成相应的 makefile(在Unix like系统下) 或者 project文件(指定用window下的相应编程工具编译时)。
cmake 要求工程 主目录 和所有存放 源代码子目录 下都要编写 CMakeLists.txt 文件,注意大小写.
CMakeLists.txt(命令说明)
## 指定允许执行的最低 CMake 版本要求;不写会出警告
cmake_minimum_required( VERSION 2.8 ) ## 指定项目的名称,通常对应于项目文件夹名
project( SAMPLE_SINGLE_DIR ) ## 指定引用目录
include_directories( include ) ## 自动构建源文件目录
aux_source_directory( src DIR_SRCS ) ## 指定编译目标文件
add_executable( demo ${DIR_SRCS} ) ## 添加链接库,相同于指定-l参数(此处没有用到)
#TARGET_LINK_LIBRARIES(${PROJECT_NAME} m) #比如我们用到了libm.so(命名规则:lib+name+.so
CMakeLists.txt(命令)
介绍
- 每个需要进行cmake操作的目录下面都必须存在文件CMakeLists.txt.
- camke指令不区分大小写。
- 变量使用**${}**方式取值,但是在IF控制语句中是直接使用变量名的。
- 指令(参数1 参数2 …),参数使用括弧,参数之间使用空格或分号分开。
CMake中常用预定义变量
Cmake的预定义变量
- PROJECT_SOURCE_DIR:工程根目录
- PROJECT_BINARY_DIR:运行cmake命令的目录
- CMAKE_INCLUDE_PATH:环境变量,非cmake变量
- CMAKE_LIBRARY_PATH: 环境变量
- CMAKE_CURRENT_SOURCE_DIR:当前处理的CMakeLists.txt文件所在路径
- CMAKE_CURRENT_BINARY_DIR:target编译路径
CMake常用语法
- CMAKE_MINIMUM_REQUIRED
用于说明CMake最低版本要求。
cmake_minimum_required(VERSION 2.6)
- PROJECT
格式:
PROJECT(name)
- SET
格式:
SET(VAR [VALUE] [CACHE TYPEDOCSTRING [FORCE]]])
例:
SET(CMAKE_INSTALL_PREFIX /usr/local)
- ADD_SUBDIRECTORY
ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
用于向当前工程添加存放源文件的子目录。
- INCLUDE_DERECTORIES(dir1 dir2)
向工程添加多个特定的头文件搜索路径,路径之间用空格分隔。
INCLUDE_DIRECTORIES(/usr/include/thrift)
- ADD_EXECUTABLE
ADD_EXECUTABLE(exename srcname)
- exename: 可执行文件名
- srcname: 生成可执行文件的源文件
- ADD_EXECUTABEL(hello ${LIST})
- SET(LIST main.c
rpc/CRNode.cpp
rpc/task.cpp)
- ADD_LIBRARY
ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2)
- libname: 库文件名称;
- [SHARED|STATIC|MODULE]: 生成库文件类型(共享库/静态库)
- source1, ... , sourceN: 生成库所依赖的源文件
ADD_LIBRARY(hello SHARED &{LIST})
- LINK_DIRECTORIES
LINK_DIRECTORIES(directory1 directory2)
添加外部库的搜索路径
- TARGET_LINK_LIBRARIES
TARGET_LINK_LIBRARIES(target library1 library2 ..)
target: 目标文件
library1, ..., library2:链接外部库文件
- MESSAGE
MESSAGE()
向终端输出用户定义的信息或变量值
-SET_TARGET_PROPERTIES
设置目标的某些属性,改变它们构建的方式。
格式:
SET_TARGET_PROPERTIES(target1 target2 ...
PROPERTIES prop1 value1 prop2 value2 ...)
1
2
该指令为一个目标设置属性,语法是列出所有用户想要变更的文件,然后提供想要设置的值。用户可以使用任何想用的属性与对应的值,并在随后的代码中调用GET_TARGET_PROPERTY命令取出属性的值。
影响目标输出文件的属性PROPERTIES详述如下:
(1) PREFIX, SUFFIX
PREFIX覆盖了默认的目标名前缀(如lib);
SUFFIX覆盖了默认的目标名后缀(如.so)。
(2) IMPORT_PREFIX, IMPORT_PREFIX
与PREFIX, SUFFIX是等价的属性,但针对的是DLL导入库(即共享库目标)。
(3) OUTPUT_NAME
构建目标时,OUTPUT_NAME用来设置目标的真实名称。
(4) LINK_FLAGS
为一个目标的链接阶段添加额外标志。
LINK_FLAGS_< CONFIG >将为配置< CONFIG >添加链接标志,如DEBUG, RELEASE, MINSIZEREL, RELWITHDEBINFO。
(5) COMPILE_FLAGS
设置附加的编译器标志,在构建目标内的源文件时被用到。
(6) LINKER_LANGUAGE
改变链接可执行文件或共享库的工具。默认值是设置与库中文件相匹配的语言。
CXX与C是该属性的公共值。
(7) VERSION, SOVERSION
VERSION指定构建的版本号,SOVERSION指定构建的API版本号。
构建或安装时,如果平台支持符号链接,且链接器支持so名称,那么恰当的符号链接将会被创建。如果只指定两者中的一个,缺失的另一个假定为具有相同版本号。
例1:
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
例2:
SET_TARGET_PROPERTIES(hello PROPERTEIES VERSION 1.2 SOVERSION 1)
该指令用于控制版本,VERSION指代动态库版本,SOVERSION指代API版本。
参考文档
https://www.jianshu.com/p/c417e4ab8b30
https://blog.csdn.net/ajianyingxiaoqinghan/article/details/70229799
https://blog.csdn.net/ajianyingxiaoqinghan/article/details/70230902
https://blog.csdn.net/liukang325/article/details/52222023
https://blog.csdn.net/ajianyingxiaoqinghan/article/details/70338459