CMake常用的30个命令详解

CMake常用的30个命令详解

1. 项目与环境设置

cmake_minimum_required

cmake_minimum_required 是 CMake 中的一个命令,用于指定项目所需的最低 CMake 版本。它通常位于 CMakeLists.txt 文件的开头部分。

语法

cmake_minimum_required(VERSION [...] [FATAL_ERROR])

VERSION :指定所需的最低 CMake 版本,格式为 major.minor[.patch[.tweak]]。[...](可选):可以指定一个最高版本,确保 CMake 版本不超过某个上限。FATAL_ERROR(可选):如果 CMake 版本低于要求,将产生致命错误并停止处理。

示例

cmake_minimum_required(VERSION 3.10)

表示该项目需要 CMake 3.10 或更高版本才能构建。

cmake_minimum_required(VERSION 3.10...3.15)

表示该项目需要 CMake 版本在 3.10 到 3.15 之间。

作用

版本兼容性检查:确保用户使用的 CMake 版本满足项目需求。策略设置:CMake 会根据指定的版本调整其行为(如策略设置),以确保向后兼容性。

注意事项

通常应放在 CMakeLists.txt 文件的最前面,在其他命令之前。如果不指定,CMake 可能会使用默认行为,但可能导致不可预期的结果。

project

project 是 CMake 中的一个命令,用于定义项目的基本信息,包括项目名称、版本、描述以及使用的编程语言等。它是 CMakeLists.txt 文件中的基本指令之一,通常在文件的开头部分使用。

语法

project(

[VERSION [.[.[.]]]]

[DESCRIPTION ]

[HOMEPAGE_URL ]

[LANGUAGES ...])

参数说明

:必填参数,指定项目的名称。VERSION:可选参数,指定项目的版本号,格式为 major.minor.patch.tweak。DESCRIPTION:可选参数,提供项目的简短描述。HOMEPAGE_URL:可选参数,指定项目的主页 URL。LANGUAGES:可选参数,指定项目使用的编程语言(如 C、CXX、Fortran 等)。如果未指定,CMake 会默认启用 C 和 CXX。

示例

project(MyProject

VERSION 1.0.0

DESCRIPTION "A simple CMake project"

HOMEPAGE_URL "https://example.com"

LANGUAGES C CXX)

作用

设置项目名称:CMake 会将该名称存储在变量 PROJECT_NAME 中。设置版本信息:版本信息会存储在变量 PROJECT_VERSION、PROJECT_VERSION_MAJOR 等中。启用语言支持:通过 LANGUAGES 参数指定项目使用的编程语言,CMake 会检查相应的编译器是否可用。定义相关变量:如 PROJECT_SOURCE_DIR(项目源码目录)、PROJECT_BINARY_DIR(项目构建目录)等。

注意事项

project 命令通常放在 CMakeLists.txt 文件的开头,但在 cmake_minimum_required 之后。如果未指定 LANGUAGES,CMake 会默认启用 C 和 CXX(C++)。如果项目中不需要某些语言,应明确指定以避免不必要的检查。

set

在CMake中,set命令用于定义或修改变量的值。变量可以存储字符串、列表或路径等信息,并在后续的CMake脚本中使用。set的基本语法如下:

set( [CACHE [FORCE]])

参数说明:

:要设置或修改的变量名。:分配给变量的值。可以是字符串、列表(以空格分隔的多个值)或路径。CACHE(可选):将变量存入CMake缓存(CMakeCache.txt),使其在多次配置时持久化。

:缓存变量的类型,如STRING、BOOL、FILEPATH等。:变量的描述信息。FORCE(可选):强制覆盖缓存中已存在的变量值。

示例:

设置普通变量:

set(MY_VAR "Hello, CMake!") # 定义变量MY_VAR

设置列表变量:

set(SOURCE_FILES main.cpp utils.cpp lib.cpp) # SOURCE_FILES为列表

设置缓存变量(持久化):

set(CMAKE_CXX_STANDARD 14 CACHE STRING "C++ standard version") # 设置C++标准为14

强制覆盖缓存变量:

set(ENABLE_TESTING ON CACHE BOOL "Enable tests" FORCE) # 强制开启测试选项

注意事项:

变量名区分大小写,通常约定全大写(如CMAKE_CXX_STANDARD)。未指定CACHE的变量默认为普通变量,作用域限于当前目录及子目录。通过CACHE定义的变量可在命令行或GUI工具(如ccmake)中修改。

message

message 是 CMake 中的一个命令,用于在构建过程中输出调试信息或错误提示。它可以帮助开发者在 CMake 配置或构建阶段打印相关信息,便于调试和跟踪问题。

语法

message([] "message text" ...)

参数说明

:可选参数,指定消息的类型,常见的模式包括:

STATUS:输出一般状态信息(通常以 -- 前缀显示)。WARNING:输出警告信息(黄色高亮)。AUTHOR_WARNING:输出作者警告(类似 WARNING,但可能被忽略)。SEND_ERROR:输出错误信息(红色高亮),但不会终止配置过程。FATAL_ERROR:输出致命错误信息(红色高亮),并终止配置过程。DEPRECATION:输出弃用警告(如果启用了 CMAKE_ERROR_DEPRECATED 或 CMAKE_WARN_DEPRECATED)。VERBOSE、DEBUG、TRACE:输出更详细的调试信息(需配合 CMake 日志级别使用)。

"message text":要输出的消息内容,可以是字符串或变量。

示例

输出普通信息:

message("This is a simple message.")

输出状态信息:

message(STATUS "This is a status message.")

输出警告信息:

message(WARNING "This is a warning message.")

输出错误信息并终止配置:

message(FATAL_ERROR "This is a fatal error message.")

结合变量输出:

set(MY_VAR "Hello, CMake!")

message("The value of MY_VAR is: ${MY_VAR}")

注意事项

如果不指定 ,默认输出普通信息。FATAL_ERROR 会立即终止 CMake 的配置过程。消息内容可以包含变量或表达式,CMake 会先解析再输出。

2. 文件与目录操作

add_subdirectory

add_subdirectory 是 CMake 中的一个命令,用于将指定的子目录添加到当前项目的构建系统中。这个命令通常用于模块化项目结构,允许将不同的功能模块或组件组织在不同的子目录中。

语法

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

参数说明

source_dir

指定包含 CMakeLists.txt 的子目录路径。路径可以是相对路径(相对于当前 CMakeLists.txt 文件)或绝对路径。

binary_dir(可选)

指定子目录的构建输出路径。如果未指定,CMake 默认使用 source_dir 的同名目录(在构建目录中)。

EXCLUDE_FROM_ALL(可选)

如果指定此选项,子目录中的目标(如可执行文件或库)默认不会包含在父目录的 ALL 目标中。这意味着这些目标不会在默认构建时被编译,除非显式指定。

功能

加载子目录的 CMakeLists.txt

CMake 会解析子目录中的 CMakeLists.txt 文件,并将其内容纳入当前项目的构建系统。

作用域隔离

子目录中的变量和选项通常不会影响父目录,除非显式传递(例如通过 set 或 PARENT_SCOPE)。

构建输出管理

通过 binary_dir 可以控制子目录的构建产物存放位置,便于组织复杂的项目结构。

示例

# 添加子目录 src,构建输出到 build/src

add_subdirectory(src)

# 添加子目录 tests,并排除默认构建

add_subdirectory(tests EXCLUDE_FROM_ALL)

注意事项

子目录必须包含有效的 CMakeLists.txt 文件,否则会报错。路径中的空格或特殊字符可能需要转义处理。多次调用 add_subdirectory 添加同一目录会导致重复定义错误。

aux_source_directory

aux_source_directory 是 CMake 中的一个命令,用于自动收集指定目录下的所有源文件。这个命令会扫描指定目录,并将所有符合条件的源文件(如 .c、.cpp 等)的路径存储到一个变量中,方便后续使用。

语法

aux_source_directory(

)

:要扫描的目录路径。:存储源文件列表的变量名。

示例

# 收集当前目录下的所有源文件,并存储到变量 SOURCES 中

aux_source_directory(. SOURCES)

# 使用收集到的源文件编译可执行文件

add_executable(my_app ${SOURCES})

注意事项

文件类型:aux_source_directory 默认会识别常见的源文件扩展名(如 .c、.cpp、.cc 等),但不会识别头文件(如 .h、.hpp)。递归扫描:该命令不会递归扫描子目录,仅扫描指定的目录。手动指定文件:对于复杂的项目,建议手动指定源文件,以避免意外包含不需要的文件。

适用场景

适用于小型项目或快速原型开发,可以简化源文件的收集。不推荐用于大型或复杂的项目,因为可能会包含不需要的文件。

file

file 是 CMake 中的一个命令,用于执行与文件相关的操作。它支持多种子命令,可以用于文件的复制、查找、读写等操作。以下是一些常用的 file 子命令:

1. COPY

用于复制文件或目录到指定位置。

file(COPY ... DESTINATION

)

:要复制的文件或目录列表。

:目标目录。

示例:

file(COPY myfile.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

2. GLOB

用于匹配指定模式的文件列表。

file(GLOB [LIST_DIRECTORIES ] [RELATIVE ] ...)

:存储匹配结果的变量。LIST_DIRECTORIES:是否包含目录(默认为 ON)。RELATIVE:返回相对路径。:匹配模式(如 *.cpp)。

示例:

file(GLOB SOURCES "src/*.cpp")

3. WRITE

用于将内容写入文件。

file(WRITE ...)

:目标文件名。:要写入的内容。

示例:

file(WRITE output.txt "Hello, CMake!")

4. READ

用于读取文件内容。

file(READ [OFFSET ] [LIMIT ])

:要读取的文件名。:存储内容的变量。OFFSET:读取的起始偏移量。LIMIT:读取的最大字节数。

示例:

file(READ input.txt CONTENT)

5. REMOVE 和 REMOVE_RECURSE

用于删除文件或目录。

file(REMOVE ...)

file(REMOVE_RECURSE ...)

REMOVE:删除文件。REMOVE_RECURSE:递归删除目录及其内容。

示例:

file(REMOVE oldfile.txt)

file(REMOVE_RECURSE olddir)

6. MAKE_DIRECTORY

用于创建目录。

file(MAKE_DIRECTORY ...)

:要创建的目录列表。

示例:

file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mydir)

7. RENAME

用于重命名文件或目录。

file(RENAME )

:原文件名或目录名。:新文件名或目录名。

示例:

file(RENAME oldname.txt newname.txt)

8. TOUCH

用于创建空文件或更新文件的时间戳。

file(TOUCH ...)

:要操作的文件列表。

示例:

file(TOUCH newfile.txt)

9. GENERATE

用于生成文件。

file(GENERATE OUTPUT CONTENT )

OUTPUT:生成的文件路径。CONTENT:文件内容。

示例:

file(GENERATE OUTPUT config.h CONTENT "#define VERSION 1.0")

注意事项

路径可以是绝对路径或相对路径(相对于 CMAKE_CURRENT_SOURCE_DIR)。某些操作(如 GLOB)在配置阶段执行,而不是构建阶段。

3. 构建目标管理

add_executable

add_executable 是 CMake 中的一个命令,用于创建一个可执行文件。它的基本语法如下:

add_executable( [source1] [source2] ...)

:指定要生成的可执行文件的名称。这个名称在项目中必须是唯一的。[source1] [source2] ...:列出构建可执行文件所需的源文件(如 .c、.cpp 文件等)。

示例

add_executable(my_app main.cpp helper.cpp)

这个命令会生成一个名为 my_app 的可执行文件,使用 main.cpp 和 helper.cpp 作为源文件。

注意事项

源文件路径:如果源文件不在当前 CMakeLists.txt 所在的目录中,需要指定相对或绝对路径。目标名称唯一性: 必须在项目中唯一,不能与其他目标(如库或其他可执行文件)重名。依赖管理:add_executable 只定义可执行文件的生成,如果依赖其他库,需要使用 target_link_libraries 进行链接。

add_library

add_library 是 CMake 中的一个命令,用于创建库文件(静态库、共享库或模块库)。它的基本语法如下:

add_library( [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [source1] [source2 ...])

参数说明

指定库的名称,生成的库文件会根据平台自动添加前缀和后缀(如 lib 和 .a、.so 等)。

库类型(可选)

STATIC:创建静态库(.a 或 .lib)。SHARED:创建共享库(.so 或 .dll)。MODULE:创建模块库(通常用于插件,不链接到其他目标,但可以动态加载)。

如果未指定类型,默认由 BUILD_SHARED_LIBS 变量决定(默认为 STATIC)。

EXCLUDE_FROM_ALL(可选)

如果指定,该库不会在默认构建目标(如 make all)中构建,需要显式构建。

源文件(source1, source2, …)

列出构建库所需的源文件(如 .cpp, .c)。可以是绝对路径或相对路径(相对于 CMakeLists.txt)。

示例

创建静态库

add_library(my_static_lib STATIC src/file1.cpp src/file2.cpp)

创建共享库

add_library(my_shared_lib SHARED src/file1.cpp src/file2.cpp)

不指定类型(依赖 BUILD_SHARED_LIBS)

set(BUILD_SHARED_LIBS ON) # 默认生成 SHARED 库

add_library(my_lib src/file1.cpp)

排除默认构建

add_library(optional_lib EXCLUDE_FROM_ALL STATIC src/optional.cpp)

注意事项

库名称在项目中必须唯一。源文件路径建议使用 target_sources 动态管理,而非硬编码在 add_library 中。

target_link_libraries

target_link_libraries 是 CMake 中的一个命令,用于将库文件链接到指定的目标(target)。这个目标通常是通过 add_executable 或 add_library 命令生成的可执行文件或库。

基本语法

target_link_libraries( [PRIVATE|PUBLIC|INTERFACE] ...)

:需要链接库的目标名称,通常是 add_executable 或 add_library 创建的目标。PRIVATE|PUBLIC|INTERFACE:可选的关键字,用于指定链接的可见性:

PRIVATE:库仅链接到目标本身,不会传递给依赖该目标的其他目标。PUBLIC:库不仅链接到目标本身,还会传递给依赖该目标的其他目标。INTERFACE:库不会链接到目标本身,但会传递给依赖该目标的其他目标。

...:要链接的库文件或目标名称。可以是库文件的路径、库的名称(如 pthread)或其他 CMake 目标。

示例

链接系统库

add_executable(my_app main.cpp)

target_link_libraries(my_app pthread)

这里将 pthread 库链接到 my_app 可执行文件。

使用可见性关键字

add_library(my_lib STATIC my_lib.cpp)

target_link_libraries(my_lib PRIVATE some_private_lib)

target_link_libraries(my_lib PUBLIC some_public_lib)

some_private_lib 仅用于 my_lib 的构建。some_public_lib 不仅用于 my_lib,还会传递给链接 my_lib 的其他目标。

链接其他 CMake 目标

add_library(helper_lib STATIC helper.cpp)

add_executable(my_app main.cpp)

target_link_libraries(my_app PRIVATE helper_lib)

这里将 helper_lib 静态库链接到 my_app 可执行文件。

注意事项

如果未指定 PRIVATE、PUBLIC 或 INTERFACE,默认行为可能因 CMake 版本而异,建议显式指定。可以一次链接多个库,例如:target_link_libraries(my_app PUBLIC lib1 lib2)

target_link_libraries 是 CMake 中管理依赖关系的重要命令,确保构建时正确链接所需的库文件。

target_include_directories

target_include_directories 是 CMake 中的一个命令,用于为特定的目标(如可执行文件或库)指定头文件的搜索路径。

语法

target_include_directories( [SYSTEM] [BEFORE]

[items1...]

[ [items2...] ...])

参数说明

:目标名称,必须是通过 add_executable() 或 add_library() 创建的目标。[SYSTEM]:可选参数,将目录标记为系统头文件目录,编译器可能会抑制这些目录的警告。[BEFORE]:可选参数,将包含目录添加到现有目录之前。:指定包含目录的可见性:

PRIVATE:仅用于构建目标本身。PUBLIC:用于构建目标本身和依赖该目标的其他目标。INTERFACE:仅用于依赖该目标的其他目标。

示例

add_executable(my_app main.cpp)

target_include_directories(my_app PRIVATE include)

注意事项

路径可以是绝对路径或相对路径(相对于当前 CMakeLists.txt 文件)。多次调用 target_include_directories 会追加目录,而不是覆盖。使用 PUBLIC 或 INTERFACE 时,依赖该目标的其他目标会自动继承这些包含目录。

target_compile_options

target_compile_options 是 CMake 中的一个命令,用于为特定的目标(如可执行文件或库)添加编译选项。这些选项可以是编译器特定的标志,例如警告选项、优化选项等。

语法

target_compile_options( [BEFORE]

[items1...]

[ [items2...] ...])

:指定要添加编译选项的目标名称。BEFORE:可选参数,表示将新选项插入到现有选项之前。INTERFACE|PUBLIC|PRIVATE:指定选项的可见性范围:

PRIVATE:仅用于当前目标的编译。PUBLIC:用于当前目标的编译,并且会传递给依赖该目标的其他目标。INTERFACE:仅传递给依赖该目标的其他目标,不用于当前目标的编译。

items1..., items2...:要添加的编译选项列表。

示例

add_executable(my_app main.cpp)

# 添加私有编译选项(仅用于 my_app)

target_compile_options(my_app PRIVATE -Wall -Wextra)

# 添加公共编译选项(用于 my_app 并传递给依赖它的目标)

target_compile_options(my_lib PUBLIC -O2)

注意事项

选项的格式取决于所使用的编译器(如 GCC、Clang、MSVC)。使用 PRIVATE、PUBLIC 或 INTERFACE 时需根据需求选择合适的可见性。可以通过 BEFORE 控制选项的插入顺序,这在某些情况下可能影响编译行为。

target_compile_definitions

target_compile_definitions 是 CMake 中的一个命令,用于向特定的目标(如可执行文件或库)添加预处理器定义。这些定义会在编译时传递给编译器,通常用于条件编译或配置代码的不同行为。

语法

target_compile_definitions(

[items1...]

[ [items2...] ...])

:指定要添加预处理器定义的目标名称。INTERFACE|PUBLIC|PRIVATE:指定定义的作用范围:

PRIVATE:仅适用于当前目标的编译。PUBLIC:适用于当前目标的编译,并且会传递给依赖该目标的其他目标。INTERFACE:仅传递给依赖该目标的其他目标,不用于当前目标的编译。

[items...]:预处理器定义的列表,可以是 -D 开头的定义(如 -DDEBUG),或直接写定义(如 DEBUG=1)。

示例

添加私有定义(仅当前目标使用):

target_compile_definitions(my_target PRIVATE DEBUG)

等效于在编译时传递 -DDEBUG。

添加公有定义(当前目标和依赖目标使用):

target_compile_definitions(my_target PUBLIC USE_FEATURE_X)

添加接口定义(仅依赖目标使用):

target_compile_definitions(my_target INTERFACE ENABLE_LOGGING)

带值的定义:

target_compile_definitions(my_target PRIVATE "VERSION=1.0")

等效于 -DVERSION=1.0。

注意事项

定义可以是简单的标识符(如 DEBUG)或带值的定义(如 VERSION=1.0)。如果定义中包含空格或特殊字符,建议用引号包裹。该命令仅适用于通过 add_executable() 或 add_library() 创建的目标。

4. 依赖管理

find_package

find_package 是 CMake 中的一个命令,用于查找并导入外部库(如 Boost、OpenCV 等)。它的主要功能是定位系统上已安装的第三方库,并设置相关变量,以便在 CMake 项目中使用这些库。

基本语法

find_package( [version] [EXACT] [QUIET] [MODULE]

[REQUIRED] [[COMPONENTS] [components...]]

[OPTIONAL_COMPONENTS components...]

[NO_POLICY_SCOPE])

参数说明

:要查找的包名称(如 Boost、OpenCV)。version:可选,指定所需的最低版本号(如 2.8.0)。EXACT:可选,要求版本号必须完全匹配。QUIET:可选,抑制未找到包时的警告信息。MODULE:可选,优先使用 Find.cmake 模块模式。REQUIRED:可选,如果未找到包,则终止 CMake 配置并报错。COMPONENTS:可选,指定需要查找的库组件(如 Boost 的 filesystem、system)。OPTIONAL_COMPONENTS:可选,指定可选的库组件。

工作原理

查找包:

CMake 会搜索 Config.cmake 或 Find.cmake 文件。搜索路径包括:

CMAKE_PREFIX_PATH 指定的路径。系统默认路径(如 /usr/local、/usr)。

设置变量:

成功找到包后,CMake 会设置以下变量:

_FOUND:表示是否找到包(TRUE/FALSE)。_INCLUDE_DIRS:包含头文件的路径。_LIBRARIES:库文件路径。

使用包:

通过 target_link_libraries 将库链接到目标。

示例

# 查找 OpenCV,要求最低版本 3.0,且必须找到

find_package(OpenCV 3.0 REQUIRED)

if(OpenCV_FOUND)

# 添加 OpenCV 头文件路径

include_directories(${OpenCV_INCLUDE_DIRS})

# 将 OpenCV 库链接到目标

target_link_libraries(my_target ${OpenCV_LIBRARIES})

endif()

注意事项

如果包未找到且未指定 REQUIRED,CMake 不会报错,但 _FOUND 为 FALSE。使用 COMPONENTS 时,需确保包支持组件化(如 Boost)。

find_library

find_library 是 CMake 提供的一个命令,用于在系统中查找指定的库文件。它会搜索常见的库文件路径,并返回找到的库文件的完整路径。这个命令通常用于定位第三方库的位置。

基本语法:

find_library( name [path1 path2 ...])

:用于存储找到的库文件路径的变量名。name:要查找的库的名称(不包含前缀 lib 和后缀,如 .so 或 .a)。[path1 path2 ...]:可选参数,指定额外的搜索路径。

示例:

find_library(LOG_LIB log)

如果找到 liblog.so 或 liblog.a,路径会存储在变量 LOG_LIB 中。

常见选项:

NO_DEFAULT_PATH:禁止搜索默认路径。PATHS:指定额外的搜索路径。

find_path

find_path 是 CMake 提供的一个命令,用于在系统中查找指定的头文件路径。它会搜索常见的头文件路径,并返回找到的头文件所在的目录路径。这个命令通常用于定位第三方库的头文件位置。

基本语法:

find_path( name [path1 path2 ...])

:用于存储找到的头文件目录路径的变量名。name:要查找的头文件名(如 stdio.h)。[path1 path2 ...]:可选参数,指定额外的搜索路径。

示例:

find_path(ZLIB_INCLUDE_DIR zlib.h)

如果找到 zlib.h,其所在目录路径会存储在变量 ZLIB_INCLUDE_DIR 中。

常见选项:

NO_DEFAULT_PATH:禁止搜索默认路径。PATHS:指定额外的搜索路径。

使用场景

find_library 和 find_path 通常结合使用,用于定位第三方库的头文件和库文件路径。例如:

find_path(OPENSSL_INCLUDE_DIR openssl/ssl.h)

find_library(OPENSSL_LIBRARY ssl)

if (OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARY)

include_directories(${OPENSSL_INCLUDE_DIR})

target_link_libraries(my_target ${OPENSSL_LIBRARY})

endif()

include_directories

include_directories 是 CMake 中的一个命令,用于向构建系统添加头文件的搜索路径。这个命令会全局地影响当前 CMakeLists.txt 及其所有子目录中的所有目标(如可执行文件和库)。

基本语法

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

参数说明

AFTER|BEFORE:可选参数,控制新路径是追加到现有路径之后(AFTER,默认行为)还是插入到现有路径之前(BEFORE)。SYSTEM:可选参数,将目录标记为系统头文件目录(编译器可能会抑制这些目录中的警告)。dir1 [dir2 ...]:要添加的头文件搜索路径(可以是绝对路径或相对路径)。

特点

全局性:会影响当前目录及所有子目录中的所有目标。不推荐使用:现代 CMake 更推荐使用 target_include_directories(),因为它可以精确控制每个目标的头文件搜索路径,避免污染全局作用域。路径顺序:默认新路径追加到现有路径列表末尾,但可以通过 BEFORE 调整。

示例

include_directories(${PROJECT_SOURCE_DIR}/include)

注意事项

如果路径中包含空格,需要用引号包裹(如 "path/with spaces")。相对路径会被解释为相对于当前 CMakeLists.txt 所在目录。

link_directories

link_directories 是 CMake 中的一个命令,用于在构建过程中指定链接器搜索库文件的目录路径。它会全局添加库文件搜索路径,影响当前目录及所有子目录中的目标。

基本语法

link_directories(directory1 directory2 ...)

主要特点

全局作用:设置的路径会影响当前 CMakeLists.txt 及其所有子目录中的目标。链接器搜索路径:这些目录会被添加到链接器的库文件搜索路径中(如 -L 选项在 GCC 中)。不推荐使用:CMake 官方文档建议优先使用 target_link_directories() 或直接指定库的完整路径。

使用示例

link_directories(/path/to/libs /another/path)

add_executable(my_app main.cpp)

target_link_libraries(my_app my_library) # 链接器会在上述路径中查找 my_library

注意事项

现代 CMake 推荐使用 target_link_directories() 替代,因为它可以精确控制每个目标的链接路径。直接使用绝对路径指定库文件通常是最可靠的做法。过度使用可能导致构建系统难以维护,特别是大型项目中。

5. 属性与配置

set_property

set_property 是 CMake 中的一个命令,用于设置目标(targets)、源文件(source files)、目录(directories)或其他 CMake 实体的属性。属性可以用于控制构建过程中的各种行为,例如编译选项、链接选项、依赖关系等。

基本语法

set_property( [ ...]

PROPERTY [ ...])

参数说明

:指定属性的作用范围,可以是以下之一:

GLOBAL:全局属性。DIRECTORY:目录属性。TARGET:目标属性(如可执行文件或库)。SOURCE:源文件属性。TEST:测试属性。CACHE:缓存变量属性。

[ …]:指定要设置属性的目标或文件列表。具体取决于 SCOPE 的选择。

PROPERTY :指定要设置的属性名称。

[ …]:属性的值,可以是单个值或多个值(取决于属性类型)。

示例

设置目标属性:

add_executable(my_app main.cpp)

set_property(TARGET my_app PROPERTY CXX_STANDARD 11)

这里将 my_app 目标的 C++ 标准设置为 C++11。

设置源文件属性:

set_property(SOURCE main.cpp PROPERTY COMPILE_DEFINITIONS "DEBUG=1")

这里为 main.cpp 源文件设置了一个编译定义 DEBUG=1。

设置全局属性:

set_property(GLOBAL PROPERTY USE_FOLDERS ON)

这里设置了一个全局属性 USE_FOLDERS,用于启用 IDE 中的文件夹组织功能。

注意事项

属性的名称和值取决于具体的 CMake 版本和生成器(如 Makefile、Visual Studio 等)。某些属性是只读的,不能通过 set_property 修改。可以使用 get_property 命令获取属性的当前值。

set_property 是 CMake 中非常灵活的命令,可以用于精细控制构建过程的各个方面。

set_target_properties

set_target_properties 是 CMake 中用于设置目标(target)属性的命令。目标可以是可执行文件(add_executable 创建)、静态库(add_library 创建,类型为 STATIC)或动态库(add_library 创建,类型为 SHARED)。

语法

set_target_properties(target1 target2 ...

PROPERTIES prop1 value1

prop2 value2 ...)

参数说明

target1 target2 …:需要设置属性的目标名称。PROPERTIES:关键字,表示后面是属性名和属性值的列表。prop1 value1, prop2 value2 …:要设置的属性名和对应的值。

常用属性

OUTPUT_NAME:指定目标输出文件的名称(不包含扩展名)。

set_target_properties(my_lib PROPERTIES OUTPUT_NAME "renamed_lib")

生成的文件可能是 renamed_lib.a(静态库)或 renamed_lib.so(动态库)。

VERSION:设置目标的版本号(通常用于动态库)。

set_target_properties(my_lib PROPERTIES VERSION "1.2.3")

生成的文件可能是 my_lib.so.1.2.3(Linux)或 my_lib.1.2.3.dylib(macOS)。

SOVERSION:设置目标的符号版本号(通常用于动态库的兼容性)。

set_target_properties(my_lib PROPERTIES SOVERSION "1")

生成的文件可能是 my_lib.so.1(符号链接到 my_lib.so.1.2.3)。

CXX_STANDARD:设置目标的 C++ 标准(如 C++11、C++14 等)。

set_target_properties(my_target PROPERTIES CXX_STANDARD 11)

COMPILE_FLAGS:设置目标的编译选项。

set_target_properties(my_target PROPERTIES COMPILE_FLAGS "-Wall -Wextra")

示例

add_library(my_shared_lib SHARED src.cpp)

set_target_properties(my_shared_lib

PROPERTIES

OUTPUT_NAME "custom_name"

VERSION "1.0.0"

SOVERSION "1")

生成的文件可能是:

custom_name.so.1.0.0(实际库文件)custom_name.so.1(符号链接到 custom_name.so.1.0.0)custom_name.so(符号链接到 custom_name.so.1)

option

在 CMake 中,option 是一个命令,用于定义一个可以由用户在配置阶段(cmake 命令运行时)切换的布尔选项。它的语法如下:

option( "" [initial_value])

:选项的名称,通常使用大写字母(如 BUILD_TESTS)。:描述选项用途的字符串,会显示在 CMake 的 GUI 工具(如 ccmake 或 cmake-gui)中。[initial_value](可选):选项的默认值(ON 或 OFF),默认为 OFF。

示例

option(BUILD_TESTS "Build the test suite" ON)

定义了一个名为 BUILD_TESTS 的选项,默认值为 ON。用户可以通过命令行覆盖默认值:cmake -DBUILD_TESTS=OFF ..

用途

控制项目的可选功能(如测试、文档生成)。在 if() 语句中检查选项状态:if(BUILD_TESTS)

add_subdirectory(tests)

endif()

注意

option 仅支持布尔值(ON/OFF)。与 set(... CACHE BOOL "...") 类似,但 option 更简洁。

6. 安装与导出

install

install 是 CMake 中的一个命令,用于定义项目安装规则。它指定了在构建完成后,如何将生成的文件(如可执行文件、库、头文件等)安装到目标系统中。

基本语法

install(TARGETS ...

[EXPORT ]

[RUNTIME|LIBRARY|ARCHIVE|FRAMEWORK|BUNDLE|PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]

DESTINATION

[PERMISSIONS ...]

[CONFIGURATIONS [Debug|Release|...]]

[COMPONENT ]

[OPTIONAL] [NAMELINK_COMPONENT ]

[NAMELINK_ONLY|NAMELINK_SKIP]

[...])

install(FILES ...

DESTINATION

[PERMISSIONS ...]

[CONFIGURATIONS [Debug|Release|...]]

[COMPONENT ]

[RENAME ] [OPTIONAL])

install(DIRECTORY

...

DESTINATION

[FILE_PERMISSIONS ...]

[DIRECTORY_PERMISSIONS ...]

[USE_SOURCE_PERMISSIONS] [OPTIONAL]

[CONFIGURATIONS [Debug|Release|...]]

[COMPONENT ]

[FILES_MATCHING]

[[PATTERN | REGEX ]

[EXCLUDE] [PERMISSIONS ...]] [...])

主要用途

安装目标文件(如可执行文件、库):

install(TARGETS my_executable

RUNTIME DESTINATION bin)

TARGETS 指定要安装的目标(如可执行文件或库)。RUNTIME 表示可执行文件,LIBRARY 表示共享库,ARCHIVE 表示静态库。DESTINATION 指定安装目录(如 bin、lib、include)。

安装文件(如头文件、配置文件):

install(FILES my_header.h

DESTINATION include)

FILES 指定要安装的单个文件。DESTINATION 指定目标目录。

安装目录(递归安装目录内容):

install(DIRECTORY include/

DESTINATION include)

DIRECTORY 指定要安装的目录。可以使用 PATTERN 或 REGEX 过滤文件。

常用选项

PERMISSIONS:设置文件权限(如 OWNER_READ、GROUP_WRITE)。CONFIGURATIONS:指定仅在特定构建配置(如 Debug 或 Release)下安装。COMPONENT:将安装内容分组到组件中(用于分步安装)。

示例

# 安装可执行文件到 bin 目录

install(TARGETS my_app

RUNTIME DESTINATION bin)

# 安装静态库到 lib 目录

install(TARGETS my_lib

ARCHIVE DESTINATION lib)

# 安装头文件到 include 目录

install(FILES my_header.h

DESTINATION include)

# 安装整个目录(递归)

install(DIRECTORY docs/

DESTINATION share/doc)

export

export 是 CMake 中的一个命令,用于将当前项目的配置导出,以便其他项目可以方便地引用和使用。它通常用于库项目的构建,使得其他项目可以通过 find_package() 命令找到并使用该库。

基本语法

export(EXPORT

[NAMESPACE ]

[FILE ]

[CXX_MODULES_DIRECTORY ])

参数说明

EXPORT

指定要导出的目标集合的名称,这个名称通常是通过 install(TARGETS ... EXPORT ...) 命令定义的。

NAMESPACE

为导出的目标添加命名空间前缀,避免命名冲突。例如,如果命名空间是 MyLib::,那么目标 mylib 会被导出为 MyLib::mylib。

FILE

指定导出的配置文件名称。如果不指定,默认会生成一个 .cmake 文件。

CXX_MODULES_DIRECTORY

(可选)指定 C++ 模块文件的导出目录(CMake 3.28+ 支持)。

使用场景

导出库目标供其他项目使用

在库项目中,通过 export 命令生成配置文件,其他项目可以通过 find_package() 直接引用该库。

与 install(EXPORT) 结合使用

通常在库的安装脚本中,export 会和 install(EXPORT) 一起使用,确保库的安装和导出配置同时完成。

示例

# 定义一个库目标

add_library(mylib STATIC mylib.cpp)

# 安装目标并指定导出名称

install(TARGETS mylib

EXPORT MyLibTargets

ARCHIVE DESTINATION lib)

# 导出目标配置到 MyLibTargets.cmake 文件

export(EXPORT MyLibTargets

FILE "${CMAKE_CURRENT_BINARY_DIR}/MyLibTargets.cmake"

NAMESPACE MyLib::)

其他项目可以通过以下方式引用:

find_package(MyLib REQUIRED)

target_link_libraries(myapp PRIVATE MyLib::mylib)

注意事项

export 通常用于开发阶段的临时导出,而 install(EXPORT) 用于正式安装时的导出。导出的文件需要与项目的版本和配置(如 Debug/Release)匹配。

configure_file

configure_file 是 CMake 中的一个命令,用于生成配置文件。它通常用于将模板文件中的变量替换为 CMake 中的值,从而生成最终的配置文件。

基本语法

configure_file(

[COPYONLY] [ESCAPE_QUOTES] [@ONLY]

[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF]])

参数说明

: 输入的模板文件路径(通常是 .in 文件)。: 生成的配置文件路径。COPYONLY: 仅复制文件,不进行变量替换。ESCAPE_QUOTES: 对引号进行转义处理。@ONLY: 仅替换 @VAR@ 形式的变量,不替换 ${VAR} 形式的变量。NEWLINE_STYLE: 指定生成文件的换行符风格(如 UNIX 的 LF 或 Windows 的 CRLF)。

使用示例

假设有一个模板文件 config.h.in,内容如下:

#define VERSION "@PROJECT_VERSION@"

#define INSTALL_PATH "@CMAKE_INSTALL_PREFIX@"

在 CMakeLists.txt 中使用 configure_file:

project(MyProject VERSION 1.0.0)

configure_file(config.h.in config.h)

生成的 config.h 文件内容为:

#define VERSION "1.0.0"

#define INSTALL_PATH "/usr/local"

常见用途

生成版本信息文件:将项目版本号写入头文件。配置安装路径:根据 CMAKE_INSTALL_PREFIX 生成路径配置文件。平台相关配置:根据不同的编译环境生成不同的配置。

注意事项

输入文件中的变量必须已在 CMake 中定义,否则会被替换为空字符串。使用 @ONLY 可以避免与脚本语言(如 shell)的变量冲突。

7. 测试与文档

enable_testing

enable_testing() 是 CMake 中的一个命令,用于在当前目录及其子目录中启用测试功能。它通常与 add_test() 命令一起使用,用于定义和运行项目的测试用例。

功能

启用 CMake 的测试功能,使得后续可以使用 add_test() 命令添加测试用例。必须在调用 add_test() 之前调用 enable_testing(),否则 add_test() 不会生效。

语法

enable_testing()

使用示例

# 启用测试功能

enable_testing()

# 添加一个测试用例

add_test(NAME my_test COMMAND my_test_executable)

注意事项

enable_testing() 只需要在 CMakeLists.txt 文件中调用一次,通常在项目的根目录或测试目录中调用。如果没有调用 enable_testing(),即使定义了 add_test(),也不会生成任何测试目标。启用测试后,可以通过 ctest 命令运行测试。

add_test

add_test 是 CMake 中的一个命令,用于向项目添加测试用例。它通常与 CTest(CMake 的测试工具)结合使用,用于定义和运行项目的测试。

基本语法

add_test(NAME COMMAND [...]

[CONFIGURATIONS ...]

[WORKING_DIRECTORY

]

[COMMAND_EXPAND_LISTS])

参数说明

NAME:指定测试的名称,用于标识测试用例。COMMAND:指定运行测试的可执行文件及其参数。CONFIGURATIONS(可选):指定测试仅在特定的构建配置(如 Debug、Release)下运行。WORKING_DIRECTORY(可选):设置测试运行的工作目录。COMMAND_EXPAND_LISTS(可选):如果命令参数中包含生成器表达式($<...>),则展开列表。

示例

add_executable(MyTest test.cpp)

add_test(NAME MyTest COMMAND MyTest)

注意事项

add_test 通常与 enable_testing() 一起使用,后者用于启用测试功能。测试用例需要在 CMakeLists.txt 的适当位置定义,通常在项目构建完成后运行。使用 ctest 命令可以运行所有定义的测试用例。

运行测试

在构建目录下执行:

ctest

add_test 是 CMake 测试框架的基础,用于集成单元测试或其他验证步骤到构建流程中。

add_custom_target

add_custom_target 是 CMake 中的一个命令,用于在构建系统中创建一个自定义目标。自定义目标通常用于执行一些不需要编译的操作,例如生成文档、运行测试、打包发布等。

基本语法

add_custom_target(Name [ALL] [command1 [args1...]]

[COMMAND command2 [args2...] ...]

[DEPENDS depend depend depend ... ]

[BYPRODUCTS [files...]]

[WORKING_DIRECTORY dir]

[COMMENT comment]

[VERBATIM] [SOURCES src1 [src2...]])

参数说明

Name: 自定义目标的名称。ALL: 如果指定了 ALL,则该目标会被默认构建(即在执行 make 或 cmake --build 时会自动构建)。COMMAND: 指定要执行的命令。可以指定多个命令,它们会按顺序执行。DEPENDS: 指定该目标依赖的其他目标或文件。如果依赖项发生变化,该目标会重新构建。BYPRODUCTS: 指定该目标生成的副产品文件。这些文件可能会被其他目标依赖。WORKING_DIRECTORY: 指定命令执行的工作目录。COMMENT: 在执行目标时显示的注释信息。VERBATIM: 确保命令参数不会被转义或修改。SOURCES: 指定与该目标关联的源文件(通常用于 IDE 中的显示)。

示例

add_custom_target(docs

COMMAND doxygen Doxyfile

WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}

COMMENT "Generating API documentation with Doxygen"

)

在这个示例中,创建了一个名为 docs 的自定义目标,用于运行 Doxygen 生成文档。执行 make docs 时会触发该目标。

注意事项

自定义目标不会自动构建,除非指定了 ALL 或显式调用(如 make docs)。如果目标依赖其他文件或目标(通过 DEPENDS),则这些依赖项会被检查是否需要重新构建。自定义目标通常用于非编译任务,例如生成文档、运行测试或打包。

8. 条件逻辑与循环

if/else/endif

在 CMake 中,if/else/endif 用于条件判断,可以根据不同的条件执行不同的 CMake 命令或设置不同的变量。以下是基本语法和常见用法:

基本语法

if(condition)

# 条件为真时执行的命令

else()

# 条件为假时执行的命令

endif()

常见条件类型

变量检查

检查变量是否为真:if(VARIABLE_NAME)

检查变量是否等于某个值:if(VARIABLE_NAME STREQUAL "value")

逻辑运算

与运算(AND):if(condition1 AND condition2)

或运算(OR):if(condition1 OR condition2)

非运算(NOT):if(NOT condition)

文件或路径检查

检查文件是否存在:if(EXISTS "path/to/file")

检查是否为目录:if(IS_DIRECTORY "path/to/dir")

平台检查

检查操作系统类型:if(WIN32) # Windows

if(UNIX) # Unix-like (Linux, macOS)

if(APPLE) # macOS

示例

set(MY_VAR "ON")

if(MY_VAR STREQUAL "ON")

message(STATUS "MY_VAR is ON")

else()

message(STATUS "MY_VAR is OFF")

endif()

if(WIN32)

message(STATUS "Running on Windows")

elseif(APPLE)

message(STATUS "Running on macOS")

else()

message(STATUS "Running on Linux or other Unix-like system")

endif()

注意事项

if 和 endif 必须成对出现。条件表达式中的变量名不需要 ${} 符号(直接使用变量名)。字符串比较时区分大小写,建议使用 STREQUAL 或 STRCASEEQUAL(不区分大小写)。

foreach

foreach 是 CMake 中的一个控制流命令,用于遍历列表中的元素,并对每个元素执行相同的操作。它通常用于批量处理多个文件或目标,例如编译多个源文件或链接多个库。

基本语法

foreach(loop_var item1 item2 ... itemN)

# 循环体,可以使用 ${loop_var} 引用当前元素

endforeach()

参数说明

loop_var:循环变量,每次迭代时会赋值为当前列表元素。item1 item2 … itemN:要遍历的列表元素,可以是变量或直接列出的值。

示例

遍历直接列出的值

以下示例打印列表中的每个元素:

foreach(name Alice Bob Charlie)

message("Hello, ${name}!")

endforeach()

输出:

Hello, Alice!

Hello, Bob!

Hello, Charlie!

遍历变量中的列表

使用 set 定义列表变量,并通过 foreach 遍历:

set(SOURCE_FILES main.cpp utils.cpp helper.cpp)

foreach(file ${SOURCE_FILES})

message("Processing file: ${file}")

endforeach()

结合范围生成列表

使用 RANGE 关键字生成数字序列并遍历:

foreach(i RANGE 1 3)

message("Index: ${i}")

endforeach()

输出:

Index: 1

Index: 2

Index: 3

高级用法

遍历目录中的文件

结合 file(GLOB) 获取文件列表并处理:

file(GLOB SOURCES "src/*.cpp")

foreach(src ${SOURCES})

message("Found source: ${src}")

endforeach()

嵌套循环

支持多层嵌套遍历:

foreach(dir include src)

foreach(file ${dir}/*.h ${dir}/*.cpp)

message("File: ${file}")

endforeach()

endforeach()

注意事项

循环变量(如 loop_var)的作用域仅限于 foreach 和 endforeach 之间。若需提前终止循环,可使用 break() 或 continue() 控制流程。

function/macro

在 CMake 中,function 和 macro 用于定义可重用的代码块,类似于其他编程语言中的函数或宏。它们的主要区别在于作用域和参数传递方式。

function

使用 function(name [arg1 [arg2 ...]]) 定义函数。函数有自己的作用域,变量在函数内部定义不会影响外部作用域。参数按值传递,函数内部对参数的修改不会影响外部变量。使用 return() 可以提前退出函数。

示例:

function(my_function arg1 arg2)

message("arg1: ${arg1}, arg2: ${arg2}")

set(arg1 "new_value") # 修改不会影响外部

endfunction()

my_function("hello" "world")

macro

使用 macro(name [arg1 [arg2 ...]]) 定义宏。宏没有独立作用域,相当于直接将代码插入调用位置。参数按名称传递(类似文本替换),宏内部对参数的修改会影响外部变量。不能使用 return() 退出宏。

示例:

macro(my_macro arg1 arg2)

message("arg1: ${arg1}, arg2: ${arg2}")

set(arg1 "new_value") # 修改会影响外部

endmacro()

my_macro("hello" "world")

选择建议

优先使用 function,除非需要宏的文本替换特性。宏适合简单代码替换,函数适合复杂逻辑。

9. 高级特性

include

include 是 CMake 中的一个命令,用于在当前的 CMake 脚本中包含其他 CMake 脚本文件。它通常用于引入外部的工具链文件、模块或其他 CMake 脚本,以便复用代码或配置。

基本语法

include( [OPTIONAL] [RESULT_VARIABLE ])

:指定要包含的文件或模块名。可以是绝对路径或相对路径(相对于当前 CMake 脚本的路径)。OPTIONAL:可选参数。如果文件不存在,CMake 不会报错,而是静默忽略。RESULT_VARIABLE :可选参数。将包含操作的结果(成功时为文件的完整路径,失败时为 NOTFOUND)存储到变量 中。

示例

包含一个工具链文件:

include(toolchain.cmake)

包含一个模块(CMake 会在模块路径中查找):

include(FindPython)

使用 OPTIONAL 和 RESULT_VARIABLE:

include(optional_file.cmake OPTIONAL RESULT_VARIABLE included_file)

if (NOT included_file)

message(WARNING "Optional file not found!")

endif()

注意事项

include 不会引入新的变量作用域,被包含文件中的变量会影响当前作用域。如果文件路径包含空格或特殊字符,需要用引号括起来。

相关文章

做天猫任务的方法与发布步骤 天猫任务多少钱
365bet手机端

做天猫任务的方法与发布步骤 天猫任务多少钱

⌚ 08-11 👁️‍🗨️ 7657
1954年属什么生肖属相?
365bet手机端

1954年属什么生肖属相?

⌚ 10-04 👁️‍🗨️ 4372
小红书为啥比官网便宜?小红书是正品还是假货?
365bet网球比赛比分

小红书为啥比官网便宜?小红书是正品还是假货?

⌚ 07-21 👁️‍🗨️ 5425