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}
)
相关推荐
yunmi_2 小时前
微服务,Spring Cloud 和 Eureka:服务发现工具
java·spring boot·spring cloud·微服务·eureka·架构·服务发现
一叶飘零_sweeeet2 小时前
从 0 到 PB 级存储:MinIO 分布式文件系统实战指南与架构解密
java·架构·大文件存储
Dest1ny-安全2 小时前
Java代码审计-Servlet基础(1)
java·python·servlet
迎風吹頭髮3 小时前
UNIX下C语言编程与实践39-UNIX 定时器:alarm 函数与 setitimer 函数的使用与对比
服务器·c语言·unix
名誉寒冰3 小时前
# 深入理解Linux内核与用户态通信:Netlink机制实战
linux·服务器·windows
lingggggaaaa3 小时前
小迪安全v2023学习笔记(九十七天)—— 云原生篇&Kubernetes&K8s安全&API&Kubelet未授权访问&容器执行
java·笔记·学习·安全·网络安全·云原生·kubernetes
翻斗花园牛图图-3 小时前
Linux网络编程——UdpServer
服务器
Mr.Ja3 小时前
【LeetCode 热题 100】No.49—— 字母异位词分组(Java 版)
java·算法·leetcode·字母异位词分组
薰衣草23333 小时前
linux-1
linux·运维·服务器