CMake 的一个简单案例释义
案例
# CMakeLists.txt
cmake_minimum_required(VERSION 3.25)
project(main)
set(CMAKE_MAKE_PROGRAM "/usr/bin/make")
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED True)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/target/libs)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/target/libs)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/target)
set(BUILD_SHARED_LIBS ON)
set(SRC_LIST main.c)
add_library(sorting "libs/sorting.c")
add_library(utils "libs/utils.c")
add_library("string" "libs/string.c")
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries("string" PUBLIC sorting utils)
target_link_libraries(${PROJECT_NAME} PUBLIC sorting utils "string")
-
cmake_minimum_required(VERSION 3.25)。表示要求 CMake 程序的版本最低为3.25,并设置CMAKE_MINIMUM_REQUIRED_VERSION的值为3.25。参见 cmake-minimum-required。[!note] 注意
CMake 文档建议在项目最顶级的CMakeLists.txt文件 (因为这个文件是可以在子目录中再次配置的) 的最前面使用这个命令。并且建议要比project命令 (见下) 要更早使用,且不要在某个function()中调用此命令。 -
project(main)。表示当前项目的名字。这个命令会设置当前CMakeLists.txt文件所在范围内的PROJECT_NAME变量。如果在顶级CMakeLists.txt文件中使用,还会同时设置CMAKE_PROJECT_NAME变量。其他一些用法比如设置项目描述信息、版本号等,参阅 project。 -
set(CMAKE_MAKE_PROGRAM "/usr/bin/make")。首先set命令用于手动设定一个变量的值,当需要将某个变量的值设置为空字符串时,可以使用set(<variable> "")这样的写法。参见 set如果想要彻底清除一个变量,则需要使用
unset(<variable>)命令,参见 unset其次,
CMAKE_MAKE_PROGRAM表示需要在后续构建过程中使用的二进制程序名 (如果已经在PATH环境变量中存在,就只需要二进制程序名,比如make) 或者完整路径,比如/usr/bin/make。参见 CMAKE_MAKE_PROGRAM。 -
set(CMAKE_C_STANDARD 11)。表示将构建时使用的 C 语言标准设置为C11。这个变量的值是添加构建目标 (target) 时对应C_STANDARD属性的默认值。参见 CMAKE_C_STANDARD。 -
set(CMAKE_C_STANDARD_REQUIRED True)。表示添加构建目标时需要设定C_STANDARD属性,它常常与上一条的变量配合使用。参见 CMAKE_C_STANDARD_REQUIRED。 -
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/target/libs)。CMAKE_ARCHIVE_OUTPUT_DIRECTORY变量用于设定库构建目标的输出内容存放的位置,这里使用${CMAKE_BINARY_DIR}/target/libs表示在项目根目录创建一个target/libs的目录结构,用于存放相关构建产物。关于它与后面两项的区别,参见后文辨析CMAKE_LIBRARY_OUTPUT_DIRECTORY、CMAKE_RUNTIME_OUTPUT_DIRECTORY和CMAKE_ARCHIVE_OUTPUT_DIRECTORY的部分。 -
set(BUILD_SHARED_LIBS ON)。用于修改add_library()命令的默认行为。默认情况下此命令会构建静态库,但是启用了这个变量后,默认会构建共享库。 -
set(SRC_LIST main.c)。使用一个变量来代表源文件列表。这对于有多源文件复用或源文件很多的情况帮助较大。 -
add_library(sorting "libs/sorting.c")等。定义一个名为sorting的链接库。由于此前通过BUILD_SHARED_LIBS开启了默认共享库构建,所以产物都是动态链接库。比如在 Windows 上,产物的名字是cygsorting.dll。 -
add_executable(${PROJECT_NAME} ${SRC_LIST})。这行命令的目的是定义程序的可执行文件生成目标。我们用项目名字 (早前使用project()命令定义的名字) 为这个文件取名,然后通过变量SRC_LIST表名需要使用的源文件清单。注意使用变量时需要使用${}标记,这是与定义时不同的。 -
target_link_libraries("string" PUBLIC sorting utils)。为某个构建目标指定依赖项。比如我们的string库依赖sorting和utils,就需要这样定义。参见 target_link_libraries。
辨析
CMAKE_SOURCE_DIR 和 CMAKE_BINARY_DIR
默认情况下,这两个值是相同的,都是当前构建/树的顶级所在目录。如果没有使用 -S 和 -B 选项指定,也就是当采用了 in-source 模式,这两个值都是一样的。如果希望获取当前所在一级的构建树目录,应该使用 CMAKE_CURRENT_BINARY_DIR 变量;若是当前所在一级的源码树目录,则应该使用 CMAKE_CURRENT_SOURCE_DIR 变量。
参考:
CMAKE_LIBRARY_OUTPUT_DIRECTORY、CMAKE_RUNTIME_OUTPUT_DIRECTORY 和 CMAKE_ARCHIVE_OUTPUT_DIRECTORY
这三个变量都是用来设置顶级 (全局) 构建产物 (buildsystem artifact) 的输出或存放位置的。
最容易判断的就是 CMAKE_RUNTIME_OUTPUT_DIRECTORY,因为它一定是指构建产物中的 可执行文件 类型 (executable)。所谓可执行文件类型,具体分为两类:
- 常见的
.exe可执行文件。对应的产物由add_executable()命令来定义和产生; - 在 Windows 等 DLL 平台上,通过带有
SHARED参数的add_library()命令构建的所有共享库的可执行.dll产物[1]。
其次 CMAKE_LIBRARY_OUTPUT_DIRECTORY定义了 共享库 类型 (shared library) 构建产物的输出位置。共享库类型的产物可以通过以下方式定义:
- 通过带
MODULE参数的add_library()命令定义的所有可加载模块产物,如.so或.lib。 - 在 Linux、Unix、macOS 等非 DLL 平台上,通过带有
SHARED参数的add_library()命令构建的所有共享库的可执行.so或.dylib产物。
最后 CMAKE_LIBRARY_OUTPUT_DIRECTORY定义了 归档 类型 (archive) 构建产物的输出位置。归档类型的产物可以通过以下方式定义:
- 通过带
STATIC参数 (默认) 的add_library()命令定义的所有静态链接库 (static library) 产物,如.a或.lib。 - 在 DLL 平台: 使用了
SHARED选项的add_library()命令定义的那些可供链接器导入的共享库目标 (如.lib)。注意,只有当对应的库导出了至少一个非托管的符号 (unmanaged symbol) 时,才会生成对应的构建产物。 - 在 DLL 平台: 定义了
ENABLE_EXPORTS属性的add_executable()命令定义的那些可供链接器导入的文件 (比如.lib)。 - 在 AIX 平台[2]: 定义了
ENABLE_EXPORTS属性的add_executable()命令定义的那些可供链接器导入的文件 (比如.imp)。 - 在 macOS 平台,同时使用
SHARED选项和ENABLE_EXPORTS属性的add_library()命令定义的那些可供链接器导入的文件 (比如.tbd)。
参考:

读枯燥的文档,不如从简单案例开始,一步一步由生到熟。
浙公网安备 33010602011771号