文章目录
- CMake 的基本语法和用法
- 1. CMakeLists.txt 基本结构
- 2. 变量和宏
- 3. 条件语句
- 4. 循环语句
- 5. 定义和使用函数
- 6. 导入库和链接库
- 7. 设置编译器选项
- message
- 1. 显示普通消息:
- 2. 显示带模式的消息:
- 3. 显示变量值:
- 4. 显示多行消息:
- 5. 显示条件消息:
- set的常见用法
- 1. 简单的变量定义:
- 2. 定义列表变量:
- 3. 引用变量的值:
- 4. 添加到已有变量:
- 5. 条件设置:
- 6. 缓存变量:
- file
- 1. 复制文件
- 2. 创建目录
- 3. 移动文件
- 4. 移除文件
- 5. 读取文件内容
- 6. 写入文件内容
- add_library
- 1. 添加静态库:
- 2. 添加共享库:
- 3. 添加模块库:
- 4. 添加源文件到现有库:
- target_sources
- target_include_directories
- target_link_libraries
- 1. 链接到其他库:
- 2. 链接到多个库:
- 3. 链接到系统库:
- 4. 链接到第三方库:
- 5. 链接到其他目标:
- 6. 指定链接选项:
- PUBLIC关键字
- 参考
CMake(Cross-platform Make,跨平台构建)是一个跨平台的构建工具,用于管理项目的构建过程。它使用简单的配置文件(CMakeLists.txt
)来生成本地化的构建文件,如 Makefile 或 Visual Studio 解决方案。
以下是 CMake 的基本语法和用法:
CMake 的基本语法和用法
1. CMakeLists.txt 基本结构
一个简单的 CMakeLists.txt
文件通常包含以下基本结构:
# 最小版本要求
cmake_minimum_required(VERSION 3.10)# 项目名称
project(MyProject)# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)# 添加可执行文件或库的源文件
add_executable(MyExecutable main.cpp)# 添加子目录,进入子目录继续构建
add_subdirectory(subdirectory_name)
2. 变量和宏
# 定义变量
set(SOURCES file1.cpp file2.cpp)# 使用变量
add_executable(MyExecutable ${SOURCES})# 定义宏
macro(my_macro arg1 arg2)# 宏体message("Arguments: ${arg1}, ${arg2}")
endmacro()# 使用宏
my_macro(value1 value2)
3. 条件语句
# 条件语句
if(CONDITION)# 条件成立时执行的命令
elseif(ANOTHER_CONDITION)# 另一个条件成立时执行的命令
else()# 如果所有条件都不成立时执行的命令
endif()
4. 循环语句
# 循环语句
foreach(item IN LISTS my_list)# 循环体message(${item})
endforeach()
5. 定义和使用函数
# 定义函数
function(my_function arg1 arg2)# 函数体message("Arguments: ${arg1}, ${arg2}")
endfunction()# 使用函数
my_function(value1 value2)
6. 导入库和链接库
# 导入库
find_library(MY_LIBRARY my_library)# 链接库
target_link_libraries(MyExecutable ${MY_LIBRARY})
7. 设置编译器选项
# 设置编译器选项
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")# 或者
add_compile_options(-Wall)
message
message
命令用于在 CMake 构建过程中输出信息。它对于调试和显示构建脚本中的信息非常有用。基本语法如下:
message([<mode>] "message to display" ...)
其中:
<mode>
是可选的,用于指定消息的模式,可以是STATUS
、WARNING
、AUTHOR_WARNING
、SEND_ERROR
、FATAL_ERROR
或DEPRECATION
。如果省略<mode>
,则默认为STATUS
。"message to display"
是要显示的消息字符串。
以下是一些 message
命令的使用示例:
1. 显示普通消息:
message("This is a normal message.")
2. 显示带模式的消息:
message(STATUS "This is a status message.")
message(WARNING "This is a warning message.")
message(SEND_ERROR "This is an error message.")
message(FATAL_ERROR "This is a fatal error message.")
3. 显示变量值:
set(my_variable "Hello, CMake!")
message("Value of my_variable: ${my_variable}")
4. 显示多行消息:
message(STATUS "This is a multi-line message.\n""It spans multiple lines.")
5. 显示条件消息:
if(MY_CONDITION)message("Condition is true.")
else()message("Condition is false.")
endif()
message
命令对于调试 CMakeLists.txt 文件和构建过程中的问题非常有帮助。通过在适当的位置添加消息,可以更容易地理解 CMake 脚本的执行过程,以及在构建时的一些关键信息。
set的常见用法
在 CMake 中,set
命令用于定义变量。这个命令的基本语法是:
set(variable_name value1 value2 ...)
其中,variable_name
是变量的名称,而 value1 value2 ...
是变量的值。可以通过空格分隔多个值。
以下是一些 set
命令的常见用法:
1. 简单的变量定义:
set(my_variable "Hello, CMake!")
2. 定义列表变量:
set(my_list_variable "item1" "item2" "item3")
3. 引用变量的值:
message("Value of my_variable: ${my_variable}")
4. 添加到已有变量:
set(my_variable "Hello")
set(my_variable "${my_variable}, CMake!")
5. 条件设置:
if(SOME_CONDITION)set(my_variable "Value1")
else()set(my_variable "Value2")
endif()
6. 缓存变量:
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type (Debug/Release)" FORCE)
在这个例子中,CMAKE_BUILD_TYPE
是一个缓存变量,用于指定构建类型。FORCE
选项表示如果已经存在这个缓存变量,就覆盖它。
更多的使用场景和用法可以在CMake 官方文档中查看更详细的信息:
CMake - set Command。
file
在 CMake 中,file
命令用于操作文件系统。这个命令有多个子命令,用于执行不同的文件操作。以下是一些常见的 file
命令的用法:
1. 复制文件
file(COPY source_file DESTINATION destination_directory)
这个命令用于将文件从一个位置复制到另一个位置。例如:
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
2. 创建目录
file(MAKE_DIRECTORY directory_path)
这个命令用于创建目录。例如:
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/my_directory)
3. 移动文件
file(RENAME old_name new_name)
这个命令用于移动或重命名文件。例如:
file(RENAME ${CMAKE_CURRENT_BINARY_DIR}/file.txt ${CMAKE_CURRENT_BINARY_DIR}/new_file.txt)
4. 移除文件
file(REMOVE [files...])
这个命令用于移除文件。例如:
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/unnecessary_file.txt)
5. 读取文件内容
file(READ filename variable)
这个命令用于读取文件的内容并存储到一个变量中。例如:
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/version.txt VERSION)
message("Version: ${VERSION}")
6. 写入文件内容
file(WRITE filename content)
这个命令用于将指定的内容写入文件。例如:
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/output.txt "Hello, CMake!")
以上是 file
命令的一些常见用法,还有其他更多的子命令和选项,可以在 CMake 官方文档中查看更详细的信息:
CMake - file Command。
add_library
在 CMake 中,add_library
命令用于定义和构建一个库。这个命令的基本语法如下:
add_library(<library_name> [STATIC | SHARED | MODULE][EXCLUDE_FROM_ALL]source1 [source2 ...])
其中:
<library_name>
是库的名称,可以在后续的target_link_libraries
命令中使用这个名称引用这个库。[STATIC | SHARED | MODULE]
用于指定库的类型,可以是静态库(STATIC
,默认),共享库(SHARED
),或模块库(MODULE
)。[EXCLUDE_FROM_ALL]
是一个可选项,如果指定了,将把这个库从构建过程的默认目标中排除。
以下是一些 add_library
命令的用法示例:
1. 添加静态库:
add_library(my_static_lib STATIC source1.cpp source2.cpp)
2. 添加共享库:
add_library(my_shared_lib SHARED source1.cpp source2.cpp)
3. 添加模块库:
add_library(my_module_lib MODULE source1.cpp source2.cpp)
4. 添加源文件到现有库:
add_library(my_static_lib STATIC source1.cpp)
add_library(my_shared_lib SHARED source2.cpp)# 添加 source2.cpp 到 my_static_lib 和 my_shared_lib
target_sources(my_static_lib PRIVATE source2.cpp)
target_sources(my_shared_lib PRIVATE source2.cpp)
在上述示例中,my_static_lib
和 my_shared_lib
是库的名称,source1.cpp
和 source2.cpp
是库的源文件。
可以在 CMake 官方文档中查看更详细的信息:
CMake - add_library。
target_sources
target_sources
命令用于将源文件添加到一个已经存在的 CMake 目标(例如,可执行文件、库)。这个命令的基本语法如下:
target_sources(target_namePRIVATE source1 [source2 ...]PUBLIC source3 [source4 ...]INTERFACE source5 [source6 ...]
)
target_name
是目标的名称,可以是可执行文件或库的名称,由add_executable
或add_library
命令定义。PRIVATE
,PUBLIC
, 和INTERFACE
是关键字,用于指定添加源文件的属性。
PRIVATE
, PUBLIC
, 和 INTERFACE
关键字分别表示:
PRIVATE
: 源文件只会在目标的编译和链接阶段中可见,不会传递给依赖此目标的其他目标。PUBLIC
: 源文件会在目标的编译和链接阶段中可见,并且会传递给依赖此目标的其他目标。INTERFACE
: 源文件不会被添加到目标的编译和链接阶段中,但会传递给依赖此目标的其他目标。
以下是一些 target_sources
命令的使用示例:
# 添加私有源文件到目标
target_sources(my_executable PRIVATE source1.cpp source2.cpp)# 添加公共源文件到目标
target_sources(my_library PUBLIC source3.cpp source4.cpp)# 添加接口源文件到目标
target_sources(my_interface_library INTERFACE source5.cpp source6.cpp)
在上述示例中,my_executable
、my_library
、和 my_interface_library
是目标的名称,source1.cpp
到 source6.cpp
是源文件的名称。
target_sources
命令使得在 CMakeLists.txt 文件中添加源文件更加灵活,可以将源文件与目标关联起来,而不是直接将它们列在 add_executable
或 add_library
命令中。这样可以更容易地组织代码,并且在不同目标之间共享源文件。
target_include_directories
target_include_directories
用于向一个目标(例如可执行文件或库)添加头文件目录。这个命令的基本语法如下:
target_include_directories(target_name[SYSTEM] [BEFORE]INTERFACE|PUBLIC|PRIVATE[items1...][INTERFACE|PUBLIC|PRIVATE[items2]...]
)
其中:
target_name
是目标的名称,可以是可执行文件或库的名称,由add_executable
或add_library
命令定义。SYSTEM
关键字用于将目录标记为系统目录,通常用于禁止特定编译器的警告。BEFORE
关键字用于将目录添加到当前目录列表的前面,而不是后面。
INTERFACE
, PUBLIC
, 和 PRIVATE
关键字的含义与 target_sources
中的相同:
INTERFACE
: 目录不会被添加到目标的编译和链接阶段中,但会传递给依赖此目标的其他目标。PUBLIC
: 目录会在目标的编译和链接阶段中可见,并会传递给依赖此目标的其他目标。PRIVATE
: 目录只会在目标的编译和链接阶段中可见,不会传递给依赖此目标的其他目标。
以下是一些 target_include_directories
命令的使用示例:
# 添加私有头文件目录到目标
target_include_directories(my_executable PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)# 添加公共头文件目录到目标
target_include_directories(my_library PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)# 添加接口头文件目录到目标
target_include_directories(my_interface_library INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include)
在上述示例中,my_executable
、my_library
和 my_interface_library
是目标的名称,${CMAKE_CURRENT_SOURCE_DIR}/include
是头文件目录的路径。
target_include_directories
的主要目的是确保正确的头文件路径在编译和链接阶段中可用,并且能够传递给依赖此目标的其他目标。这有助于更好地组织项目中的头文件和确保正确的构建过程。
target_link_libraries
target_link_libraries
是 CMake 中的一个关键命令,用于指定一个目标(例如可执行文件或库)所依赖的其他库。这个命令的基本语法如下:
target_link_libraries(target_nameitem1item2...
)
其中:
target_name
是目标的名称,可以是可执行文件或库的名称,由add_executable
或add_library
命令定义。item1
,item2
, … 是目标所依赖的其他库或库的名称。
以下是一些 target_link_libraries
命令的使用示例:
1. 链接到其他库:
# 链接到名为 my_library 的库
target_link_libraries(my_executable my_library)
2. 链接到多个库:
# 链接到名为 my_library1 和 my_library2 的库
target_link_libraries(my_executable my_library1 my_library2)
3. 链接到系统库:
# 链接到系统库,例如 pthread
target_link_libraries(my_executable pthread)
4. 链接到第三方库:
# 链接到第三方库,例如 Boost
target_link_libraries(my_executable Boost::filesystem)
5. 链接到其他目标:
# 链接到另一个目标
target_link_libraries(my_executable my_other_target)
6. 指定链接选项:
# 指定链接选项
target_link_libraries(my_executable PRIVATE -Wl,-rpath,/custom/library/path)
上述示例中,my_executable
是目标的名称,my_library
, my_library1
, my_library2
, pthread
, Boost::filesystem
, my_other_target
是目标依赖的库或目标。
target_link_libraries
命令用于确保在链接目标时正确地包含所需的库。这对于确保可执行文件或库在构建和运行时都能正确链接到依赖项非常重要。
PUBLIC关键字
下面以target_link_libraries
为例,分析PUBLIC关键字。
target_link_libraries
命令中的 PUBLIC
关键字用于指定库的依赖关系,并将这些依赖关系传递给依赖于当前目标的其他目标。用于确保在链接时包含正确的依赖项。
基本语法如下:
target_link_libraries(target_namePUBLIC item1PUBLIC item2...
)
使用 PUBLIC
关键字的效果是,item1
, item2
, … 这些库将不仅会被链接到当前目标,还会传递给依赖于当前目标的其他目标。
示例:
# 定义一个库
add_library(my_library STATIC my_library.cpp)# 定义一个可执行文件,链接到 my_library
add_executable(my_executable main.cpp)
target_link_libraries(my_executable PUBLIC my_library)
示例中,my_executable
依赖于 my_library
,而且 my_library
中的依赖项也会传递给 my_executable
。
使用 PUBLIC
关键字还允许在 INTERFACE
和 PRIVATE
之间共享依赖关系。例如,PUBLIC
的依赖项既会被当前目标使用,也会被依赖于当前目标的其他目标使用。
参考
https://cmake.org/documentation/