活动公告

系统通知
05-18 21:22
系统通知
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,资源失效请在帖子内回复要求补档,会尽快处理!
10-23 09:31

CMake构建规则示例详解与实战应用完全手册 从基础语法到高级配置全面解析CMake构建系统助您成为跨平台开发专家提升项目构建与管理效率解决常见构建问题与性能优化技巧加速开发流程

SunJu_FaceMall

3万

主题

2860

科技点

3万

积分

白金月票

碾压王

积分
32872

塔罗立华奏

<font color=白金月票" /> 发表于 2025-10-1 12:40:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1. 引言:CMake的重要性与跨平台构建概述

CMake是一个开源、跨平台的构建自动化工具,它使用平台无关的配置文件来生成标准的构建文件(如Unix的Makefile或Windows Visual Studio的项目文件)。CMake的出现解决了跨平台开发中的构建问题,使开发者能够用一套配置管理不同平台上的项目构建。

在当今多样化的开发环境中,一个项目可能需要在Windows、Linux、macOS等多个平台上构建,甚至需要针对不同的编译器(如GCC、Clang、MSVC)进行优化。CMake通过抽象这些平台差异,提供了一致的构建体验,大大简化了跨平台项目管理和持续集成流程。

本手册将全面介绍CMake的构建规则,从基础语法到高级配置,通过丰富的示例帮助您掌握CMake的使用技巧,提升项目构建与管理效率,并解决常见的构建问题。

2. CMake基础语法和核心概念

2.1 CMake语言基础

CMake使用自己的脚本语言,具有简单直观的语法。CMake命令不区分大小写,但参数和变量名区分大小写。以下是CMake的基本语法结构:
  1. # 这是一个注释
  2. COMMAND(参数1 参数2 参数3)
复制代码

CMake文件通常以.cmake为扩展名,主要的配置文件名为CMakeLists.txt。

2.2 变量与作用域

在CMake中,变量可以通过set()命令设置:
  1. # 设置变量
  2. set(MY_VARIABLE "value")
  3. # 引用变量
  4. message(STATUS "Variable value: ${MY_VARIABLE}")
复制代码

CMake有自己的作用域规则:

• 函数和宏创建新的作用域
• 变量可以在当前作用域及其子作用域中访问
• 要在父作用域中修改变量,可以使用PARENT_SCOPE选项:
  1. function(set_value)
  2.     set(MY_VAR "new_value" PARENT_SCOPE)
  3. endfunction()
复制代码

2.3 缓存变量

缓存变量是CMake的特有概念,它们存储在CMakeCache.txt文件中,即使重新运行CMake也会保留。设置缓存变量:
  1. set(MY_CACHE_VAR "value" CACHE STRING "Description")
复制代码

缓存变量有几种类型:BOOL、FILEPATH、PATH、STRING、INTERNAL。

2.4 列表处理

CMake中的变量可以视为列表,列表元素用分号分隔:
  1. set(MY_LIST "a" "b" "c")  # 创建包含三个元素的列表
  2. # 列表操作
  3. list(LENGTH MY_LIST len)  # 获取列表长度
  4. list(GET MY_LIST 1 item)  # 获取索引为1的元素
  5. list(APPEND MY_LIST "d")  # 添加元素
  6. list(REMOVE_ITEM MY_LIST "b")  # 移除元素
复制代码

3. CMakeLists.txt的基本结构和常用命令

3.1 基本项目结构

一个基本的CMakeLists.txt文件通常包含以下部分:
  1. # 指定最低CMake版本要求
  2. cmake_minimum_required(VERSION 3.10)
  3. # 项目名称和版本
  4. project(MyProject VERSION 1.0.0 LANGUAGES C CXX)
  5. # 设置C++标准
  6. set(CMAKE_CXX_STANDARD 17)
  7. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  8. # 添加可执行文件
  9. add_executable(my_app main.cpp)
  10. # 链接库
  11. target_link_libraries(my_app PRIVATE some_library)
复制代码

3.2 常用CMake命令

• cmake_minimum_required(): 指定所需的CMake最低版本
• project(): 定义项目名称和版本
• include(): 包含其他CMake文件
• option(): 定义用户可选择的选项
  1. cmake_minimum_required(VERSION 3.10)
  2. project(MyProject VERSION 1.0.0)
  3. option(ENABLE_TESTS "Build tests" ON)
  4. option(ENABLE_EXAMPLES "Build examples" OFF)
复制代码

• set(): 设置变量
• message(): 输出信息
• if(): 条件判断
  1. set(DEBUG_MODE ON)
  2. if(DEBUG_MODE)
  3.     message(STATUS "Debug mode is enabled")
  4. endif()
复制代码

• add_executable(): 添加可执行文件目标
• add_library(): 添加库目标
• add_subdirectory(): 添加子目录
  1. # 添加可执行文件
  2. add_executable(my_app main.cpp helper.cpp)
  3. # 添加静态库
  4. add_library(my_lib STATIC lib_source.cpp)
  5. # 添加子目录
  6. add_subdirectory(src)
  7. add_subdirectory(tests)
复制代码

• set_target_properties(): 设置目标属性
• target_compile_definitions(): 设置目标编译定义
• target_include_directories(): 设置目标包含目录
• target_link_libraries(): 设置目标链接库
  1. # 设置目标属性
  2. set_target_properties(my_app PROPERTIES
  3.     CXX_STANDARD 17
  4.     OUTPUT_NAME "my_app"
  5. )
  6. # 添加编译定义
  7. target_compile_definitions(my_app PRIVATE
  8.     MY_APP_EXPORTS
  9.     DEBUG_MODE=${DEBUG_MODE}
  10. )
  11. # 添加包含目录
  12. target_include_directories(my_app PRIVATE
  13.     ${CMAKE_CURRENT_SOURCE_DIR}/include
  14. )
  15. # 链接库
  16. target_link_libraries(my_app PRIVATE
  17.     pthread
  18.     my_lib
  19. )
复制代码

4. 项目设置和变量管理

4.1 项目版本和配置

在CMake中,可以通过project()命令设置项目的基本信息:
  1. cmake_minimum_required(VERSION 3.10)
  2. # 设置项目名称、版本和语言
  3. project(MyProject
  4.     VERSION 1.2.3
  5.     DESCRIPTION "My awesome project"
  6.     LANGUAGES C CXX
  7. )
  8. # 访问项目变量
  9. message(STATUS "Project name: ${PROJECT_NAME}")
  10. message(STATUS "Project version: ${PROJECT_VERSION}")
  11. message(STATUS "Project version major: ${PROJECT_VERSION_MAJOR}")
  12. message(STATUS "Project version minor: ${PROJECT_VERSION_MINOR}")
  13. message(STATUS "Project version patch: ${PROJECT_VERSION_PATCH}")
复制代码

4.2 构建类型配置

CMake支持多种构建类型,如Debug、Release、RelWithDebInfo和MinSizeRel:
  1. # 设置默认构建类型
  2. if(NOT CMAKE_BUILD_TYPE)
  3.     set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
  4. endif()
  5. # 根据构建类型设置编译选项
  6. set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
  7. set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
  8. set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG")
  9. set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
复制代码

4.3 输出目录配置

可以自定义构建产物的输出目录:
  1. # 设置可执行文件输出目录
  2. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
  3. # 设置库文件输出目录
  4. set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
  5. set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
  6. # 按构建类型设置输出目录
  7. foreach(config DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
  8.     set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config} ${CMAKE_BINARY_DIR}/bin/${config})
  9.     set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${config} ${CMAKE_BINARY_DIR}/lib/${config})
  10.     set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${config} ${CMAKE_BINARY_DIR}/lib/${config})
  11. endforeach()
复制代码

4.4 编译器检测和设置

CMake可以自动检测编译器,并允许进行特定设置:
  1. # 检测编译器
  2. if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  3.     message(STATUS "Using GCC compiler")
  4.     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
  5. elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  6.     message(STATUS "Using Clang compiler")
  7.     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
  8. elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
  9.     message(STATUS "Using MSVC compiler")
  10.     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
  11. endif()
复制代码

5. 查找和处理依赖项

5.1 find_package基础

find_package是CMake中用于查找外部依赖的主要命令。它有两种模式:Module模式和Config模式。
  1. # 查找Boost库(Module模式示例)
  2. find_package(Boost 1.66 REQUIRED COMPONENTS filesystem system)
  3. # 检查是否找到
  4. if(Boost_FOUND)
  5.     message(STATUS "Boost found: ${Boost_VERSION}")
  6.     message(STATUS "Boost include directories: ${Boost_INCLUDE_DIRS}")
  7.     message(STATUS "Boost libraries: ${Boost_LIBRARIES}")
  8. endif()
复制代码

5.2 常见依赖项查找示例
  1. find_package(OpenMP REQUIRED)
  2. if(OpenMP_CXX_FOUND)
  3.     target_link_libraries(my_app PUBLIC OpenMP::OpenMP_CXX)
  4. endif()
复制代码
  1. find_package(Threads REQUIRED)
  2. target_link_libraries(my_app PUBLIC Threads::Threads)
复制代码
  1. find_package(Python COMPONENTS Interpreter Development REQUIRED)
  2. if(Python_FOUND)
  3.     message(STATUS "Python executable: ${Python_EXECUTABLE}")
  4.     message(STATUS "Python include directories: ${Python_INCLUDE_DIRS}")
  5.     message(STATUS "Python libraries: ${Python_LIBRARIES}")
  6. endif()
复制代码

5.3 使用pkg-config查找依赖

对于使用pkg-config的库,可以使用find_package(PkgConfig):
  1. find_package(PkgConfig REQUIRED)
  2. # 查找GTK3
  3. pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
  4. if(GTK3_FOUND)
  5.     message(STATUS "GTK3 include directories: ${GTK3_INCLUDE_DIRS}")
  6.     message(STATUS "GTK3 libraries: ${GTK3_LIBRARIES}")
  7.     message(STATUS "GTK3 CFlags: ${GTK3_CFLAGS_OTHER}")
  8.    
  9.     # 将GTK3添加到目标
  10.     target_include_directories(my_app PUBLIC ${GTK3_INCLUDE_DIRS})
  11.     target_link_libraries(my_app PUBLIC ${GTK3_LIBRARIES})
  12.     target_compile_options(my_app PUBLIC ${GTK3_CFLAGS_OTHER})
  13. endif()
复制代码

5.4 手动查找库

对于没有提供CMake配置文件的库,可以手动查找:
  1. # 查找头文件
  2. find_path(MYLIB_INCLUDE_DIR
  3.     NAMES mylib.h
  4.     PATHS /usr/include /usr/local/include
  5.     PATH_SUFFIXES mylib
  6. )
  7. # 查找库文件
  8. find_library(MYLIB_LIBRARY
  9.     NAMES mylib
  10.     PATHS /usr/lib /usr/local/lib
  11. )
  12. # 检查是否找到
  13. if(MYLIB_INCLUDE_DIR AND MYLIB_LIBRARY)
  14.     set(MYLIB_FOUND TRUE)
  15. else()
  16.     set(MYLIB_FOUND FALSE)
  17. endif()
  18. # 如果找到,添加到目标
  19. if(MYLIB_FOUND)
  20.     target_include_directories(my_app PUBLIC ${MYLIB_INCLUDE_DIR})
  21.     target_link_libraries(my_app PUBLIC ${MYLIB_LIBRARY})
  22. else()
  23.     message(FATAL_ERROR "MyLib not found!")
  24. endif()
复制代码

6. 构建目标和可执行文件/库的配置

6.1 创建可执行文件

创建可执行文件是CMake的基本功能之一:
  1. # 简单可执行文件
  2. add_executable(my_app main.cpp)
  3. # 多个源文件
  4. add_executable(my_app
  5.     main.cpp
  6.     utils.cpp
  7.     network.cpp
  8. )
  9. # 使用glob自动查找源文件(不推荐,原因见下文)
  10. file(GLOB SOURCES "*.cpp")
  11. add_executable(my_app ${SOURCES})
复制代码

注意: 虽然使用file(GLOB)可以自动查找源文件,但不推荐这种方式,因为当添加或删除源文件时,CMake不会自动重新生成构建文件。更好的做法是显式列出所有源文件。

6.2 创建库

CMake支持创建多种类型的库:
  1. # 静态库
  2. add_library(my_lib STATIC
  3.     lib_source1.cpp
  4.     lib_source2.cpp
  5. )
  6. # 共享库
  7. add_library(my_lib SHARED
  8.     lib_source1.cpp
  9.     lib_source2.cpp
  10. )
  11. # 模块库(通常用于插件)
  12. add_library(my_lib MODULE
  13.     plugin_source.cpp
  14. )
  15. # 对象库(只编译,不归档)
  16. add_library(my_lib OBJECT
  17.     obj_source1.cpp
  18.     obj_source2.cpp
  19. )
复制代码

6.3 目标属性配置

使用set_target_properties可以设置目标的属性:
  1. # 设置目标属性
  2. set_target_properties(my_lib PROPERTIES
  3.     # 输出名称
  4.     OUTPUT_NAME "mylib"
  5.    
  6.     # 版本信息(适用于共享库)
  7.     VERSION 1.2.3
  8.     SOVERSION 1
  9.    
  10.     # 位置无关代码(适用于库)
  11.     POSITION_INDEPENDENT_CODE ON
  12.    
  13.     # C++标准
  14.     CXX_STANDARD 17
  15.     CXX_STANDARD_REQUIRED ON
  16.     CXX_EXTENSIONS OFF
  17. )
复制代码

6.4 目标编译选项和定义

使用target_compile_options和target_compile_definitions设置编译选项和定义:
  1. # 添加编译选项
  2. target_compile_options(my_lib PRIVATE
  3.     -Wall
  4.     -Wextra
  5.     $<$<CONFIG:Debug>:-O0 -g>
  6.     $<$<CONFIG:Release>:-O3>
  7. )
  8. # 添加编译定义
  9. target_compile_definitions(my_lib PRIVATE
  10.     MYLIB_EXPORTS
  11.     $<$<CONFIG:Debug>:DEBUG_MODE=1>
  12.     $<$<CONFIG:Release>:NDEBUG>
  13. )
复制代码

6.5 目标包含目录和链接库

使用target_include_directories和target_link_libraries设置包含目录和链接库:
  1. # 添加包含目录
  2. target_include_directories(my_lib
  3.     PUBLIC
  4.         $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  5.         $<INSTALL_INTERFACE:include>
  6.     PRIVATE
  7.         ${CMAKE_CURRENT_SOURCE_DIR}/src
  8. )
  9. # 链接库
  10. target_link_libraries(my_lib
  11.     PUBLIC
  12.         Boost::filesystem
  13.         Threads::Threads
  14.     PRIVATE
  15.         some_internal_lib
  16. )
复制代码

6.6 目标别名和导出

使用add_library创建别名目标,并使用install和export导出目标:
  1. # 创建别名目标
  2. add_library(MyProject::my_lib ALIAS my_lib)
  3. # 安装规则
  4. install(TARGETS my_lib
  5.     EXPORT MyProjectTargets
  6.     LIBRARY DESTINATION lib
  7.     ARCHIVE DESTINATION lib
  8.     RUNTIME DESTINATION bin
  9.     INCLUDES DESTINATION include
  10. )
  11. # 安装头文件
  12. install(DIRECTORY include/ DESTINATION include)
  13. # 导出目标
  14. install(EXPORT MyProjectTargets
  15.     FILE MyProjectTargets.cmake
  16.     NAMESPACE MyProject::
  17.     DESTINATION lib/cmake/MyProject
  18. )
复制代码

7. 条件构建和平台特定配置

7.1 基本条件判断

CMake提供了丰富的条件判断功能:
  1. # 基本条件判断
  2. if(DEFINED MY_VARIABLE)
  3.     message(STATUS "MY_VARIABLE is defined")
  4. endif()
  5. # 比较数值
  6. if(MY_VERSION VERSION_GREATER 1.0)
  7.     message(STATUS "Version is greater than 1.0")
  8. endif()
  9. # 检查变量是否为真
  10. if(ENABLE_FEATURE)
  11.     message(STATUS "Feature is enabled")
  12. endif()
  13. # 检查变量是否为假
  14. if(NOT DISABLE_FEATURE)
  15.     message(STATUS "Feature is not disabled")
  16. endif()
  17. # 逻辑组合
  18. if(ENABLE_FEATURE AND (MY_VERSION VERSION_GREATER 1.0 OR FORCE_ENABLE))
  19.     message(STATUS "Feature is enabled and conditions are met")
  20. endif()
复制代码

7.2 平台特定配置

CMake可以检测运行平台,并根据平台进行特定配置:
  1. # 检测操作系统
  2. if(WIN32)
  3.     message(STATUS "Building for Windows")
  4.     add_definitions(-DPLATFORM_WINDOWS)
  5. elseif(UNIX AND NOT APPLE)
  6.     message(STATUS "Building for Linux")
  7.     add_definitions(-DPLATFORM_LINUX)
  8. elseif(APPLE)
  9.     message(STATUS "Building for macOS")
  10.     add_definitions(-DPLATFORM_MACOS)
  11. endif()
  12. # 检测处理器架构
  13. if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
  14.     message(STATUS "Building for 64-bit x86")
  15. elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i386|i686|x86")
  16.     message(STATUS "Building for 32-bit x86")
  17. elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64")
  18.     message(STATUS "Building for ARM64")
  19. endif()
  20. # 检测编译器
  21. if(MSVC)
  22.     message(STATUS "Using MSVC compiler")
  23.     add_compile_options(/W4)
  24. elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
  25.     message(STATUS "Using GCC or Clang compiler")
  26.     add_compile_options(-Wall -Wextra)
  27. endif()
复制代码

7.3 生成器表达式

生成器表达式是CMake的强大功能,可以在生成构建系统时进行条件判断:
  1. # 基于配置的生成器表达式
  2. target_compile_definitions(my_app PRIVATE
  3.     $<$<CONFIG:Debug>:DEBUG_MODE=1>
  4.     $<$<CONFIG:Release>:NDEBUG>
  5. )
  6. # 基于平台的生成器表达式
  7. target_link_libraries(my_app PRIVATE
  8.     $<$<PLATFORM_ID:Windows>:winmm.lib>
  9.     $<$<PLATFORM_ID:Linux>:pthread>
  10. )
  11. # 基于编译器特性的生成器表达式
  12. target_compile_options(my_app PRIVATE
  13.     $<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra>
  14.     $<$<CXX_COMPILER_ID:MSVC>:/W4>
  15. )
  16. # 基于语言特性的生成器表达式
  17. target_compile_features(my_app PRIVATE
  18.     $<$<C_COMPILER_ID:GNU>:c_std_11>
  19.     $<$<CXX_COMPILER_ID:GNU>:cxx_std_17>
  20. )
复制代码

7.4 条件包含源文件

可以根据条件选择性地包含源文件:
  1. # 基本条件包含
  2. set(SOURCES
  3.     main.cpp
  4.     utils.cpp
  5. )
  6. if(ENABLE_NETWORKING)
  7.     list(APPEND SOURCES network.cpp)
  8. endif()
  9. if(ENABLE_GUI)
  10.     list(APPEND SOURCES gui.cpp)
  11. endif()
  12. add_executable(my_app ${SOURCES})
复制代码

7.5 使用配置文件

CMake可以使用.in模板文件生成配置文件:
  1. # 配置模板文件 (config.h.in)
  2. #cmakedefine ENABLE_FEATURE
  3. #cmakedefine VERSION "@VERSION@"
  4. #cmakedefine INSTALL_PATH "@INSTALL_PATH@"
  5. # 在CMakeLists.txt中配置
  6. configure_file(
  7.     ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
  8.     ${CMAKE_CURRENT_BINARY_DIR}/config.h
  9. )
  10. # 将生成的目录添加到包含路径
  11. target_include_directories(my_app PRIVATE
  12.     ${CMAKE_CURRENT_BINARY_DIR}
  13. )
复制代码

8. 测试和安装配置

8.1 使用CTest进行测试

CMake集成了CTest测试框架,可以轻松添加和管理测试:
  1. # 启用测试
  2. enable_testing()
  3. # 添加简单测试
  4. add_executable(test_basic test_basic.cpp)
  5. target_link_libraries(test_basic PRIVATE my_lib)
  6. add_test(NAME BasicTest COMMAND test_basic)
  7. # 添加带参数的测试
  8. add_test(NAME AdvancedTest COMMAND test_advanced --verbose --timeout=60)
  9. # 设置测试属性
  10. set_tests_properties(AdvancedTest PROPERTIES
  11.     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
  12.     TIMEOUT 30
  13. )
  14. # 添加需要先构建的测试
  15. add_test(NAME FeatureTest COMMAND test_feature)
  16. add_dependencies(FeatureTest my_lib)
复制代码

8.2 测试套件和 fixtures

CTest支持测试套件和fixtures,可以组织复杂的测试场景:
  1. # 定义测试套件
  2. set_tests_properties(BasicTest AdvancedTest PROPERTIES
  3.     LABELS "unit"
  4. )
  5. set_tests_properties(IntegrationTest PROPERTIES
  6.     LABELS "integration"
  7. )
  8. # 定义fixtures
  9. set_tests_PROPERTIES(SetupTest PROPERTIES
  10.     FIXTURES_SETUP "MyFixture"
  11. )
  12. set_tests_PROPERTIES(TearDownTest PROPERTIES
  13.     FIXTURES_CLEANUP "MyFixture"
  14. )
  15. set_tests_PROPERTIES(FeatureTest1 FeatureTest2 PROPERTIES
  16.     FIXTURES_REQUIRED "MyFixture"
  17. )
复制代码

8.3 基本安装规则

使用install命令可以定义安装规则:
  1. # 安装目标
  2. install(TARGETS my_lib my_app
  3.     # 导出目标
  4.     EXPORT MyProjectTargets
  5.    
  6.     # 运行时文件(可执行文件、DLL)
  7.     RUNTIME DESTINATION bin
  8.    
  9.     # 库文件
  10.     LIBRARY DESTINATION lib
  11.    
  12.     # 静态库和导入库
  13.     ARCHIVE DESTINATION lib
  14.    
  15.     # 包含目录
  16.     INCLUDES DESTINATION include
  17. )
  18. # 安装头文件
  19. install(DIRECTORY include/ DESTINATION include)
  20. # 安装配置文件
  21. install(FILES config.h DESTINATION include)
  22. # 安装其他文件
  23. install(FILES README.md DESTINATION doc)
  24. install(PROGRAMS scripts/run.sh DESTINATION bin)
复制代码

8.4 组件安装

CMake支持将安装内容分组为组件:
  1. # 定义组件
  2. install(TARGETS my_lib
  3.     EXPORT MyProjectTargets
  4.     LIBRARY DESTINATION lib
  5.     ARCHIVE DESTINATION lib
  6.     COMPONENT Development
  7. )
  8. install(TARGETS my_app
  9.     RUNTIME DESTINATION bin
  10.     COMPONENT Runtime
  11. )
  12. install(DIRECTORY include/ DESTINATION include
  13.     COMPONENT Development
  14. )
  15. install(FILES README.md DESTINATION doc
  16.     COMPONENT Documentation
  17. )
  18. # 设置默认组件
  19. set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Runtime)
复制代码

8.5 打包支持

CMake支持创建二进制包和源码包:
  1. # 设置包信息
  2. set(CPACK_PACKAGE_NAME "MyProject")
  3. set(CPACK_PACKAGE_VERSION "1.2.3")
  4. set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "My awesome project")
  5. set(CPACK_PACKAGE_VENDOR "My Company")
  6. # 设置包生成器
  7. if(WIN32)
  8.     set(CPACK_GENERATOR "NSIS;ZIP")
  9. elseif(APPLE)
  10.     set(CPACK_GENERATOR "DragNDrop;TGZ")
  11. else()
  12.     set(CPACK_GENERATOR "DEB;RPM;TGZ")
  13. endif()
  14. # 包含CPack
  15. include(CPack)
复制代码

9. 高级CMake技术

9.1 函数和宏

CMake支持定义函数和宏,以实现代码复用:
  1. # 定义函数
  2. function(add_my_target TARGET_NAME)
  3.     # 参数解析
  4.     set(options DEBUG)
  5.     set(oneValueArgs VERSION)
  6.     set(multiValueArgs SOURCES LIBRARIES)
  7.     cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  8.    
  9.     # 创建目标
  10.     add_executable(${TARGET_NAME} ${ARG_SOURCES})
  11.    
  12.     # 设置属性
  13.     if(ARG_DEBUG)
  14.         target_compile_definitions(${TARGET_NAME} PRIVATE DEBUG_MODE)
  15.     endif()
  16.    
  17.     if(DEFINED ARG_VERSION)
  18.         set_target_properties(${TARGET_NAME} PROPERTIES VERSION ${ARG_VERSION})
  19.     endif()
  20.    
  21.     # 链接库
  22.     target_link_libraries(${TARGET_NAME} PRIVATE ${ARG_LIBRARIES})
  23. endfunction()
  24. # 使用函数
  25. add_my_target(my_app
  26.     SOURCES main.cpp utils.cpp
  27.     LIBRARIES my_lib
  28.     DEBUG
  29.     VERSION 1.0
  30. )
  31. # 定义宏(宏不创建新作用域)
  32. macro(print_list LIST_NAME)
  33.     message(STATUS "List ${LIST_NAME}:")
  34.     foreach(item IN LISTS ${LIST_NAME})
  35.         message(STATUS "  - ${item}")
  36.     endforeach()
  37. endmacro()
  38. # 使用宏
  39. set(MY_LIST a b c)
  40. print_list(MY_LIST)
复制代码

9.2 自定义模块

可以创建自定义模块来扩展CMake功能:
  1. # 文件: FindMyLib.cmake
  2. # 查找MyLib库
  3. # 查找头文件
  4. find_path(MYLIB_INCLUDE_DIR
  5.     NAMES mylib.h
  6.     PATHS /usr/include /usr/local/include
  7.     PATH_SUFFIXES mylib
  8. )
  9. # 查找库文件
  10. find_library(MYLIB_LIBRARY
  11.     NAMES mylib
  12.     PATHS /usr/lib /usr/local/lib
  13. )
  14. # 检查是否找到
  15. include(FindPackageHandleStandardArgs)
  16. find_package_handle_standard_args(MyLib
  17.     DEFAULT_MSG
  18.     MYLIB_INCLUDE_DIR
  19.     MYLIB_LIBRARY
  20. )
  21. # 如果找到,设置变量
  22. if(MYLIB_FOUND)
  23.     set(MYLIB_INCLUDE_DIRS ${MYLIB_INCLUDE_DIR})
  24.     set(MYLIB_LIBRARIES ${MYLIB_LIBRARY})
  25.    
  26.     # 如果不是在构建树中,创建导入目标
  27.     if(NOT TARGET MyLib::MyLib)
  28.         add_library(MyLib::MyLib UNKNOWN IMPORTED)
  29.         set_target_properties(MyLib::MyLib PROPERTIES
  30.             INTERFACE_INCLUDE_DIRECTORIES "${MYLIB_INCLUDE_DIRS}"
  31.             IMPORTED_LOCATION "${MYLIB_LIBRARIES}"
  32.         )
  33.     endif()
  34. endif()
  35. # 隐藏内部变量
  36. mark_as_advanced(
  37.     MYLIB_INCLUDE_DIR
  38.     MYLIB_LIBRARY
  39. )
复制代码

9.3 配置文件包

创建配置文件包使其他项目可以轻松使用你的库:
  1. # 文件: MyProjectConfig.cmake.in
  2. @PACKAGE_INIT@
  3. # 包含依赖项
  4. include(CMakeFindDependencyMacro)
  5. find_dependency(Boost 1.66 REQUIRED COMPONENTS filesystem system)
  6. find_dependency(Threads REQUIRED)
  7. # 包含目标
  8. include("${CMAKE_CURRENT_LIST_DIR}/MyProjectTargets.cmake")
  9. # 检查兼容性
  10. check_required_components(MyProject)
复制代码

然后在CMakeLists.txt中:
  1. # 生成配置文件
  2. include(CMakePackageConfigHelpers)
  3. # 生成版本文件
  4. write_basic_package_version_file(
  5.     "${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfigVersion.cmake"
  6.     VERSION ${PROJECT_VERSION}
  7.     COMPATIBILITY AnyNewerVersion
  8. )
  9. # 安装配置文件
  10. install(FILES
  11.     "${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfig.cmake"
  12.     "${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfigVersion.cmake"
  13.     DESTINATION lib/cmake/MyProject
  14. )
复制代码

9.4 自定义命令和目标

使用add_custom_command和add_custom_target可以创建自定义构建步骤:
  1. # 自定义命令(生成源文件)
  2. add_custom_command(
  3.     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp
  4.     COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/generator.py
  5.         -i ${CMAKE_CURRENT_SOURCE_DIR}/data/input.json
  6.         -o ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp
  7.     DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generator.py
  8.             ${CMAKE_CURRENT_SOURCE_DIR}/data/input.json
  9.     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
  10.     COMMENT "Generating source code"
  11. )
  12. # 使用生成的源文件
  13. add_library(generated_lib ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp)
  14. # 自定义目标(运行测试)
  15. add_custom_target(run_tests
  16.     COMMAND ${CMAKE_CTEST_COMMAND} --verbose
  17.     DEPENDS my_app test_basic
  18.     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
  19. )
  20. # 自定义目标(生成文档)
  21. find_package(Doxygen REQUIRED)
  22. add_custom_target(docs
  23.     COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile
  24.     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
  25.     COMMENT "Generating API documentation with Doxygen"
  26.     VERBATIM
  27. )
复制代码

9.5 工具链文件

工具链文件用于交叉编译或指定特定的编译器环境:
  1. # 文件: toolchain.cmake
  2. # 设置目标系统
  3. set(CMAKE_SYSTEM_NAME Linux)
  4. set(CMAKE_SYSTEM_PROCESSOR arm)
  5. # 设置编译器
  6. set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
  7. set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
  8. # 设置查找路径
  9. set(CMAKE_FIND_ROOT_PATH /usr/arm-linux-gnueabihf)
  10. # 设置查找行为
  11. set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
  12. set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
  13. set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
  14. set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
复制代码

使用工具链文件:
  1. cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake /path/to/source
复制代码

10. 性能优化技巧

10.1 减少配置时间

大型项目的CMake配置可能会很慢,以下是一些优化技巧:
  1. # 使用CMake的预编译头文件支持
  2. if(MSVC)
  3.     target_precompile_headers(my_app PRIVATE
  4.         stdafx.h
  5.     )
  6. elseif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  7.     target_precompile_headers(my_app PRIVATE
  8.         stdafx.h
  9.     )
  10. endif()
  11. # 避免不必要的重新配置
  12. set(CMAKE_SUPPRESS_REGENERATION FALSE)
  13. # 使用CMake的依赖关系跟踪
  14. set(CMAKE_DEPENDS_USE_COMPILER TRUE)
复制代码

10.2 并行构建

CMake支持并行构建,可以显著提高构建速度:
  1. # 设置默认并行构建数
  2. if(NOT CMAKE_BUILD_PARALLEL_LEVEL)
  3.     # 设置为CPU核心数
  4.     include(ProcessorCount)
  5.     ProcessorCount(N)
  6.     if(NOT N EQUAL 0)
  7.         set(CMAKE_BUILD_PARALLEL_LEVEL ${N})
  8.     endif()
  9. endif()
  10. # 使用Ninja生成器(通常比Make更快)
  11. if(NOT CMAKE_GENERATOR MATCHES "Ninja")
  12.     find_program(NINJA ninja)
  13.     if(NINJA)
  14.         set(CMAKE_GENERATOR "Ninja" CACHE INTERNAL "")
  15.     endif()
  16. endif()
复制代码

10.3 优化依赖查找

优化依赖查找可以减少配置时间:
  1. # 缓存查找结果
  2. set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
  3. # 限制查找路径
  4. set(CMAKE_SYSTEM_PREFIX_PATH
  5.     /usr
  6.     /usr/local
  7.     $ENV{HOME}/.local
  8. )
  9. # 使用CMAKE_PREFIX_PATH指定特定路径
  10. list(APPEND CMAKE_PREFIX_PATH /path/to/custom/install)
复制代码

10.4 减少目标依赖

减少目标之间的依赖关系可以提高并行构建效率:
  1. # 使用PRIVATE而不是PUBLIC/INTERFACE,除非必要
  2. target_link_libraries(my_lib PRIVATE
  3.     some_internal_lib
  4. )
  5. # 使用OBJECT库避免重复编译
  6. add_library(common_objs OBJECT
  7.     common1.cpp
  8.     common2.cpp
  9. )
  10. add_library(lib1 STATIC
  11.     lib1.cpp
  12.     $<TARGET_OBJECTS:common_objs>
  13. )
  14. add_library(lib2 STATIC
  15.     lib2.cpp
  16.     $<TARGET_OBJECTS:common_objs>
  17. )
复制代码

10.5 使用Unity构建

Unity构建(也称为Jumbo构建)可以减少编译时间,特别是对于有许多小文件的项目:
  1. # 启用Unity构建
  2. set(CMAKE_UNITY_BUILD ON)
  3. set(CMAKE_UNITY_BUILD_BATCH_SIZE 10)
  4. # 为特定目标启用Unity构建
  5. set_target_properties(my_lib PROPERTIES
  6.     UNITY_BUILD ON
  7.     UNITY_BUILD_BATCH_SIZE 8
  8. )
复制代码

11. 常见问题及解决方案

11.1 处理不同平台的路径问题

不同平台使用不同的路径分隔符和大小写规则:
  1. # 使用CMake的路径处理函数
  2. file(TO_CMAKE_PATH "$ENV{PATH}" NATIVE_PATH)
  3. file(TO_NATIVE_PATH "/usr/local/bin" UNIX_PATH)
  4. # 使用file(GLOB)时注意大小写
  5. if(WIN32)
  6.     file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.hpp")
  7. else()
  8.     file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.hpp")
  9.     file(GLOB_RECURSE HEADERS "src/*.h" "src/*.hpp")
  10. endif()
复制代码

11.2 处理不同平台的库文件扩展名

不同平台使用不同的库文件扩展名:
  1. # 使用CMake的变量处理不同平台的库扩展名
  2. if(WIN32)
  3.     set(LIB_EXT ".lib")
  4.     set(DLL_EXT ".dll")
  5. elseif(APPLE)
  6.     set(LIB_EXT ".a")
  7.     set(DLL_EXT ".dylib")
  8. else()
  9.     set(LIB_EXT ".a")
  10.     set(DLL_EXT ".so")
  11. endif()
  12. # 使用生成器表达式处理平台差异
  13. target_link_libraries(my_app PRIVATE
  14.     $<$<PLATFORM_ID:Windows>:mylib${LIB_EXT}>
  15.     $<$<PLATFORM_ID:Linux,Apple>:mylib${DLL_EXT}>
  16. )
复制代码

11.3 处理不同平台的编译标志

不同编译器使用不同的编译标志:
  1. # 使用CMake的编译器变量
  2. if(MSVC)
  3.     add_compile_options(/W4 /WX)
  4. else()
  5.     add_compile_options(-Wall -Wextra -Werror)
  6. endif()
  7. # 使用生成器表达式处理编译器差异
  8. target_compile_options(my_app PRIVATE
  9.     $<$<CXX_COMPILER_ID:MSVC>:/W4>
  10.     $<$<CXX_COMPILER_ID:GNU,Clang>:-Wall -Wextra>
  11. )
复制代码

11.4 处理静态链接与动态链接

处理不同平台的链接方式:
  1. # 静态链接C++标准库
  2. if(MSVC)
  3.     set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
  4. else()
  5.     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++")
  6. endif()
  7. # 控制库的可见性
  8. set(CMAKE_CXX_VISIBILITY_PRESET hidden)
  9. set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
复制代码

11.5 处理依赖冲突

处理不同版本的依赖冲突:
  1. # 使用别名避免冲突
  2. add_library(myproject::boost ALIAS Boost::boost)
  3. # 使用命名空间隔离
  4. add_library(myproject::sqlite3 ALIAS sqlite3)
  5. # 使用INTERFACE库定义公共接口
  6. add_library(myproject_common INTERFACE)
  7. target_include_directories(myproject_common INTERFACE
  8.     $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  9.     $<INSTALL_INTERFACE:include>
  10. )
  11. target_compile_features(myproject_common INTERFACE cxx_std_17)
复制代码

12. 实战案例:使用CMake构建一个跨平台项目

12.1 项目结构

假设我们有一个跨平台的C++项目,结构如下:
  1. myproject/
  2. ├── CMakeLists.txt
  3. ├── include/
  4. │   └── myproject/
  5. │       ├── common.h
  6. │       ├── network.h
  7. │       └── utils.h
  8. ├── src/
  9. │   ├── common.cpp
  10. │   ├── network.cpp
  11. │   ├── utils.cpp
  12. │   └── main.cpp
  13. ├── tests/
  14. │   ├── CMakeLists.txt
  15. │   ├── test_common.cpp
  16. │   └── test_network.cpp
  17. ├── examples/
  18. │   ├── CMakeLists.txt
  19. │   └── simple_example.cpp
  20. ├── docs/
  21. │   └── Doxyfile
  22. ├── cmake/
  23. │   └── FindSomeLib.cmake
  24. └── README.md
复制代码

12.2 主CMakeLists.txt
  1. # 指定最低CMake版本要求
  2. cmake_minimum_required(VERSION 3.15)
  3. # 项目名称和版本
  4. project(MyProject
  5.     VERSION 1.0.0
  6.     DESCRIPTION "A cross-platform C++ project"
  7.     LANGUAGES C CXX
  8. )
  9. # 设置C++标准
  10. set(CMAKE_CXX_STANDARD 17)
  11. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  12. set(CMAKE_CXX_EXTENSIONS OFF)
  13. # 设置输出目录
  14. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
  15. set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
  16. set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
  17. # 添加编译选项
  18. if(MSVC)
  19.     add_compile_options(/W4)
  20. else()
  21.     add_compile_options(-Wall -Wextra)
  22. endif()
  23. # 查找依赖项
  24. find_package(Threads REQUIRED)
  25. find_package(Boost 1.66 REQUIRED COMPONENTS filesystem system)
  26. # 添加子目录
  27. add_subdirectory(src)
  28. add_subdirectory(tests)
  29. add_subdirectory(examples)
  30. # 配置文件
  31. configure_file(
  32.     ${CMAKE_CURRENT_SOURCE_DIR}/include/myproject/config.h.in
  33.     ${CMAKE_CURRENT_BINARY_DIR}/include/myproject/config.h
  34. )
  35. # 安装规则
  36. install(DIRECTORY include/ DESTINATION include)
  37. install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ DESTINATION include)
  38. install(FILES README.md DESTINATION doc)
  39. # 打包支持
  40. include(CPack)
复制代码

12.3 src/CMakeLists.txt
  1. # 创建库
  2. add_library(myproject_lib
  3.     common.cpp
  4.     network.cpp
  5.     utils.cpp
  6. )
  7. # 设置目标属性
  8. set_target_properties(myproject_lib PROPERTIES
  9.     VERSION ${PROJECT_VERSION}
  10.     SOVERSION 1
  11.     PUBLIC_HEADER "include/myproject/common.h;include/myproject/network.h;include/myproject/utils.h"
  12. )
  13. # 添加包含目录
  14. target_include_directories(myproject_lib
  15.     PUBLIC
  16.         $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
  17.         $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
  18.         $<INSTALL_INTERFACE:include>
  19.     PRIVATE
  20.         ${CMAKE_CURRENT_SOURCE_DIR}
  21. )
  22. # 添加编译定义
  23. target_compile_definitions(myproject_lib PRIVATE
  24.     $<$<CONFIG:Debug>:DEBUG_MODE=1>
  25.     $<$<CONFIG:Release>:NDEBUG>
  26. )
  27. # 链接库
  28. target_link_libraries(myproject_lib
  29.     PUBLIC
  30.         Boost::filesystem
  31.         Boost::system
  32.         Threads::Threads
  33. )
  34. # 创建可执行文件
  35. add_executable(myproject_app main.cpp)
  36. # 链接库
  37. target_link_libraries(myproject_app PRIVATE myproject_lib)
  38. # 安装规则
  39. install(TARGETS myproject_lib myproject_app
  40.     EXPORT MyProjectTargets
  41.     RUNTIME DESTINATION bin
  42.     LIBRARY DESTINATION lib
  43.     ARCHIVE DESTINATION lib
  44.     PUBLIC_HEADER DESTINATION include
  45. )
复制代码

12.4 tests/CMakeLists.txt
  1. # 启用测试
  2. enable_testing()
  3. # 添加测试可执行文件
  4. add_executable(test_common test_common.cpp)
  5. target_link_libraries(test_common PRIVATE myproject_lib)
  6. add_executable(test_network test_network.cpp)
  7. target_link_libraries(test_network PRIVATE myproject_lib)
  8. # 添加测试
  9. add_test(NAME CommonTest COMMAND test_common)
  10. add_test(NAME NetworkTest COMMAND test_network)
  11. # 设置测试属性
  12. set_tests_PROPERTIES(NetworkTest PROPERTIES
  13.     TIMEOUT 30
  14. )
复制代码

12.5 examples/CMakeLists.txt
  1. # 添加示例可执行文件
  2. add_executable(simple_example simple_example.cpp)
  3. target_link_libraries(simple_example PRIVATE myproject_lib)
  4. # 安装示例
  5. install(TARGETS simple_example
  6.     RUNTIME DESTINATION bin/examples
  7. )
复制代码

12.6 使用CMake构建项目
  1. # 创建构建目录
  2. mkdir build && cd build
  3. # 配置项目
  4. cmake ..
  5. # 构建
  6. cmake --build .
  7. # 运行测试
  8. ctest --output-on-failure
  9. # 安装
  10. cmake --install . --prefix /usr/local
  11. # 创建包
  12. cpack -G TGZ
复制代码
  1. # 创建构建目录
  2. mkdir build
  3. cd build
  4. # 配置项目(使用Visual Studio 2019)
  5. cmake -G "Visual Studio 16 2019" ..
  6. # 构建
  7. cmake --build . --config Release
  8. # 运行测试
  9. ctest -C Release --output-on-failure
  10. # 安装
  11. cmake --install . --prefix C:/MyProject
  12. # 创建包
  13. cpack -G ZIP -C Release
复制代码

12.7 高级配置示例
  1. # 在主CMakeLists.txt中添加选项
  2. option(ENABLE_TESTS "Build tests" ON)
  3. option(ENABLE_EXAMPLES "Build examples" ON)
  4. option(ENABLE_PROFILING "Enable profiling support" OFF)
  5. # 根据选项添加子目录
  6. if(ENABLE_TESTS)
  7.     add_subdirectory(tests)
  8. endif()
  9. if(ENABLE_EXAMPLES)
  10.     add_subdirectory(examples)
  11. endif()
  12. # 根据选项添加编译定义
  13. if(ENABLE_PROFILING)
  14.     add_compile_definitions(ENABLE_PROFILING=1)
  15.     if(MSVC)
  16.         add_compile_options(/PROFILE)
  17.     else()
  18.         add_compile_options(-pg)
  19.     endif()
  20. endif()
复制代码
  1. # 在src/CMakeLists.txt中添加自定义命令
  2. find_package(Python3 REQUIRED)
  3. # 生成源文件
  4. add_custom_command(
  5.     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated_code.cpp
  6.     COMMAND Python3::Interpreter
  7.         ${CMAKE_CURRENT_SOURCE_DIR}/../tools/generate_code.py
  8.         --input ${CMAKE_CURRENT_SOURCE_DIR}/../data/code_spec.json
  9.         --output ${CMAKE_CURRENT_BINARY_DIR}/generated_code.cpp
  10.     DEPENDS
  11.         ${CMAKE_CURRENT_SOURCE_DIR}/../tools/generate_code.py
  12.         ${CMAKE_CURRENT_SOURCE_DIR}/../data/code_spec.json
  13.     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
  14.     COMMENT "Generating source code"
  15. )
  16. # 将生成的源文件添加到库
  17. target_sources(myproject_lib
  18.     PRIVATE
  19.         ${CMAKE_CURRENT_BINARY_DIR}/generated_code.cpp
  20. )
复制代码
  1. # 在主CMakeLists.txt中添加文档生成
  2. find_package(Doxygen)
  3. if(Doxygen_FOUND)
  4.     # 设置Doxygen配置文件
  5.     set(DOXYGEN_INPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
  6.     set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/docs)
  7.     set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/html/index.html)
  8.    
  9.     # 配置Doxygen
  10.     configure_file(
  11.         ${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in
  12.         ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
  13.         @ONLY
  14.     )
  15.    
  16.     # 添加自定义目标生成文档
  17.     add_custom_target(docs ALL
  18.         COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
  19.         WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
  20.         COMMENT "Generating API documentation with Doxygen"
  21.         VERBATIM
  22.     )
  23.    
  24.     # 安装文档
  25.     install(DIRECTORY ${DOXYGEN_OUTPUT_DIR}/html
  26.         DESTINATION doc
  27.         OPTIONAL
  28.     )
  29. endif()
复制代码

13. 总结

本手册全面介绍了CMake构建系统的各个方面,从基础语法到高级配置,通过丰富的示例帮助您掌握CMake的使用技巧。我们学习了:

1. CMake的基础语法和核心概念
2. CMakeLists.txt的基本结构和常用命令
3. 项目设置和变量管理
4. 查找和处理依赖项
5. 构建目标和可执行文件/库的配置
6. 条件构建和平台特定配置
7. 测试和安装配置
8. 高级CMake技术,如函数、宏、自定义模块等
9. 性能优化技巧
10. 常见问题及解决方案
11. 实战案例:使用CMake构建一个跨平台项目

通过掌握这些知识,您可以有效地使用CMake管理跨平台项目,提高构建效率,并解决常见的构建问题。CMake是一个强大而灵活的工具,随着您对其理解的深入,您将能够更加高效地利用它来管理复杂的项目构建过程。

希望本手册能够帮助您成为CMake专家,并在您的开发工作中发挥重要作用。如果您有任何问题或需要进一步的帮助,请参考CMake官方文档或社区资源。
「七転び八起き(ななころびやおき)」
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则