CMake 从入门到精通:完整教程 / 第 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 安装目录对照表
| 目标类型 | 目标关键字 | 默认安装目录 |
|---|
| 可执行文件 | RUNTIME | bin |
| 动态库(非 macOS) | LIBRARY | lib |
| 动态库(macOS) | LIBRARY | lib |
| Windows DLL | RUNTIME(.dll)+ ARCHIVE(.lib) | bin + lib |
| 静态库 | ARCHIVE | lib |
| 对象库 | OBJECTS | lib |
| 头文件集 | FILE_SET HEADERS | include |
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_BINDIR | bin | 用户可执行文件 |
CMAKE_INSTALL_SBINDIR | sbin | 系统管理可执行文件 |
CMAKE_INSTALL_LIBDIR | lib 或 lib64 | 库文件 |
CMAKE_INSTALL_INCLUDEDIR | include | 头文件 |
CMAKE_INSTALL_DATADIR | share | 架构无关数据 |
CMAKE_INSTALL_SYSCONFDIR | etc | 配置文件 |
CMAKE_INSTALL_LOCALSTATEDIR | var | 可变数据 |
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.gz | TGZ | Linux/macOS | .tar.gz |
| tar.bz2 | TBZ2 | Linux/macOS | .tar.bz2 |
| tar.xz | TXZ | Linux/macOS | .tar.xz |
| ZIP | ZIP | 全平台 | .zip |
| DEB | DEB | Debian/Ubuntu | .deb |
| RPM | RPM | RHEL/Fedora | .rpm |
| NSIS | NSIS | Windows | .exe |
| WiX | WIX | Windows | .msi |
| DragNDrop | DragNDrop | macOS | .dmg |
| productbuild | productbuild | macOS | .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 DLL | DLL 文件需要安装到 RUNTIME 目录 |
| RPATH | 设置 CMAKE_INSTALL_RPATH 确保运行时能找到库 |
DESTDIR | 用于打包时的临时安装根目录 |
| COMPONENT 安装 | 开发包和运行时包分开 |
11.11 扩展阅读
上一章:第 10 章 — 测试与 CTest | 下一章:第 12 章 — CMake 预设 →