CMake/CPack构建DEB包:如何为单个子目录添加postinst脚本?
解决多组件DEB包仅指定组件带postinst脚本的CMake配置问题
核心问题分析
你遇到的问题是CPACK变量作用域处理错误:
- 添加
PARENT_SCOPE会将postinst脚本的配置提升到全局父作用域,导致所有组件继承该设置,最终两个包都带脚本; - 直接移除
PARENT_SCOPE后,若未针对组件绑定专属CPACK变量,子目录的配置无法被CPACK正确识别,导致脚本全部消失。
正确配置方案
以下是各文件的修正代码,确保仅c1组件的DEB包包含post-installation脚本:
根目录CMakeLists.txt
cmake_minimum_required(VERSION 3.10) project(tst_deb_components) # 基础配置 set(CMAKE_INSTALL_PREFIX /usr) set(CPACK_GENERATOR "DEB") # 启用组件拆分打包 set(CPACK_DEB_COMPONENT_INSTALL ON) # 全局包信息 set(CPACK_PACKAGE_VERSION "1.0.0") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Multi-component DEB test project") set(CPACK_PACKAGE_MAINTAINER "Your Name") # 引入子组件 add_subdirectory(c1) add_subdirectory(c2) include(CPack)
c1/CMakeLists.txt
add_executable(c1 main.c) # 绑定安装目标到c1组件 install(TARGETS c1 DESTINATION bin COMPONENT c1) # 为c1组件单独设置postinst脚本 # 变量命名规则:CPACK_DEBIAN_<组件名>_PACKAGE_CONTROL_EXTRA,组件名需与install指令的COMPONENT一致 set(CPACK_DEBIAN_C1_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst") # 可选:确保postinst脚本具备可执行权限(避免DEB安装时出错) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/postinst DESTINATION ${CMAKE_CURRENT_BINARY_DIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) set(CPACK_DEBIAN_C1_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_BINARY_DIR}/postinst")
c2/CMakeLists.txt
add_executable(c2 main.c) # 绑定安装目标到c2组件,无需额外配置脚本 install(TARGETS c2 DESTINATION bin COMPONENT c2)
build.sh(确保脚本可执行)
#!/bin/bash rm -rf build mkdir -p build && cd build cmake .. make -j$(nproc) cpack -G DEB
关键原理说明
- 组件专属CPACK变量:使用
CPACK_DEBIAN_<组件名>_PACKAGE_CONTROL_EXTRA而非全局变量,可精准为单个组件绑定控制脚本,无需PARENT_SCOPE——CPACK会自动扫描所有子目录中定义的组件专属变量。 - 脚本权限:DEB包要求postinst脚本必须具备可执行权限,通过
file(COPY ...)设置权限可避免安装时的权限错误。
运行build.sh后,会生成两个独立DEB包:
tst_deb_components-c1_1.0.0_amd64.deb:包含postinst脚本tst_deb_components-c2_1.0.0_amd64.deb:无额外脚本
内容的提问来源于stack exchange,提问作者Aloïkè
相关产品推荐
相关产品推荐

