Cmake使用CPack实现打包

打包基操

在顶层 CMakeList的末尾加上 cpack模块,

我的测试代码是linux的lvgl代码,用了ffmpeg等外部动态库

bash 复制代码
# ---------------------- 1. 基础包信息(必填)----------------------
set(CPACK_PACKAGE_NAME "lvglsim")                # 安装包名称(如 deb/rpm 包名)
set(CPACK_PACKAGE_VERSION "1.0.0")               # 版本号(格式:主.次.修订)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LVGL Simulator with Serial/Video Support")  # 包简介
set(CPACK_PACKAGE_CONTACT "your_email@example.com")  # 维护者邮箱(可选)
set(CPACK_PACKAGE_INSTALL_DIRECTORY "lvglsim")   # 安装根目录(默认 /usr/local,可改)
bash 复制代码
# ---------------------- 2. 安装路径配置(可选,默认 /usr/local)----------------------
# 若需自定义安装路径(如 /opt/lvglsim),设置以下变量:
# set(CMAKE_INSTALL_PREFIX "/opt/lvglsim")  # 全局安装前缀,会影响所有 install 目标
bash 复制代码
#包含一个模块,该模块会自动检测并安装目标系统上所需的系统库。
#这通常用于确保在生成的安装包中包含所有必要的动态链接库(DLL 或 SO 文件),以便在目标系统上运行应用程序。
include(InstallRequiredSystemLibraries)
#设置CPack变量,指定安装包包含的许可证
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
#CPack变量,指定安装包的主要版本号
set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
#CPack变量,指定安装包的次要版本号
set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
#指定生成的安装包格式
set(CPACK_GENERATOR "TGZ")
#指定生成的源码包格式
set(CPACK_SOURCE_GENERATOR "TGZ")
#包含CPack模块,启用CPack功能
include(CPack)
bash 复制代码
# ---------------------- 4. 安装目标确认(已在原 CMake 配置,无需修改)----------------------
# 安装源为lvglsim
# 安装类型为RUNTIME可执行程序
# 安装目的地为 bin目录
install(TARGETS lvglsim
    RUNTIME DESTINATION bin  # 可执行文件安装到 <安装前缀>/bin(如 /usr/local/bin)
)

然后我看 LVGL提供的原版cmakeList.txt里面已经有了

bash 复制代码
#安装 lvgl_linux 相关头文件
install(DIRECTORY src/lib/            #指定要安装的源目录,/指目录下的文件,而非目录本身
    DESTINATION include/lvgl          #目标安装目录,
                                      #默认路径:
                                      # ${CMAKE_INSTALL_PREFIX}/include/lvgl
                                      #(CMAKE_INSTALL_PREFIX 默认是 /usr/local),
                                      # 即最终安装到 /usr/local/include/lvgl

    FILES_MATCHING                    # 开启文件筛选模式,只安装符合后续 PATTERN 规则的文件
    PATTERN "backends*" EXCLUDE       # 排除所有以 backends 开头的文件 / 目录
    PATTERN "*.h")                    # 仅保留后缀为 .h 的头文件
bash 复制代码
install(TARGETS lvgl_linux  # 指定要安装的目标:
                            # lvgl_linux 是之前通过 add_library(lvgl_linux STATIC ...) 
                            # 定义的静态库目标(STATIC 表示静态库)。

    ARCHIVE DESTINATION lib #指定要安装目标的的安装路径:
                            #- ARCHIVE:是 CMake 中 "静态库" 的专用类型(对应 .a 文件,Windows 下是 .lib)。
                            #- DESTINATION lib:目标目录是 ${CMAKE_INSTALL_PREFIX}/lib,默认即 /usr/local/lib。
                            #- 最终安装的文件是:/usr/local/lib/liblvgl_linux.a(静态库文件名默认是 lib+目标名+.a)。
)

CMAKE官方其实有打包的例程。

下面是我自己在LVGL的CMakeList.txt末尾额外添加的代码

bash 复制代码
# ---------------------- 1. 基础包信息(必填)----------------------
set(CPACK_PACKAGE_NAME "lvglsim")                # 安装包名称(如 deb/rpm 包名)
set(CPACK_PACKAGE_VERSION "1.0.0")               # 版本号(格式:主.次.修订)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LVGL Simulator with Serial/Video Support")  # 包简介
set(CPACK_PACKAGE_CONTACT "18967107546@163.com")  # 维护者邮箱(可选)
set(CPACK_PACKAGE_INSTALL_DIRECTORY "lvglsim")   # 安装根目录(默认 /usr/local,可改)
#包含一个模块,该模块会自动检测并安装目标系统上所需的系统库。
#这通常用于确保在生成的安装包中包含所有必要的动态链接库(DLL 或 SO 文件),以便在目标系统上运行应用程序。
include(InstallRequiredSystemLibraries) #此处主要是对.tar.gz格式有用,
#设置CPack变量,指定安装包包含的许可证
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
#CPack变量,指定安装包的主要版本号
# set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")  由于前面通过set明确指定了版本号,因此此处多余.
#CPack变量,指定安装包的次要版本号
# set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
#指定生成的安装包格式
# set(CPACK_GENERATOR "TGZ")
#指定生成的源码包格式
#set(CPACK_SOURCE_GENERATOR "TGZ")
#包含CPack模块,启用CPack功能

# ---------------------- 2. 安装路径配置(可选,默认 /usr/local)----------------------
# 若需自定义安装路径(如 /opt/lvglsim),设置以下变量:
# set(CMAKE_INSTALL_PREFIX "/opt/lvglsim")  # 全局安装前缀,会影响所有 install 目标

# ---------------------- 3. 打包格式(已配置 TGZ,可扩展)----------------------
# 除了默认 TGZ,可添加 DEB(Debian/Ubuntu)、RPM(CentOS/Fedora)格式:
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
    #将DEB追加赋给 CPACK_GENERATOR
    list(APPEND CPACK_GENERATOR "DEB")# 同时生成"DEB" "RPM" "TGZ"3种格式,可扩展,我这里只用了DEB  
    # DEB 包额外配置(依赖自动检测)
    set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)  # 自动检测 DEB 包依赖的动态库(关键)
    set(CPACK_DEBIAN_PACKAGE_SECTION "utils")  # DEB 包分类(如 utils、libs)
    # RPM 包额外配置
    # set(CPACK_RPM_PACKAGE_REQUIRES "ffmpeg, SDL2, libevdev")  # 手动指定 RPM 依赖(可选)
endif()

include(CPack) #启用CPack

# 安装可执行文件
install(TARGETS lvglsim
    RUNTIME DESTINATION bin
)

打包成不同格式的包管理能力不同

打包指令

bash 复制代码
cd build  # 进入构建目录
cmake ..  # 重新加载 CMakeLists.txt(关键,确保 CPack 配置生效)
bash 复制代码
make package  # 执行打包(依赖 make 编译完成,会自动调用 CPack)

打包图片

如果是png之类的格式,其实就是通过Install(DIRECTORY xxx )

这种格式,指定安装DEB包的时候,图片复制到纯净系统的什么路径下。

可以在cmakeList的末尾添加:

bash 复制代码
# 设置安装图片资源的路径
set(IMAGE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/ImageSrc/Logo)
install(DIRECTORY ${IMAGE_DIR}/
        DESTINATION share/${CPACK_PACKAGE_NAME}/images
        FILES_MATCHING PATTERN "*.c") # 根据实际图片文件类型调整

代码中动态读取安装路径

cpp 复制代码
# 定义图片安装路径变量,供代码使用
set(APP_IMAGE_PATH "/usr/share/${CPACK_PACKAGE_NAME}/images" CACHE PATH "Path to installed images")
target_compile_definitions(lvglsim PRIVATE APP_IMAGE_PATH="${APP_IMAGE_PATH}")
bash 复制代码
// 示例:获取图片路径
const char *image_path = APP_IMAGE_PATH "/BT.c"; // 根据实际图片文件名调整

然后项目中创建build文件夹,进入该文件夹

cmake .. 执行 cmakelist,

cmakelist是 cmake的配置文件,这里的..是包含cmakelist文件所在项目的根目录,是告诉cmake去该目录下找cmakelist执行。生成build目录下的构建文件。(通常cmakelist中会用execute指定要生成的可执行文件)

由于我的测试项目是lvgl,png直接转换成了.c,而.c文件作为源文件处于 cmakelist的编译链中,所以其实不需要这一步。

Cmake关于链接外部库的方式

pkg-config工具查找

还是以LVGL for linux为例子,

下面是通过 pkg-config查找ffmpeg所有必须库的例子,我是直接放在 cmakelist的末尾,

execute(lvglsim xxx) 之后,否则会说lvglsim未定义

bash 复制代码
# 1. 查找 pkg-config(系统已支持,无需额外安装)
find_package(PkgConfig REQUIRED)

# 2. 通过 pkg-config 查找 FFmpeg 所有必需库(与终端输出的库对应)
pkg_check_modules(FFMPEG REQUIRED
  libavcodec   # 对应 -lavcodec(avcodec_send_packet 等函数)
  libavformat  # 对应 -lavformat(avformat_open_input 等函数)
  libswscale   # 对应 -lswscale(sws_getContext/sws_scale 等函数)
  libavdevice  # 对应 -lavdevice(设备输入相关,若用到需保留)
  libavutil    # 对应 -lavutil(av_packet_unref/av_frame_free 等函数)
)

# 4. 为 lvglsim 添加 FFmpeg 头文件目录(确保编译时能找到 avcodec.h 等)
target_include_directories(lvglsim PRIVATE ${FFMPEG_INCLUDE_DIRS})
#上面PRIVATE制定了依赖的作用域,不加就是默认public,所有和lvglsim相关的依赖都会继承该依赖

target_link_libraries(lvglsim  ${FFMPEG_LDFLAGS})

原生依赖查找方式

bash 复制代码
# 设置 FFmpeg 头文件目录
set(FFMPEG_INCLUDE_DIR /usr/include/aarch64-linux-gnu)
include_directories(${FFMPEG_INCLUDE_DIR})

# 设置 FFmpeg 库文件目录
set(FFMPEG_LIBRARY_DIR /usr/lib/aarch64-linux-gnu)
link_directories(${FFMPEG_LIBRARY_DIR})

# 手动查找每个库
find_library(AVCODEC_LIB avcodec HINTS ${FFMPEG_LIBRARY_DIR})
find_library(AVFORMAT_LIB avformat HINTS ${FFMPEG_LIBRARY_DIR})
find_library(SWSCALE_LIB swscale HINTS ${FFMPEG_LIBRARY_DIR})
find_library(AVDEVICE_LIB avdevice HINTS ${FFMPEG_LIBRARY_DIR})
find_library(AVUTIL_LIB avutil HINTS ${FFMPEG_LIBRARY_DIR})

# 检查是否找到所有库
if(NOT AVCODEC_LIB OR NOT AVFORMAT_LIB OR NOT SWSCALE_LIB OR NOT AVDEVICE_LIB OR NOT AVUTIL_LIB)
    message(FATAL_ERROR "❌ FFmpeg libraries not found!")
else()
    message(STATUS "✅ Found FFmpeg libraries")
endif()

# 链接到你的可执行程序
target_link_libraries(lvglsim PRIVATE
    ${AVCODEC_LIB}
    ${AVFORMAT_LIB}
    ${SWSCALE_LIB}
    ${AVDEVICE_LIB}
    ${AVUTIL_LIB}
)
相关推荐
崔庆才丨静觅1 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
曹牧2 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅2 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅3 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
爬山算法3 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
七夜zippoe3 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
盟接之桥3 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
kfyty7253 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai