C++网络编程入门学习(五)-- CMake 学习笔记
CMake 学习笔记
- C++网络编程入门学习(五)-- CMake 学习笔记
- 注释
- 基本用法
- set的使用
- 定义变量
- 设置编译选项
- 指定输出路径
- 搜索文件
- aux_source_directory 命令
- file 命令
- 指定头文件路径
- 制作静态库和动态库
- 制作静态库
- 制作动态库
- 链接静态库与动态库
- 链接静态库
- 链接动态库
- target_link_libraries 和 link_libraries 区别
- 打印日志信息
- list 方法
- 宏的自定义
- 常见的预定义宏
- 嵌套的cmake
C++网络编程入门学习(五)-- CMake 学习笔记
CMake(Cross-platform Make)是一个跨平台的元构建系统,用于生成各种编译环境所需的构建文件(如 Makefile、Visual Studio 项目文件等)。它的核心作用是:
- 抽象底层编译细节:通过统一的 CMakeLists.txt 配置文件,支持不同平台和编译器。
- 简化项目构建流程:自动处理依赖关系、头文件路径、库链接等复杂任务。
- 支持大规模项目:通过目录嵌套和模块化设计,管理复杂项目结构。
如果自己动手写 makefile,会发现,makefile 通常依赖于当前的编译平台,而且编写 makefile 的工作量比较大,解决依赖关系时也容易出错。
cmake允许开发者指定整个工程的编译流程,在根据编译平台,自动生成本地化的Makefile和工程文件,最后用户只需make编译即可,所以可以把CMake看成一款自动生成 Makefile的工具。
注释
-
注释行
使用
#
符号,从#
到行尾的内容都会被忽略。# 设置项目名称和版本 project(MyProject VERSION 1.0)# 添加可执行文件 add_executable(myapp main.cpp) # 这是行尾注释
-
块注释
使用
#[[ ... ]]
包裹多行内容,适合临时注释大段代码。#[[ 这是一个块注释 可以包含多行内容 常用于临时禁用代码 add_library(old_lib src/old_code.cpp) target_link_libraries(myapp old_lib) ]]
基本用法
对于如下文件
$ tree
.
├── add.c
├── div.c
├── head.h
├── main.c
├── mult.c
└── sub.c
CMakeLists.txt
文件可以按照如下写法:
cmake_minimum_required(VERSION 3.0)project(test)add_executable(app add.c div.c main.c mult.c sub.c)
其中:
-
cmake_minimum_required
:指定cmake的最低版本(可选,非必须,如果不加可能会有警告) -
project
:定义工程名称,并可指定工程的版本、工程描述、web主页地址、支持的语言(默认情况支持所有语言),如果不需要这些都是可以忽略的,只需要指定出工程名字即可。# 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
:定义工程会生成一个可执行程序add_executable(可执行程序名 源文件名称)
这里的可执行程序名和
project
中的项目名没有任何关系源文件名可以是一个也可以是多个,如有多个可用空格或
;
间隔# 样式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)
set的使用
定义变量
在上面的例子中一共提供了5个源文件,假设这五个源文件需要反复被使用,每次都直接将它们的名字写出来确实是很麻烦,此时我们就需要定义一个变量,将文件名对应的字符串存储起来,在cmake里定义变量需要使用set
。
set(变量名 值 [CACHE 类型 描述 [FORCE]])
set(变量名 值1 值2 ...) # 定义列表变量
# 方式1: 各个源文件之间使用空格间隔
# set(SRC_LIST add.c div.c main.c mult.c sub.c)# 方式2: 各个源文件之间使用分号 ; 间隔
set(SRC_LIST add.c;div.c;main.c;mult.c;sub.c)
add_executable(app ${SRC_LIST})set(SOURCE_FILESsrc/main.cppsrc/module1.cppsrc/module2.cpp
)
add_executable(myapp ${SOURCE_FILES})
设置编译选项
在编写C++程序的时候,可能会用到C++11、C++14等新特性,那么就需要在编译的时候在编译命令中制定出要使用哪个标准:
$ g++ *.cpp -std=c++11 -o app
上面的例子中通过参数-std=c++11指定出要使用c++11标准编译程序,C++标准对应有一宏叫做DCMAKE_CXX_STANDARD。在CMake中想要指定C++标准有两种方式:
-
在CMakeLists.txt文件中通过set命令指定
#增加-std=c++11 set(CMAKE_CXX_STANDARD 11) #增加-std=c++14 set(CMAKE_CXX_STANDARD 14) #增加-std=c++17 set(CMAKE_CXX_STANDARD 17)
-
在执行cmake命令通过宏进行指定
#增加-std=c++11 cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=11 #增加-std=c++14 cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=14 #增加-std=c++17 cmake CMakeLists.txt文件路径 -DCMAKE_CXX_STANDARD=17
其他编译选项举例
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
指定输出路径
在CMake中指定可执行程序输出的路径,也对应一个宏,叫做EXECUTABLE_OUTPUT_PATH
,它的值还是通过set命令进行设置:
set(HOME /home/robin/Linux/Sort)
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin)
- 第一行:定义一个变量用于存储一个绝对路径
- 第二行:将拼接好的路径值设置给
EXECUTABLE_OUTPUT_PATH
宏(如果这个路径中的子目录不存在,会自动生成,无需自己手动创建)
由于可执行程序是基于 cmake 命令生成的 makefile 文件然后再执行 make 命令得到的,所以如果此处指定可执行程序生成路径的时候使用的是相对路径 ./xxx/xxx,那么这个路径中的 ./ 对应的就是 makefile 文件所在的那个目录。
学习完set之后,之前的的CMakeLists.txt文件可以按照如下方式的写法
cmake_minimum_required(VERSION 3.15)project(test)# add_executable(app add.cpp div.cpp mult.cpp main.cpp sub.cpp)set(SRC add.cpp div.cpp mult.cpp main.cpp sub.cpp)set(CMAKE_CXX_STANDARD 11)add_executable(app ${SRC})
搜索文件
如果一个项目里边的源文件很多,在编写CMakeLists.txt文件的时候不可能将项目目录的各个文件一一罗列出来,这样太麻烦也不现实。所以,在CMake中为我们提供了搜索文件的命令,可以使用aux_source_directory
命令或者file
命令。
aux_source_directory 命令
在 CMake 中使用aux_source_directory
命令可以查找某个路径下的所有源文件,命令格式为:
aux_source_directory(<dir> <variable>)
dir
:要搜索的目录variable
:将从dir目录下搜索到的源文件列表存储到该变量中
cmake_minimum_required(VERSION 3.0)
project(CALC)
include_directories(${PROJECT_SOURCE_DIR}/include)
# 搜索 src 目录下的源文件
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LIST)
add_executable(app ${SRC_LIST})
file 命令
如果一个项目里边的源文件很多,在编写CMakeLists.txt文件的时候不可能将项目目录的各个文件一一罗列出来,这样太麻烦了。所以,在CMake中为我们提供了搜索文件的命令,他就是file
(当然,除了搜索以外通过 file 还可以做其他事情)。
基本语法如下:
# 收集当前目录下所有.cpp文件
file(GLOB SOURCES "*.cpp")# 递归收集src目录下所有.h和.cpp文件
file(GLOB_RECURSE ALL_SOURCES "src/*.cpp" "src/*.h")# 排除测试文件
file(GLOB TEST_SOURCES "tests/*_test.cpp")
list(REMOVE_ITEM ALL_SOURCES ${TEST_SOURCES})
文件操作:
# 创建目录
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/output)# 复制文件/目录(支持通配符)
file(COPY src/data DESTINATION ${CMAKE_BINARY_DIR})
file(COPY src/*.txt DESTINATION ${CMAKE_BINARY_DIR}/data)# 删除文件/目录
file(REMOVE ${CMAKE_BINARY_DIR}/temp.txt)
file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/old_data)# 重命名文件
file(RENAME ${CMAKE_BINARY_DIR}/old_name.txt ${CMAKE_BINARY_DIR}/new_name.txt)
文件读写
# 读取文件内容到变量
file(READ "config.txt" CONFIG_CONTENTS)# 写入文件(覆盖已有内容)
file(WRITE "output.txt" "Hello, CMake!\n")# 追加内容
file(APPEND "output.txt" "This is additional content.\n")# 写入二进制数据
file(WRITE "binary.bin" ${BINARY_DATA} HEX)
文件路径与属性查询
# 获取文件绝对路径
file(REAL_PATH "relative/path" ABSOLUTE_PATH)# 查询文件属性
file(SIZE "file.txt" FILE_SIZE)
file(TIMESTAMP "file.txt" MODIFY_TIME)# 获取可执行文件依赖的动态库(需CMake 3.24+)
file(GET_RUNTIME_DEPENDENCIESEXECUTABLES myappRESOLVED_DEPENDENCIES_VAR resolved_depsUNRESOLVED_DEPENDENCIES_VAR unresolved_deps
)
指定头文件路径
在编译项目源文件的时候,很多时候都需要将源文件对应的头文件路径指定出来,这样才能保证在编译过程中编译器能够找到这些头文件,并顺利通过编译。在CMake中设置要包含的目录也很简单,通过一个命令就可以搞定了,他就是include_directories
:
include_directories(headpath)
举例说明,有源文件若干,其目录结构如下:
$ tree
.
├── build
├── CMakeLists.txt
├── include
│ └── head.h
└── src├── add.cpp├── div.cpp├── main.cpp├── mult.cpp└── sub.cpp
CMakeLists.txt文件内容如下:
cmake_minimum_required(VERSION 3.15)project(test)# add_executable(app add.cpp div.cpp mult.cpp main.cpp sub.cpp)# set(SRC add.cpp div.cpp mult.cpp main.cpp sub.cpp)aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)include_directories(${PROJECT_SOURCE_DIR}/include)set(CMAKE_CXX_STANDARD 11)add_executable(app ${SRC})
制作静态库和动态库
有些时候我们编写的源代码并不需要将他们编译生成可执行程序,而是生成一些静态库或动态库提供给第三方使用。
制作静态库
在cmake中,制作静态库使用的命令如下:
add_library(target_name STATIC source1.cpp source2.cpp ...)
在linux中,静态库名字分为三部分:lib
+target_name
+.a
,此处,我们只需要指出库的名字就可以了,另外两部分在生成该文件的时候会自动填充(Windows中同样如此)。
例如,下面目录结构文件:
.
├── build
├── CMakeLists.txt
├── include # 头文件目录
│ └── head.h
├── main.cpp # 用于测试的源文件
└── src # 源文件目录├── add.cpp├── div.cpp├── mult.cpp└── sub.cpp
我们可以编写如下CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.0)project(CALC)include_directories(${PROJECT_SOURCE_DIR}/include)file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")add_library(calc STATIC ${SRC_LIST})
这样最终就会生成对应的静态库文件libcalc.a
。
制作动态库
在cmake中,如果要制作动态库,需要使用的命令如下:
add_library(target_name SHARED 源文件1 [源文件2] ...)
在linux中,静态库名字分为三部分:lib
+target_name
+.so
,此处,我们只需要指出库的名字就可以了,另外两部分在生成该文件的时候会自动填充(Windows中同样如此)。
指定输出路径
-
适用于动态库
对于生成的库文件来说和可执行程序一样都可以指定输出路径。由于在Linux下生成的动态库默认是有执行权限的,所以可以按照生成可执行程序的方式去指定它生成的目录:
cmake_minimum_required(VERSION 3.0) project(CALC) include_directories(${PROJECT_SOURCE_DIR}/include) file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") # 设置动态库生成路径 set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) add_library(calc SHARED ${SRC_LIST})
对于这种方式来说,其实就是通过set命令给
EXECUTABLE_OUTPUT_PATH
宏设置了一个路径,这个路径就是可执行文件生成的路径。 -
都适用
由于在Linux下生成的静态库默认不具有可执行权限,所以在指定静态库生成的路径的时候就不能使用
EXECUTABLE_OUTPUT_PATH
宏了,而应该使用LIBRARY_OUTPUT_PATH
,这个宏对应静态库文件和动态库文件都适用。cmake_minimum_required(VERSION 3.0) project(CALC) 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})
链接静态库与动态库
在编写程序的过程中,可能会用到一些系统提供的动态库或者自己制作出的动态库或者静态库文件,cmake中也为我们提供了相关的加载库的命令。
假设项目有如下目录结构:
$ tree
.
├── build
├── CMakeLists.txt
├── include
│ └── head.h
├── lib
│ └── libcalc.a # 制作出的静态库的名字
└── src└── main.cpp
链接静态库
在cmake中,链接静态库的命令如下:
link_libraries([lib1 [lib2 [...]]])# 例如:
# 链接多个库
link_libraries(pthread m dl)# 链接绝对路径库
link_libraries(/usr/local/lib/libboost_system.a)# 混合链接
link_libraries(${CMAKE_SOURCE_DIR}/libs/math.lib${CMAKE_BINARY_DIR}/generated/libutils.apthread
)
- 参数1:指定出要链接的静态库的名字
- 可以是全名
libxxx.a
- 也可以是掐头(
lib
)去尾(.a
)之后的名字xxx
- 可以是全名
- 参数2-N:要链接的其它静态库的名字
如果该静态库不是系统提供的(自己制作或者使用第三方提供的静态库)可能出现静态库找不到的情况,此时可以将静态库的路径也指定出来:
link_directories(<lib path>)
这样,修改之后的CMakeLists.txt文件内容如下:
cmake_minimum_required(VERSION 3.0)project(CALC)
# 搜索指定目录下源文件
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
# 包含头文件路径
include_directories(${PROJECT_SOURCE_DIR}/include)
# 包含静态库路径
link_directories(${PROJECT_SOURCE_DIR}/lib)
# 链接静态库
link_libraries(calc)add_executable(app ${SRC_LIST})
链接动态库
在cmake中链接动态库的命令如下:
target_link_libraries(<target><PRIVATE|PUBLIC|INTERFACE> <item>...[<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
PRIVATE
:仅链接到目标本身PUBLIC
:链接到目标及其使用者INTERFACE
:仅链接到使用者
如果各个动态库之间没有依赖关系,无需做任何设置,三者没有没有区别,一般无需指定,使用默认的 PUBLIC 即可。
动态库的链接具有传递性,如果动态库 A 链接了动态库B、C,动态库D链接了动态库A,此时动态库D相当于也链接了动态库B、C,并可以使用动态库B、C中定义的方法。
动态库的链接和静态库是完全不同的:
-
静态库会在生成可执行程序的链接阶段被打包到可执行程序中,所以可执行程序启动,静态库就被加载到内存中了。
-
动态库在生成可执行程序的链接阶段不会被打包到可执行程序中,当可执行程序被启动并且调用了动态库中的函数的时候,动态库才会被加载到内存
因此,在cmake中指定要链接的动态库的时候,应该将命令写到生成了可执行文件之后,例如:
cmake_minimum_required(VERSION 3.0)
project(TEST)
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
# 添加并指定最终生成的可执行程序名
add_executable(app ${SRC_LIST})
# 指定可执行程序要链接的动态库名字
target_link_libraries(app pthread)
那么,如何链接自己做的一个动态库呢,假设有如下目录结构:
$ tree
.
├── build
├── CMakeLists.txt
├── include
│ └── head.h # 动态库对应的头文件
├── lib
│ └── libcalc.so # 自己制作的动态库文件
└── main.cpp # 测试用的源文件3 directories, 4 files
假设在测试文件main.cpp中既使用了自己制作的动态库libcalc.so又使用了系统提供的线程库,此时CMakeLists.txt文件可以这样写:
cmake_minimum_required(VERSION 3.0)
project(TEST)
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
# 指定源文件或者动态库对应的头文件路径
include_directories(${PROJECT_SOURCE_DIR}/include)
# 指定要链接的动态库的路径
link_directories(${PROJECT_SOURCE_DIR}/lib)
# 添加并生成一个可执行程序
add_executable(app ${SRC_LIST})
# 指定要链接的动态库
target_link_libraries(app pthread calc)
通过
link_directories
指定了动态库的路径之后,在执行生成的可执行程序的时候,就不会出现找不到动态库的问题了。
target_link_libraries 和 link_libraries 区别
target_link_libraries
和 link_libraries
是 CMake 中用于链接库的两个命令,都可以用于链接动态库和静态库,但它们的使用场景和功能有所不同。下面是关于二者的总结:
target_link_libraries
用于指定一个目标(如可执行文件或库)在编译时需要链接哪些库。它支持指定库的名称、路径以及链接库的顺序。link_libraries
用于设置全局链接库,这些库会链接到之后定义的所有目标上。它会影响所有的目标,适用于全局设置,但不如target_link_libraries
精确。
打印日志信息
message
是CMake中最基础且最常用的命令之一,用于在构建过程中输出信息。它在调试、状态报告和用户交互中扮演着关键角色。
基本语法:
message([<mode>] "message text" ...)
模式 | 说明 | 示例 |
---|---|---|
(无) | 普通信息(默认) | message("Building project") |
STATUS | 项目状态信息(前缀"–") | message(STATUS "Configuring...") |
WARNING | CMake警告(黄色文本,不中断构建) | message(WARNING "Deprecated feature") |
AUTHOR_WARNING | 开发者警告(仅在开发者模式下显示) | message(AUTHOR_WARNING "TODO: Fix this") |
SEND_ERROR | 发送错误(红色文本,继续处理但跳过生成) | message(SEND_ERROR "Invalid path") |
FATAL_ERROR | 致命错误(红色文本,立即终止处理) | message(FATAL_ERROR "Required lib missing") |
DEPRECATION | 弃用警告(根据策略设置显示) | message(DEPRECATION "Old syntax") |
VERBOSE | 详细输出(仅当设置CMAKE_MESSAGE_VERBOSE 时显示) | message(VERBOSE "Internal variable: ${VAR}") |
DEBUG | 调试信息(仅当设置CMAKE_MESSAGE_LOG_LEVEL=DEBUG 时显示) | message(DEBUG "Function entered") |
TRACE | 追踪信息(更详细的调试) | message(TRACE "Variable scope changed") |
list 方法
一、基本语法与功能
list
命令用于操作列表变量,CMake 中列表以分号 ;
分隔元素。基本语法:
list(操作 列表变量 [参数...])
常见操作:
APPEND
:添加元素REMOVE_ITEM
:移除元素LENGTH
:获取长度GET
:获取指定位置元素SORT
:排序FILTER
:过滤元素
二、核心操作示例
1. 创建与添加元素
set(MY_LIST a b c) # 创建列表
list(APPEND MY_LIST d e) # 添加元素 → a;b;c;d;e
list(APPEND MY_LIST "f;g") # 添加包含分号的元素 → a;b;c;d;e;f;g
2. 访问与修改
list(LENGTH MY_LIST len) # 获取长度 → len=5
list(GET MY_LIST 0 first) # 获取第1个元素 → first=a
list(GET MY_LIST -1 last) # 获取最后1个元素 → last=elist(INSERT MY_LIST 2 x) # 在位置2插入x → a;b;x;c;d;e
list(REMOVE_ITEM MY_LIST b) # 移除元素b → a;x;c;d;e
list(REMOVE_AT MY_LIST 0) # 移除位置0的元素 → x;c;d;e
3. 排序与反转
list(SORT MY_LIST) # 排序 → c;d;e;x
list(REVERSE MY_LIST) # 反转 → x;e;d;c
4. 查找与过滤
list(FIND MY_LIST d index) # 查找d的位置 → index=2(从0开始)
list(FILTER MY_LIST INCLUDE REGEX "^[cd]") # 保留c或d开头的元素 → c;d
list(FILTER MY_LIST EXCLUDE REGEX "_test$") # 排除_test结尾的元素
5. 子列表操作
list(SUBLIST MY_LIST 1 3) # 获取子列表(从位置1开始,取3个元素)→ d;e;x
三、高级用法
1. 列表去重
list(REMOVE_DUPLICATES MY_LIST)
2. 条件处理列表
foreach(item IN LISTS MY_LIST)if(item MATCHES "^[abc]")list(APPEND FILTERED_LIST ${item})endif()
endforeach()
3. 与文件操作结合
file(GLOB SOURCES "src/*.cpp") # 收集源文件
list(FILTER SOURCES EXCLUDE REGEX ".*test.cpp$") # 排除测试文件
add_executable(myapp ${SOURCES})
宏的自定义
在进行程序测试的时候,我们可以在代码中添加一些宏定义,通过这些宏来控制这些代码是否生效,如下所示:
#include <stdio.h>
#define NUMBER 3int main()
{int a = 10;
#ifdef DEBUGprintf("我是一个程序猿, 我不会爬树...\n");
#endiffor(int i = 0; i < NUMBER; ++i){printf("hello, word!!!\n");}return 0;
}
在程序的第七行对DEBUG宏进行了判断,如果该宏被定义了,那么第八行就会进行日志输出,如果没有定义这个宏,第八行就相当于被注释掉了,因此最终无法看到日志输入出(上述代码中并没有定义这个宏)。
为了让测试更灵活,我们可以不在代码中定义这个宏,而是在测试的时候去把它定义出来,其中一种方式就是在gcc/g++命令中去指定,如下:
gcc test.c -DDEBUG -o app
在gcc/g++命令中通过参数 -D指定出要定义的宏的名字,这样就相当于在代码中定义了一个宏,其名字为DEBUG。
在CMake中我们也可以做类似的事情,对应的命令叫做add_definitions
:
add_definitions(-D宏名称)
例如:
cmake_minimum_required(VERSION 3.0)
project(TEST)
# 自定义 DEBUG 宏
add_definitions(-DDEBUG)
add_executable(app ./test.cpp)
常见的预定义宏
宏名称 | 功能描述 |
---|---|
PROJECT_SOURCE_DIR | 使用cmake命令后紧跟的目录,一般是工程的根目录 |
PROJECT_BINARY_DIR | 执行cmake命令的目录 |
CMAKE_CURRENT_SOURCE_DIR | 当前的CMakeLists.txt所在的路径 |
CMAKE_CURRENT_BINARY_DIR | target 编译目录 |
EXECUTABLE_OUTPUT_PATH | 重新定义目标二进制可执行文件的存放位置 |
PROJECT_NAME | 返回通过PROJECT指令定义的项目名称 |
CMAKE_BINARY_DIR | 项目实际构建路径,假设在build目录进行的构建,那么得到的就是这个目录的路径 |
CMAKE_CXX_FLAGS_<CONFIG> | 针对特定构建类型(如DEBUG /RELEASE )的C++编译器标志。 |
CMAKE_C_FLAGS_<CONFIG> | 针对特定构建类型的C编译器标志。 |
CMAKE_VERBOSE_MAKEFILE | 控制Makefile是否输出详细编译命令(用于调试)。 |
CMAKE_COLOR_MAKEFILE | 控制Makefile是否使用彩色输出。 |
CMAKE_SKIP_INSTALL_RULES | 跳过生成安装规则(适用于子项目)。 |
CMAKE_DISABLE_TESTING | 禁用测试目标的生成。 |
嵌套的cmake
https://subingwen.cn/cmake/CMake-advanced/#1-%E5%B5%8C%E5%A5%97%E7%9A%84CMake