强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

第 11 章:安装与打包

第 11 章:安装与打包

11.1 install 命令概览

install() 是 CMake 中用于定义安装规则的命令。

# 执行安装
cmake --install build
cmake --install build --prefix /opt/myapp
cmake --install build --config Release
cmake --install build --component dev

11.2 安装目标

11.2.1 基本目标安装

add_executable(myapp main.cpp)
add_library(mylib STATIC src/mylib.cpp)
add_library(mylib_shared SHARED src/mylib.cpp)

# 安装目标
install(TARGETS myapp mylib mylib_shared
    RUNTIME DESTINATION bin          # 可执行文件 (.exe, .dll)
    LIBRARY DESTINATION lib          # 共享库 (.so, .dylib)
    ARCHIVE DESTINATION lib          # 静态库 (.a, .lib)
    OBJECTS DESTINATION lib          # 对象文件
    INCLUDES DESTINATION include     # 头文件目录
)

11.2.2 安装目录对照表

目标类型目标关键字默认安装目录
可执行文件RUNTIMEbin
动态库(非 macOS)LIBRARYlib
动态库(macOS)LIBRARYlib
Windows DLLRUNTIME(.dll)+ ARCHIVE(.lib)bin + lib
静态库ARCHIVElib
对象库OBJECTSlib
头文件集FILE_SET HEADERSinclude

11.2.3 完整的安装示例

install(TARGETS myapp mylib
    EXPORT MyProjectTargets

    # 可执行文件
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}

    # 共享库
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT Runtime
        NAMELINK_COMPONENT Development

    # 静态库
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT Development

    # 头文件
    INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

💡 提示CMAKE_INSTALL_BINDIR 等变量来自 GNUInstallDirs 模块。

11.3 安装文件和目录

11.3.1 安装头文件

# 安装特定文件
install(FILES
    include/mylib/core.h
    include/mylib/utils.h
    include/mylib/types.h
    DESTINATION include/mylib
    COMPONENT Development
)

# 安装目录
install(DIRECTORY include/
    DESTINATION include
    COMPONENT Development
    FILES_MATCHING
    PATTERN "*.h"
    PATTERN "*.hpp"
    PATTERN "*.inc"
    PATTERN ".git" EXCLUDE
)

11.3.2 安装程序和脚本

# 安装为可执行文件
install(PROGRAMS
    scripts/deploy.sh
    scripts/configure.py
    DESTINATION bin
    COMPONENT Runtime
)

# 安装任意文件
install(FILES
    config/myapp.conf
    config/logging.conf
    DESTINATION etc/myapp
    COMPONENT Configuration
)

11.3.3 安装目录内容

# 安装整个目录
install(DIRECTORY data/
    DESTINATION share/myapp/data
    USE_SOURCE_PERMISSIONS
    PATTERN "*.txt"
    PATTERN "internal" EXCLUDE
)

11.3.4 安装类型汇总

命令安装内容用途
install(TARGETS ...)构建目标库和可执行文件
install(FILES ...)文件头文件、配置文件
install(PROGRAMS ...)可执行脚本脚本、工具
install(DIRECTORY ...)目录数据目录、资源
install(EXPORT ...)导出集CMake 包配置
install(IMPORTED_RUNTIME_ARTIFACTS ...)导入目标产物外部二进制

11.4 GNUInstallDirs

include(GNUInstallDirs)

# 标准安装目录变量
message("可执行文件: ${CMAKE_INSTALL_BINDIR}")        # bin
message("库文件: ${CMAKE_INSTALL_LIBDIR}")            # lib 或 lib64
message("头文件: ${CMAKE_INSTALL_INCLUDEDIR}")         # include
message("数据: ${CMAKE_INSTALL_DATADIR}")             # share
message("配置: ${CMAKE_INSTALL_SYSCONFDIR}")          # etc
message("手册: ${CMAKE_INSTALL_MANDIR}")              # share/man
变量默认值说明
CMAKE_INSTALL_BINDIRbin用户可执行文件
CMAKE_INSTALL_SBINDIRsbin系统管理可执行文件
CMAKE_INSTALL_LIBDIRliblib64库文件
CMAKE_INSTALL_INCLUDEDIRinclude头文件
CMAKE_INSTALL_DATADIRshare架构无关数据
CMAKE_INSTALL_SYSCONFDIRetc配置文件
CMAKE_INSTALL_LOCALSTATEDIRvar可变数据

11.5 导出与包配置

11.5.1 创建导出集

# 安装目标并导出
install(TARGETS mylib myapp
    EXPORT MyProjectTargets
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

# 安装导出文件
install(EXPORT MyProjectTargets
    FILE MyProjectTargets.cmake
    NAMESPACE MyProject::
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyProject
)

11.5.2 生成配置文件

include(CMakePackageConfigHelpers)

# 配置文件模板
configure_package_config_file(
    cmake/MyProjectConfig.cmake.in
    ${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfig.cmake
    INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyProject
)

# 版本文件
write_basic_package_version_file(
    ${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfigVersion.cmake
    VERSION ${PROJECT_VERSION}
    COMPATIBILITY SameMajorVersion
)

# 安装配置文件
install(FILES
    ${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfig.cmake
    ${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfigVersion.cmake
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyProject
)

11.5.3 配置模板文件

# cmake/MyProjectConfig.cmake.in
@PACKAGE_INIT@

include(CMakeFindDependencyMacro)

# 声明依赖
find_dependency(Threads)
if(@MYPROJECT_USE_OPENSSL@)
    find_dependency(OpenSSL)
endif()

# 包含目标
include("${CMAKE_CURRENT_LIST_DIR}/MyProjectTargets.cmake")

check_required_components(MyProject)

11.5.4 安装后使用

# 下游项目
find_package(MyProject REQUIRED)

add_executable(app main.cpp)
target_link_libraries(app PRIVATE MyProject::mylib)

11.6 组件安装

11.6.1 定义组件

install(TARGETS mylib
    EXPORT MyProjectTargets
    ARCHIVE DESTINATION lib
        COMPONENT Development
    LIBRARY DESTINATION lib
        COMPONENT Runtime
        NAMELINK_COMPONENT Development
)

install(DIRECTORY include/
    DESTINATION include
    COMPONENT Development
)

install(FILES config/default.conf
    DESTINATION etc/myapp
    COMPONENT Configuration
)

11.6.2 按组件安装

# 安装所有组件
cmake --install build

# 只安装特定组件
cmake --install build --component Runtime
cmake --install build --component Development

# 排除组件
cmake --install build --exclude-component Development

11.6.3 组件描述

# CMakeLists.txt
set(CPACK_COMPONENTS_ALL Runtime Development Configuration Docs)
set(CPACK_COMPONENT_Runtime_DISPLAY_NAME "运行时库")
set(CPACK_COMPONENT_Development_DISPLAY_NAME "开发文件")
set(CPACK_COMPONENT_Configuration_DISPLAY_NAME "配置文件")
set(CPACK_COMPONENT_Docs_DISPLAY_NAME "文档")

set(CPACK_COMPONENT_Development_DEPENDS Runtime)
set(CPACK_COMPONENT_Configuration_DEPENDS Runtime)

11.7 CPack 打包

11.7.1 基本配置

# 顶层 CMakeLists.txt 末尾
include(CPack)

# 通用设置
set(CPACK_PACKAGE_NAME "myproject")
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "My Project Description")
set(CPACK_PACKAGE_VENDOR "My Company")
set(CPACK_PACKAGE_CONTACT "[email protected]")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://example.com")

11.7.2 生成器选择

# 设置打包格式
set(CPACK_GENERATOR "TGZ")  # tar.gz

# 多种格式
set(CPACK_GENERATOR "TGZ;DEB;RPM")

# 自动检测
if(WIN32)
    set(CPACK_GENERATOR "NSIS;ZIP")
elseif(APPLE)
    set(CPACK_GENERATOR "DragNDrop;TGZ")
else()
    set(CPACK_GENERATOR "DEB;RPM;TGZ")
endif()

11.7.3 打包格式对照表

格式生成器平台文件扩展名
tar.gzTGZLinux/macOS.tar.gz
tar.bz2TBZ2Linux/macOS.tar.bz2
tar.xzTXZLinux/macOS.tar.xz
ZIPZIP全平台.zip
DEBDEBDebian/Ubuntu.deb
RPMRPMRHEL/Fedora.rpm
NSISNSISWindows.exe
WiXWIXWindows.msi
DragNDropDragNDropmacOS.dmg
productbuildproductbuildmacOS.pkg

11.7.4 DEB 包配置

set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Developer <[email protected]>")
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.17), libssl3")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://example.com")
set(CPACK_DEBIAN_FILENAMES DEBDEFAULT)

11.7.5 RPM 包配置

set(CPACK_RPM_PACKAGE_LICENSE "MIT")
set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries")
set(CPACK_RPM_PACKAGE_URL "https://example.com")
set(CPACK_RPM_PACKAGE_REQUIRES "openssl >= 1.1")
set(CPACK_RPM_PACKAGE_AUTOREQPROV "no")

11.7.6 NSIS 配置(Windows)

set(CPACK_NSIS_DISPLAY_NAME "My Project")
set(CPACK_NSIS_PACKAGE_NAME "MyProject")
set(CPACK_NSIS_INSTALLED_ICON_NAME "bin/myapp.exe")
set(CPACK_NSIS_URL_INFO_ABOUT "https://example.com")
set(CPACK_NSIS_HELP_LINK "https://example.com/docs")
set(CPACK_NSIS_MODIFY_PATH ON)

11.7.7 运行 CPack

# 构建项目
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build

# 生成所有包
cd build
cpack

# 指定生成器
cpack -G TGZ
cpack -G DEB

# 指定配置
cpack -C Release
cpack --config CPackConfig.cmake

11.8 cpack_add_component

cpack_add_component(Runtime
    DISPLAY_NAME "运行时库"
    DESCRIPTION "运行应用程序所需的库文件"
    REQUIRED
    GROUP "Core"
)

cpack_add_component(Development
    DISPLAY_NAME "开发文件"
    DESCRIPTION "头文件和静态库,用于开发"
    DEPENDS Runtime
    GROUP "Development"
)

cpack_add_component_group(Core
    DISPLAY_NAME "核心组件"
    DESCRIPTION "应用程序核心文件"
    EXPANDED
)

cpack_add_component_group(Development
    DISPLAY_NAME "开发工具"
    DESCRIPTION "开发所需的文件和工具"
    EXPANDED
)

11.9 业务场景

场景:完整的安装与打包配置

cmake_minimum_required(VERSION 3.16)
project(MyApp VERSION 2.1.0 LANGUAGES CXX)

include(GNUInstallDirs)

# 构建
add_library(mylib src/core.cpp)
target_include_directories(mylib PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE mylib)

# 安装
install(TARGETS mylib myapp
    EXPORT MyAppTargets
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

install(EXPORT MyAppTargets
    FILE MyAppTargets.cmake
    NAMESPACE MyApp::
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyApp
)

include(CMakePackageConfigHelpers)
configure_package_config_file(
    cmake/MyAppConfig.cmake.in
    ${CMAKE_CURRENT_BINARY_DIR}/MyAppConfig.cmake
    INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyApp
)
write_basic_package_version_file(
    ${CMAKE_CURRENT_BINARY_DIR}/MyAppConfigVersion.cmake
    VERSION ${PROJECT_VERSION}
    COMPATIBILITY SameMajorVersion
)
install(FILES
    ${CMAKE_CURRENT_BINARY_DIR}/MyAppConfig.cmake
    ${CMAKE_CURRENT_BINARY_DIR}/MyAppConfigVersion.cmake
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyApp
)

# 打包
include(CPack)
set(CPACK_PACKAGE_NAME "myapp")
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
set(CPACK_GENERATOR "TGZ;DEB")

11.10 注意事项

问题说明
安装前缀CMAKE_INSTALL_PREFIX 控制安装根目录
Windows DLLDLL 文件需要安装到 RUNTIME 目录
RPATH设置 CMAKE_INSTALL_RPATH 确保运行时能找到库
DESTDIR用于打包时的临时安装根目录
COMPONENT 安装开发包和运行时包分开

11.11 扩展阅读


上一章:第 10 章 — 测试与 CTest | 下一章:第 12 章 — CMake 预设 →