CMake
构建可执行文件
一、CMakeLists.txt
命令编写
CMakeLists.txt
必须添加的三个命令
cmake_minimum_required
: 指定使用的CMake
的最低版本(选填)。
project
: 定义工程名称(必填),指定工程版本、工程描述、web主页地址、支持语言(默认支持所有语言)。
xml
# PROJECT 指令语法:
project(<PROJECT-NAME> [<language-name>...])
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[DESCRIPTION <project-description-string>]
[HOMEPAGE_URL <url-string>]
[LANGUAGES <language-name>...])
add_executable
: 命名可执行程序及使用的源文件,与project
中的项目名无关联。
csharp
# 样式1
add_executable(app add.c div.c main.c mult.c sub.c)
# 样式2
add_executable(app add.c;div.c;main.c;mult.c;sub.c)
常用操作
- 搜索源文件
bash
# 方法1:搜索某路径下的所有源文件
aux_source_directory(< dir > < variable >)
# 方法2:按条件搜索文件,按文件名生成列表存储到自定义的变量中
file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)
# --GLOB 搜索指定目录
# --GLOB_RECURSE 递归搜索指定目录,包括子目录
# 用例:
file(GLOB MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
file(GLOB MAIN_HEAD ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
# CMAKE_CURRENT_SOURCE_DIR宏表示当前访问的CMakeLists.txt文件所在的路径。
- 包含头文件
bash
include_directories(${PROJECT_SOURCE_DIR}/include)
- 自定义宏
scss
add_definitions(-D宏名称) # 通过自定义宏来控制程序中的某些代码
- 定义变量命令
set
命令:存储文件名对应的字符串
css
# set语法
set(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
# VAR: 变量名,VALUE: 变量值,[]中的内容为可选参数。
# 使用格式为 ${VAR}
# 用例:
set(SRC_LIST add.c div.c main.c mult.c sub.c)
add_executable(app ${SRC_LIST})
- 使用
set
设置C++程序版本标准:
ini
# 方法1:在CMakeLists.txt中设置-std=c++11
set(CMAKE_CXX_STANDARD 11)
# 方法2:在cmake命令中设置
cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=17
- 使用
set
指定可执行程序的输出路径:
bash
set(HOME /home/robin/Linux/Sort) # 应使用绝对路径
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin) # 该路径下的子目录不存在将自动创建
变量操作
- 使用set命令拼接字符串
bash
set(变量名 ${子变量} 常量字符串 "Hello world" ...) # 子变量内存储字符串
- 使用list命令
xml
# 追加字符串
list(APPEND 变量名 ${子变量1} ${子变量2} ...)
# 删除list中某字符串
list(REMOVE_ITEM <listname> ${子变量1} ...)
# 获取list中的指定索引的变量元素
list(GET <listname> <index>)
# 查找列表指定元素,存在返回索引号,不存在返回-1
list(FIND <list> <value> <output variable>)
# 指定索引位置插入元素
list(INSERT <list> <element_index> <element> [<element> ...])
# 列表排序
list (SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])
CMake
日志输出
css
message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)
- (无) :重要消息
- STATUS :非重要消息
- WARNING:警告代码或配置问题,影响构建过程的错误,会继续执行
- AUTHOR_WARNING:警告,用来提供建议信息,会继续执行
- SEND_ERROR:错误,继续执行,但是会跳过生成的步骤
- FATAL_ERROR:错误,终止所有处理过程
CMake
常用预定义宏
宏名 | 功能 |
---|---|
CMAKE_C_COMPILER |
指定 C 编译器的路径 |
CMAKE_CXX_COMPILER |
指定 C++ 编译器的路径 |
CMAKE_BUILD_TYPE |
指定构建类型(如 Debug 、Release 、RelWithDebInfo 、MinSizeRel ) |
CMAKE_INSTALL_PREFIX |
指定安装目录的前缀路径 |
CMAKE_SOURCE_DIR |
顶层 CMakeLists.txt 文件所在的路径或项目源代码的顶层目录 |
CMAKE_BINARY_DIR |
构建目录的路径或项目构建的顶层目录 |
CMAKE_CURRENT_SOURCE_DIR |
当前处理的 CMakeLists.txt 文件所在的路径或当前处理的源目录 |
CMAKE_CURRENT_BINARY_DIR |
当前处理的构建目录的路径或当前处理的构建目录 |
CMAKE_MODULE_PATH |
额外的模块查找路径或用于查找 CMake 模块的路径 |
CMAKE_INCLUDE_PATH |
查找头文件的路径 |
CMAKE_LIBRARY_PATH |
查找库文件的路径 |
CMAKE_PREFIX_PATH |
查找包的前缀路径或用于查找软件包的前缀路径 |
CMAKE_RUNTIME_OUTPUT_DIRECTORY |
指定所有目标运行时文件的输出目录 |
CMAKE_LIBRARY_OUTPUT_DIRECTORY |
指定所有目标库文件的输出目录 |
CMAKE_ARCHIVE_OUTPUT_DIRECTORY |
指定所有目标存档文件的输出目录 |
CMAKE_C_FLAGS |
为 C 编译器设置的编译选项或C 编译器的默认编译选项 |
CMAKE_CXX_FLAGS |
为 C++ 编译器设置的编译选项或C++ 编译器的默认编译选项 |
CMAKE_EXE_LINKER_FLAGS |
为生成可执行文件设置的链接选项或可执行文件链接的默认链接选项 |
CMAKE_SHARED_LINKER_FLAGS |
为生成共享库设置的链接选项或共享库链接的默认链接选项 |
CMAKE_MODULE_LINKER_FLAGS |
为生成模块库设置的链接选项或模块库链接的默认链接选项 |
CMAKE_POSITION_INDEPENDENT_CODE |
指定是否生成位置无关代码 (ON 或 OFF ) |
CMAKE_EXPORT_COMPILE_COMMANDS |
生成用于编译的 JSON 数据库 (compile_commands.json ) 文件 |
CMAKE_SYSTEM_NAME |
指定目标系统的名称或目标系统的名称 |
CMAKE_SYSTEM_VERSION |
指定目标系统的版本或目标系统版本 |
二、控制台执行CMake
命令
- 一般在
build
文件夹内,使用编写好的CMakeLists.txt
文件,在命令行中执行CMake
命令。
java
$ cmake (CMakeLists.txt文件所在路径)
- 生成了
Makefile
文件后,执行Make
命令。
三、CMakeList.txt
bash
# 目录结构:
~/root/***/yourprogram$ tree
.
├── build
├── CMakeLists.txt
├── include
│ └── *.h
└── src
├── *.cpp
bash
cmake_minimum_required(VERSION 3.15)
project(test)
set(CMAKE_CXX_STANDARD 11)
# 指定项目所需源文件
file(GLOB_RECURSE SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
# 包含头文件
include_directories(${PROJECT_SOURCE_DIR}/include)
# 指定可执行程序输出路径
set(EXECUTABLE_OUTPUT_PATH ${HOME}/***/***)
# 命名程序,添加其使用的源文件
add_excutable(test ${SRC})
CMake
制作动态库和静态库
动态库 | 静态库 | |
---|---|---|
Linux | libname.so | libname.a |
Windows | name.dll | name.lib |
一、制作命令:
scss
# 制作静态库:
add_library(静态库名称 STATIC 源文件...)
# 制作动态库:
add_library(静态库名称 SHARED 源文件...)
制作静态库CMakeLists.txt
文件的编写逻辑,与制作源文件相同,只需将add_excutable()
命令替换成add_library()
命令既可。
在Linux中,库名字分为三部分:lib+库名字+库后缀 ,此处只需要指定出库的名字就可以了,另外两部分在生成该文件的时候会自动填充;在Windows中虽然库名和Linux格式不同,但也只需指定出名字即可。
二、指定生成库文件的路径:
bash
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# 不指定路径则生成到当前构建目录中
三、完整CMakeLists.txt
文件
scss
cmake_minimum_required(VERSION 3.15)
project(mylib)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
# 设置动态库/静态库生成路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# 生成动态库
add_library(calc SHARED ${SRC_LIST})
# 生成静态库
add_library(calc STATIC ${SRC_LIST})
在程序中链接动态库和静态库
将目标(可执行文件或库)链接静态库或动态库,链接库之前必须生成可执行文件。
vbnet
target_link_libraries(
<target>
<PRIVATE|PUBLIC|INTERFACE> <item>... [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
# target:链接库的目标,目标可以是可执行文件、源文件或库。
# PRIVATE|PUBLIC|INTERFACE:库访问权限,用于控制库的可见性和传播性。
# item:使用的库名称
- 库链接权限参数说明:
关键字 | 作用范围 | 用途 |
---|---|---|
PRIVATE |
当前目标内部使用,依赖目标不继承 | 当库或选项仅在当前目标内部使用时使用 |
PUBLIC |
当前目标和所有依赖目标可见和使用 | 当库或选项需要传播到所有依赖目标时使用 |
INTERFACE |
当前目标可使用和传递,但不包括实现细节 | 当库或选项仅为传播用途时使用 |
链接多个库用例:
scss
# 生成静态/动态库
add_library(mylibrary STATIC/SHARED mylibrary.cpp)
# 设置链接库目录
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
# 生成可执行文件
add_executable(my_executable main.cpp)
# 链接动态库到可执行文件
target_link_libraries(my_executable PRIVATE mylibrary)
指定链接库文件的目录:
bash
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
嵌套CMake
分层构建项目
为树状项目在CMake
中建立父子关系:
ini
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
# source_dir:指定CMakeLists.txt源文件及代码路径,即指定子目录
# binary_dir:指定输出文件路径,可忽略
# EXCLUDE_FROM_ALL:指定source_dir子目录是否被排除默认构建之外,不填写该参数则子目录参与构建