1. CMake概述
CMake是一个跨平台的项目构建工具,可以用来自动生成MakeFile,其编译流程如下:
编写源码->编写CMakeLists.txt->执行cmake命令->生成Makefile->执行make命令->生成目标文件
2. CMake基础写法
导入版本号
# 单行注释
# [[块注释]]
######################## 基础语法 ########################
# 导入外部的cmake文件,可以调用外部定义的方法
include(.../cmake/functions.cmake)
# 显示一条消息
message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)
cmake_minimum_required(VERSION 3.4.1)
# 定义C++的使用标准
set(CMAKE_CXX_STANDARD 11)
# 项目名称
project(DemoName)
# 包含头文件
include_directories(xxxx/include)
# 方式1:源文件列表定义成变量
set(SRC_LIST xx.cpp;xx.cpp)
# 方式2:查找源文件列表到变量中
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LIST)
# 方式3:GLOB单个目录,GLOB_RECURSE递归搜过指定目录
file(GLOB/GLOB_RECURSE SRC_LIST xxx/*.cpp)
# 方式4:set绑定多个不同的源码目录
set(SRC_ALL ${SRC_LIST1} ${SRC_LIST2} ...)
# 方式5:list绑定多个不同的源码目录
list(APPEND SRC_ALL ${SRC_LIST1} ${SRC_LIST2})
# 方式5:list绑定多个不同的源码目录,移除某些文件,文件路径要传绝对路径
list(REMOVE_ITEM ${SRC_LIST1} xxx/xxx.cpp)
# 定义宏变量
add_definitions(-D宏名称)
# 指定动态库的生成路径
set(EXECUTABLE_OUTPUT_PATH xxx/lib)
# 生成动态库
add_library(库名称 SHARED ${SRC_LIST})
# 指定动态库/静态库的生成路径
set(LIBRARY_OUTPUT_PATH xxx/lib)
# 生成静态库
add_library(库名称 STATIC ${SRC_LIST})
# 包含静态库/动态库的路径
link_directories(xxx/lib)
# 链接静态库
link_libraries(static_lib1 static_lib2 ...)
# 链接静态库/动态库(target:可能是源文件、动态库、可执行文件)
target_link_libraries(targetName PRIVATE|PUBLIC|INTERFACE xxx)
# 默认是PUBLIC
# PUBLIC后面的库会被Link到前面的target中,并且里面的符号也会被导出,可以被第三方使用;
# PRIVATE后面的库仅link到前面的target中,第三方不能感知调用了啥;
# INTERFACE后引入的库不会被链接到前面的target中,只会导出符号
# 生成可执行文件
add_executable(程序名称 ${SRC_LIST})
# 指定可执行程序输出路径,路径会自动创建
set(EXE_PATH /xx/xx)
set(EXECUTABLE_OUTPUT_PATH ${EXE_PATH}/bin)
# 指定安装目录
install(FILES xxx.h DESTINATION outputPath/xxx)
install(DIRECTORY xxx/include DESTINATION outputPath/xxx)
# 调用cmake文件中定义的function
include(xxx/xxx.cmake)
getFunctionFromCmakeFile(outPut)
######################## 常用方法 ########################
# 条件判断
if(NOT | AND | OR )
elseif()
else()
endif()
# 数值条件比较
if(LESS | GREATER | EQUAL | LESS_EQUAL| GREEATER_EQUAL)
# 字符串条件比较
if(STRLESS | STRGREATER |STREQUAL | STRLESS_EQUAL | STRGREATER_EQUAL)
# 文件操作
if(EXISTS filePath)
# 判断是否为目录,dirPath是绝对路径
if(IS_DIRECTORY dirPath)
# 判断是否为软链接,fileName是绝对路径
if(IS_SYMLINK fileName)
# 判断是不是绝对路径
if(IS_ABSOLUTE path)
# 判断元素是否在列表中
if(variable IN_LIST variable)
# 判断两个路径是否相等
if(variable PATH_EQUAL variable)
# 循环:方式1
foreach(item items)
endforeach()
# 循环:方式2
foreach(item RANGE stopNum)
foreach(item RANGE startNum stopNum stepNum)
# 通过list给列表添加数据
list(APPEND WORD aaa bbb "hello")
list(APPEND NAME ccc ddd eee fff zzz)
# # 循环:方式3,遍历列表
foreach(item1 item2 IN ZIP_LISTS WORD NAME)
message(STATUS "当前遍历的值为: item1 = ${item1}, item2=${item2}" )
endforeach()
# 循环:方式4
while()
endwhile()
functions.cmake中定义的方法
function(getFunctionFromCmakeFile outPut)
dosomething
endfunction()
将编译生成的文件放在单独build文件夹中,如下
mkdir build
cd build
cmake ..
动态库的链接具有传递性,如果动态库A链接了动态库B、C,动态库D链接了A后,也就相当于链接了动态库B、C
动态库的链接和静态库链接的区别:
- 静态库会在生成可执行程序的链接阶段被打包到可执行程序中,所以可执行程序启动,静态库就会被夹在到内存中
- 动态库在生成可执行程序的链接阶段不会被打包到可执行程序中,当可执行程序被启动并且调用了动态库中的函数时,才会被加载到内存中
3. CMake预定义的宏
| 宏 | 功能 |
|---|---|
| PROJECT_SOURCE_DIR | 使用cmake命令后紧跟的目录,一般是工程的根目录 |
| PROJECT_BINARY_DIR | 执行cmake命令的目录 |
| CMAKE_CURRENT_SOURCE_DIR | 当前处理的CMakeLists.txt所在的路径 |
| CMAKE_CURRENT_BINARY_DIR | target 编译目录 |
| EXECUTABLE_OUTPUT_PATH | 重新定义目标二进制可执行文件的存放位置 |
| LIBRARY_OUTPUT_PATH | 重新定义目标链接库文件的存放位置 |
| PROJECT_NAME | 返回通过PROJECT指令定义的项目名称 |
| CMAKE_BINARY_DIR | 项目实际构建路径,假设在build目录进行的构建,那么得到的就是这个目录的路径 |