1、 Cmake概述
Cmake是一个项目构建工具,并且是跨平台的。他解决了自己写MakeFile不能跨平台,文件依赖关系太强的问题。
Cmake允许开发者指定整个工程的编译流程,自动生成本地化的Makefile和工程文件,最后用户只需要make
编译即可。
2、Cmake使用步骤
如下图所示的文件目录,所有的源文件都在一个目录下,编写CmakeLists.txt
如下
- 当前目录下编写CmakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(PCF)
add_executable(app.exe add.c div.c main.c multi.c sub.c)
如上图所示,为一个最简单的CmakeLists.txt
的使用方法。
- 新建build文件夹并进入
mkdir build
cd build
- 执行Cmake
cmake ..
make
3、定义变量
3.1 定义和使用变量
set(SRC add.c div.c mult.c main.c)
set(SRC add.c;div.c;mult.c;main.c)
add_executable(app.exe ${SRC})
3.2 指定C++标准
#增加-std=c++11
set(CMAKE_CXX_STANDARD 11)
#增加-std=c++14
set(CMAKE_CXX_STANDARD 14)
#增加-std=c++17
set(CMAKE_CXX_STANDARD 17)
3.3 指定输出路径
set(HOME /home/pcf)
set(WORDDIR ./3rdparty/workdir)
set(EXECUTABLE_OUTPUT_PATH ${
HOME}/bin)
如果这个路径不存在,会自动创建
4、搜索文件
4.1 方式
公式
aux_source_directory(dir var)
- dir 要搜索的路径
- var 将从dir目录下搜索到的源文件列表存储到该变量中
cmake_minimum_required(VERSION 3.0)
project(CALC)
set(HOME /home/pcf)
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin)
include_directories(${PROJECT_SOURCE_DIR}/include)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LIST)
add_executable(app ${SRC_LIST})
4.2 方式2
公式
file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)
- GLOB: 只在指定目录下搜索
- GLOB_RECURSE:递归搜索指定目录
- 变量:存储搜索结果
- 要搜索的文件路径和文件类型
file(GLOB_RECURSE CPP_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
file(GLOB_RECURSE C_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c)
set(SRC_LIST CPP_SRC C_SRC) #组合
file(GLOB MAIN_HEAD ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
cmake_minimum_required(VERSION 3.0)
project(CALC)
set(HOME /home/pcf)
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
add_executable(app ${SRC_LIST})
5、包含头文件
include_directories(头文件路径)
6、制作库文件
6.1 制作静态库
在cmake中,如果要制作静态库,需要使用的命令如下:
cmake_minimum_required(VERSION 3.1)
project(test)
file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
include_directories(${PROJECT_SOURCE_DIR}/include)
add_library(rcp STATIC ${SRC})
#制作后生成的静态库名字为 librcp.a
6.2 制作动态库
cmake_minimum_required(VERSION 3.1)
project(test)
file(GLOB SRC ${PROJECT_SOURCE_DIR}/src)
include_directories(${PROJECT_SOURCE_DIR}/include)
add_library(rcp SHARED ${SRC})
6.3 指定动态库生成路径
set(LIBRARY_OUTPUT_PATH /home/liuzhenguang/lib)
7、链接静态库
:::warning
链接静态库
指定静态库路径
:::
cmake_minimum_required(VERSION 3.0)
project(test)
include_directories(${PROJECT_SOURCE_DIR}/include)#指定头文件路径
link_directories(${PROJECT_SOURCE_DIR}/lib)#指定静态库路径
link_libraries(rcp clac)#链接静态库
add_executable(app ${SRC_LIST})
8、链接动态库
target_link_libraries(
<target>
<PRIVATE|PUBLIC|INTERFACE> <items>
<PRIVATE|PUBLIC|INTERFACE> <items>
...
)
**target:**指定要加载的动态库文件的名字
- 该文件可能是一个源文件
- 该文件可能是一个动态库
- 该文件可能是一个可执行文件
:::warning
应该将链接动态库的地方放在最后
:::
cmake_minimum_required(VERSION 3.0)
project(test)
file(GLOB SRC ${PROJECT_SRC_DIR}/src)
include_directories(${PROJECT_SRC_DIR}/include)
link_directories(${PROJECT_SRC_DIR}/lib)
add_executable(app ${SRC})
target_link_libraries(app
PUBLIC calc
PUBLIC add)
9、日志
10、list操作
- 添加
list(APPEND tmp "xxx1" "xxx2" ${SRC})
添加xxx1、xxx2和SRC到tmp中
- 删除指定元素
_ITEM SRC ${PROJECT_SOURCE_DIR}/src/main.cpp)
从SRC
中删除main.cpp
删除时要使用绝对路径
- 获取 list 的长度。
- list(LENGTH )
- LENGTH:子命令LENGTH用于读取列表长度
- :当前操作的列表
- :新创建的变量,用于存储列表的长度。
- 读取列表中指定索引的的元素,可以指定多个索引
- list(GET [ …] )
- :当前操作的列表
- :列表元素的索引,从0开始编号;索引也可以是负数,-1表示列表的最后一个元素,-2表示列表倒数第二个元素,以此类推。
- :新创建的变量,存储指定索引元素的返回结果,也是一个列表。
- 将列表中的元素用连接符(字符串)连接起来组成一个字符串
- list (JOIN )
- :当前操作的列表
- :指定的连接符(字符串)
- :新创建的变量,存储返回的字符串
- 查找列表是否存在指定的元素,若果未找到,返回-1
- list(FIND )
- :当前操作的列表
- :要搜索的元素
- :新创建的变量
- 如果列表中存在,那么返回在列表中的索引,如果未找到则返回-1。
- 在list中指定的位置插入若干元素
- list(INSERT <element_index> [ …])
- 将元素插入到列表的0索引位置
- list (PREPEND [ …])
- 将列表中最后元素移除
- list (POP_BACK […])
- 将列表中第一个元素移除
- list (POP_FRONT […])
- 将指定索引的元素从列表中移除
- list (REMOVE_AT [ …])
- 移除列表中的重复元素
- list (REMOVE_DUPLICATES )
- 列表翻转
- list(REVERSE )
- 列表排序
- list (SORT [COMPARE ] [CASE ] [ORDER ])
COMPARE:指定排序方法。有如下几种值可选:
STRING:按照字母顺序进行排序,为默认的排序方法
FILE_BASENAME:如果是一系列路径名,会使用basename进行排序
NATURAL:使用自然数顺序排序
CASE:指明是否大小写敏感。有如下几种值可选:
SENSITIVE: 按照大小写敏感的方式进行排序,为默认值
INSENSITIVE:按照大小写不敏感方式进行排序
ORDER:指明排序的顺序。有如下几种值可选:
ASCENDING:按照升序排列,为默认值
DESCENDING:按照降序排
11、编译宏
在CmakeLists.txt中可以定义一些宏名,而不是在源文件或头文件中定义宏来使得某些代码是否生效
add_definations(-D宏名称)
12、嵌套的Cmake
12.1 一些原则
- 根节点
CmakeLists.txt
中变量全局有效 - 父节点
CmakeLists.txt
中变量可以在子节点中使用 - 子节点
CmakeLists.txt
中变量只能在当前子节点中使用
12.2 添加子目录
我们还需要知道在 CMake 中父子节点之间的关系是如何建立的,这里需要用到一个 CMake 命令:
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
12.3 解决问题
12.3.1 根目录
cmake_minimum_required(VERSION 3.0)
project(test)
# 定义变量
# 静态库生成的路径
set(LIB_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib)
# 测试程序生成的路径
set(EXEC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin)
# 头文件目录
set(HEAD_PATH ${CMAKE_CURRENT_SOURCE_DIR}/include)
# 静态库的名字
set(CALC_LIB calc)
set(SORT_LIB sort)
# 可执行程序的名字
set(APP_NAME_1 test1)
set(APP_NAME_2 test2)
# 添加子目录
add_subdirectory(calc)
add_subdirectory(sort)
add_subdirectory(test1)
add_subdirectory(test2)
12.3.2 calc目录
cmake_minimum_required(VERSION 3.0)
project(CALCLIB)
aux_source_directory(./ SRC)
include_directories(${HEAD_PATH})
set(LIBRARY_OUTPUT_PATH ${LIB_PATH})
add_library(${CALC_LIB} STATIC ${SRC})
12.3.4 test
cmake_minimum_required(VERSION 3.0)
project(CALCTEST)
aux_source_directory(./ SRC)
include_directories(${HEAD_PATH})
link_directories(${LIBPATH})
link_libraries(${CALC_LIB})
set(EXECUTABLE_OUTPUT_PATH ${EXEC_PATH})
add_executable(${APP_NAME_1} ${SRC})
13 库中链接库
13.1 库中链接静态库
在库中链接静态库和可执行文件中链接静态库无异
13.2 库中链接动态库
在库中链接动态库和可执行文件中链接动态库无异
附录
宏 | 功能 |
---|---|
PROJECT_SOURCE_DIR | CMakeLists.txt所在路径 |
CMAKE_CURRENT_SOURCE_DIR | CMakeLists.txt所在路径 |
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目录进行的构建,那么得到的就是这个目录的路径
文章评论