CMakeLists.txt 中一些最常见和核心的命令
文章目录
- 核心命令
- 1 cmake_minimum_required()
- 2 project()
- 3 add_executable()
- 4 add_library()
- 5 target_link_libraries()
- 管理源文件和头文件
- 1 set()
- 2 aux_source_directory()
- 3 target_include_directories()
- 控制编译和链接
- 1 target_compile_definitions()
- 2 target_compile_options()
- 3 find_package()
- 流程控制和信息输出
- 1 if()/elseif()/else()/endif()
- 2 message()
- 3 add_subdirectory()
核心命令
这些是构建任何 C++ 项目几乎都必须用到的基础命令。
1 cmake_minimum_required()
- 用处: 指定构建该项目所需的 CMake 最低版本。如果用户使用的 CMake 版本低于这个要求,将会报错。这确保了项目构建脚本的兼容性,避免了因使用过时的 CMake 命令而导致的错误。
- 示例:
# 要求 CMake 版本至少为 3.10 cmake_minimum_required(VERSION 3.10)
2 project()
- 用处: 定义项目名称,并可以指定项目版本、描述和支持的语言。这个命令应该在 cmake_minimum_required() 之后立即调用。
- 示例:
# 定义项目名称为 "MyAwesomeApp" project(MyAwesomeApp VERSION 1.0.0DESCRIPTION "A very awesome application"LANGUAGES CXX) # CXX 代表 C++
3 add_executable()
- 用处: 使用指定的源文件来生成一个可执行文件。
- 语法: add_executable(<可执行文件名> <源文件1> [源文件2] …)
- 示例:
# 使用 main.cpp 和 utils.cpp 生成一个名为 "app" 的可执行文件 add_executable(app main.cpp utils.cpp)
4 add_library()
- 用处: 使用指定的源文件来生成一个库文件。库可以是静态库(STATIC)、共享库/动态库(SHARED)或仅用于组织代码的接口库(INTERFACE)。
- 语法: add_library(<库名> [STATIC | SHARED | INTERFACE] <源文件1> …)
- 示例:
# 创建一个名为 "myutils" 的静态库 add_library(myutils STATIC utils.cpp)# 创建一个名为 "sharedlib" 的共享库 add_library(sharedlib SHARED lib_source.cpp)
5 target_link_libraries()
- 用处: 将一个或多个库链接到指定的目标(可执行文件或另一个库)。这是管理依赖关系的核心命令。
- 语法: target_link_libraries(<目标名> [PUBLIC | PRIVATE | INTERFACE] <库1> [<库2>] …)
- PRIVATE: 依赖项仅对当前目标内部可见。
- PUBLIC: 依赖项对当前目标和链接到当前目标的其他目标都可见。
- INTERFACE: 依赖项仅对链接到当前目标的其他目标可见。
- 示例:
# 将 myutils 库链接到 app 可执行文件 # app 的代码可以直接使用 myutils 中定义的函数 target_link_libraries(app PRIVATE myutils)
管理源文件和头文件
这些命令帮助你更好地组织和管理项目的文件。
1 set()
- 用处: 创建或修改一个 CMake 变量。这是 CMake 中最通用的命令之一,用于存储源文件列表、路径、编译选项等。
- 示例:
# 将一系列源文件存入变量 SRC_FILES set(SRC_FILESmain.cppsrc/player.cppsrc/enemy.cpp )# 使用变量创建可执行文件 add_executable(game ${SRC_FILES})
2 aux_source_directory()
- 用处: 查找指定目录下的所有源文件,并将它们存入一个变量。注意:官方不推荐使用此命令,因为它不会在添加新文件时自动触发 CMake 重新运行,容易导致新文件未被编译。但对于快速原型或简单项目,它仍然很方便。
- 示例:
# 查找 src 目录下的所有源文件并存入 DIR_SRCS 变量 aux_source_directory(src DIR_SRCS)# 将这些源文件添加到可执行文件中 add_executable(app main.cpp ${DIR_SRCS})
3 target_include_directories()
- 用处: 为一个目标指定头文件搜索路径。当你的源文件 #include "my_header.h"时,编译器会到这里指定的目录中去查找。
- 语法: target_include_directories(<目标名> [PUBLIC | PRIVATE | INTERFACE] <路径1> …)
- 示例:
# 为 "app" 添加 "include" 目录作为头文件搜索路径 # 这样在 app 的源文件中就可以 #include "my_header.h" 而不是 #include "include/my_header.h" target_include_directories(app PRIVATE include)
控制编译和链接
这些命令提供了对编译和链接过程的精细控制。
1 target_compile_definitions()
- 用处: 为目标添加预处理器宏定义,等同于在编译命令中添加 -D 选项。
- 示例:
# 为 app 添加 DEBUG=1 和 VERSION="1.0" 两个宏定义 target_compile_definitions(app PRIVATE DEBUG=1 VERSION="1.0")
2 target_compile_options()
- 用处: 为目标添加特定的编译选项,例如警告等级、优化级别或特定的语言标准。
- 示例:
# 为 app 开启所有警告,并使用 C++17 标准进行编译 target_compile_options(app PRIVATE -Wall -Wextra -std=c++17)
3 find_package()
- 用处: 查找并加载外部库的配置。这是使用第三方库(如 Boost, Qt, OpenCV)的标准方式。成功找到后,它会创建一些变量,如 _INCLUDE_DIRS 和 _LIBRARIES,供后续使用。
- 示例:
# 查找 Boost 库的 1.67 或更高版本,并要求必须找到 Components(组件) a aio 和 thread find_package(Boost 1.67 REQUIRED COMPONENTS system thread)# 如果找到了 Boost if(Boost_FOUND)# 添加 Boost 的头文件路径target_include_directories(app PRIVATE ${Boost_INCLUDE_DIRS})# 链接 Boost 的库target_link_libraries(app PRIVATE ${Boost_LIBRARIES}) endif()
流程控制和信息输出
1 if()/elseif()/else()/endif()
- 用处: 提供条件判断逻辑,可以根据不同的平台、编译选项或变量值执行不同的 CMake 命令。
- 示例:
# 根据操作系统设置不同的宏 if(WIN32)target_compile_definitions(app PRIVATE OS_WINDOWS) elseif(APPLE)target_compile_definitions(app PRIVATE OS_MACOS) else()target_compile_definitions(app PRIVATE OS_LINUX) endif()
2 message()
- 用处: 在 CMake 配置阶段向终端输出信息,常用于调试或显示状态信息。
- 模式:
- STATUS: 常规状态信息。
- WARNING: 警告信息。
- FATAL_ERROR: 严重错误,会终止 CMake 的执行。
- 示例:
# 输出 C++ 编译器的路径 message(STATUS "CXX compiler is: ${CMAKE_CXX_COMPILER}")# 如果未找到 Boost,则输出错误并停止 if(NOT Boost_FOUND)message(FATAL_ERROR "Boost library is not found!") endif()
3 add_subdirectory()
- 用处: 添加一个子目录到构建系统中。CMake 会进入该子目录并执行其下的
CMakeLists.txt
文件。这对于组织大型、多模块的项目至关重要。 - 示例:
假设项目结构如下:
顶层 CMakeLists.txt:. ├── CMakeLists.txt ├── main.cpp └── math_lib/├── CMakeLists.txt└── src/└── add.cpp
math_lib/CMakeLists.txt:cmake_minimum_required(VERSION 3.10) project(MainApp CXX)# 添加 math_lib 子目录,CMake会去执行 math_lib/CMakeLists.txt add_subdirectory(math_lib)add_executable(app main.cpp)# 链接子目录中创建的库 target_link_libraries(app PRIVATE math)
# 创建一个名为 "math" 的库 add_library(math src/add.cpp)# 将 "math" 库的头文件目录暴露出去,以便上层目标可以使用 target_include_directories(math PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
希望这份总结能帮助你快速上手 CMake!