使用cpack生成DEB二进制文件
说明
我之前习惯了直接Release源代码,然后在目标平台上编译运行的方式,但是有些项目要求将软件打包成安装包的形式发布,所以这里专门学习一下如何使用cpack(因为我现在主要使用cmake来构建项目)将工程打包成安装包和源代码包。
CPack概述
cpack是CMake的一个可执行文件,安装CMake后可以直接输入cpack命令,该命令是CMake提供的一个打包程序,它可以生成多种格式的二进制包和源代码包。CPack 在整个 CMake 工具链的位置如下:
cpack会针对每种安装程序或package产生一个“生成器”,该生成器负责生成所需的输入并调用特定的包创建工具。即cpack的作用是产生“生成器”,而安装程序则是由该生成器生成。
平台不同,安装包可能不同,那么生成器也会不同,如:Ubuntu是DEB包,CentOS是RPM包。CMake支持的生成器种类可在cpack-generators中查看。也可以通过cpack --help命令查看,如:
cpack 程序由用 CMake 语言编写的配置文件控制。除非通过命令行选项 --config 以不同方式选择,否则将使用当前目录中的文件 CPackConfig.cmake。
在标准 CMake 工作流程中,文件 CPackConfig.cmake 由 cmake 可执行文件生成,前提是 CPack 模块包含在项目的 CMakeLists.txt 文件中。
简单示例
按照惯例先看一个简单的示例。出于简化的目的,我这里将之前使用的代码进行简化后,编译成一个单独的可执行文件。
main.cpp
#include <iostream>
#include <string>
int Add(int t1, int t2)
{
int result = t1 + t2;
std::cout << t1 << " + " << t2 << " is: " << result << std::endl;
return result;
}
int main()
{
int ret_add;
ret_add = Add(1, 2);
std::cout << "Hello, this is my first cmake sample " << ret_add << std::endl;
return 0;
}
CMakeLists.txt
cmake_minimum_required (VERSION 3.0.0)
project (cmake_test VERSION 0.0.4)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
add_executable(demo main.cpp)
# package program
message(STATUS "CPack Configuration added.")
include(InstallRequiredSystemLibraries)
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR})
set(CPACK_SOURCE_IGNORE_FILES build)
set(CPACK_PACKAGE_CONTACT "xxx@163.com")
set(CPACK_PACKAGE_DESCRIPTION "cpack test program")
# set(CPACK_SET_DESTDIR ON)
# # 设置安装到的目录路径
# set(CMAKE_INSTALL_BINDIR "/home/raymond/install")
install(TARGETS demo
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# according to CMake, CPack must be included LAST
# after all settings have been set
include(CPack)
- include(InstallRequiredSystemLibraries):这个命令是CMake教程中建议使用的,该命令将包括当前平台项目所需的任何运行时库。
- CPACK_PACKAGE_NAME: 包的名称,默认使用项目名称
- CPACK_PACKAGE_VERSION : 包的版本,默认使用项目版本
- CPACK_PACKAGE_DIRECTORY :cpack要打包的目录,如果没有设置,默认使用编译目录
- CPACK_SOURCE_IGNORE_FILES :打包源代码时要排除的目录,默认情况下会将整个工程的目录都打包进源代码,但有些不属于代码的部分或者不想打包的部分可以通过这个变量排除,比如这里的build目录
- CPACK_PACKAGE_CONTACT :程序的维护者信息,这是在打包成DEB文件时必须的一个变量
- CPACK_PACKAGE_DESCRIPTION : 描述包的信息
- install()命令 :描述了包内的文件安装的位置,如可执行文件和共享库等,这里只设置了一个demo的可执行文件。
- include(CPack) : 所有的cpack命令需以这个结尾
注:关于这里的install()命令,我看了网上的部分文章,似乎打包RPM包的时候不需要这个命令,但是我在打包成DEB的时候,如果没有这个命令,包内就不会包含任何二进制文件,所以这是不同的包造成的差异?
编译
mkdir build && cd build
cmake ..
此时会在build目录下生成两个CPack配置文件: CPackConfig.cmake 和 CPackSourceConfig.cmake,前者用于生成安装文件,后者用于生成源代码。
生成源码包
默认情况下,cpack使用的是CPackConfig.cmake配置文件,所以生成源码包时要指定CPackSourceConfig.cmake
$ cpack --config CPackSourceConfig.cmake
CPack: Create package using TBZ2
CPack: Install projects
CPack: - Install directory: /home/raymond/work/experiment/cmake/12_cpack
CPack: Create package
CPack: - package: /home/raymond/work/experiment/cmake/12_cpack/build/cmake_test-0.0.4-Source.tar.bz2 generated.
CPack: Create package using TGZ
CPack: Install projects
CPack: - Install directory: /home/raymond/work/experiment/cmake/12_cpack
CPack: Create package
CPack: - package: /home/raymond/work/experiment/cmake/12_cpack/build/cmake_test-0.0.4-Source.tar.gz generated.
CPack: Create package using TXZ
CPack: Install projects
CPack: - Install directory: /home/raymond/work/experiment/cmake/12_cpack
CPack: Create package
CPack: - package: /home/raymond/work/experiment/cmake/12_cpack/build/cmake_test-0.0.4-Source.tar.xz generated.
CPack: Create package using TZ
CPack: Install projects
CPack: - Install directory: /home/raymond/work/experiment/cmake/12_cpack
CPack: Create package
CPack: - package: /home/raymond/work/experiment/cmake/12_cpack/build/cmake_test-0.0.4-Source.tar.Z generated.
执行后会生成四个源码包:cmake_test-0.0.4-Source.tar.bz2 cmake_test-0.0.4-Source.tar.gz cmake_test-0.0.4-Source.tar.xz cmake_test-0.0.4-Source.tar.Z
生成DEB二进制包
# cpack -G DEB
CPack: Create package using DEB
CPack: Install projects
CPack: - Run preinstall target for: cmake_test
CPack: - Install project: cmake_test []
CPack: Create package
-- CPACK_DEBIAN_PACKAGE_DEPENDS not set, the package will have no dependencies.
CPack: - package: /home/raymond/work/experiment/cmake/12_cpack/build/cmake_test-0.0.4-Linux.deb generated.
此时在当前目录下就生成了一个.deb的安装包。其内容如下:
$ dpkg -c cmake_test-0.0.4-Linux.deb
drwxrwxr-x root/root 0 2022-02-07 22:12 ./usr/
drwxrwxr-x root/root 0 2022-02-07 22:12 ./usr/bin/
-rwxr-xr-x root/root 17400 2022-02-07 22:12 ./usr/bin/demo
示例程序非常简单,只包含一个可执行文件demo。此时如果安装这个.deb包后,demo文件会被安装到/user/bin目录下,然后就可以直接在终端输入“demo”命令运行了。如果希望安装到其他目录,则可以参考CMakeLists.txt文件中被注释的部分安装到自己指定的目录。
cpack命令使用详解
基本用法
cpack [<options>]
基本用法由cpack + options组成,其中options可由cpack --help命令查看,如下图:
options解析
-G
这个选项用以指定生成器的类型,其中是一个列表,cpack将会遍历此列表并根据CPackConfig.cmake配置文件中的详细信息生成这个/些生成器的格式生成包。如果没有指定这个选项,将使用默认生成器集。
-C
这个选项用于指定要打包的项目的配置信息(如Debug, Release等)。
其中是一个列表。当CMake项目使用了多个配置生成器(如Xcode, Visual Studio等),需要此选项来告诉cpack哪些可执行文件要包含在包中。用户负责确保在调用cpack之前已经构建了列出的配置。
-D =
设置CPack的变量。注意如果CPackConfig.cmake存在同名变量,那么将被覆盖。
--config
指定配置文件。默认是使用当前路径下的CPackConfig.cmake,可以通过这个选项来指定其他的配置文件。
--verbose, -V
cpack运行时输出额外的log信息。
--debug
输出debug信息
--trace
设置cmake脚本为追踪模式
--trace-expand
设置cmake脚本为expanded trace模式
-P
定义或覆盖 CPACK_PACKAGE_NAME 变量,即包的名称。
-R
设置或覆盖 CPACK_PACKAGE_VERSION 变量的值,这个变量表示包的版本信息,由Major, Minor和Patch三个字段组成。
-B
设置或覆盖 CPACK_PACKAGE_DIRECTORY 变量的值,该变量控制CPack将执行打包工作的目录。默认情况下,将在此目录下生成包。
--vendor
设置或覆盖 CPACK_PACKAGE_VENDOR 变量的值。
注:各种cpack参数的描述见https://cmake.org/cmake/help/latest/module/CPack.html
CPack Module
CPack Module会产生两个配置文件:CPackConfig.cmake 和 CPackSourceConfig.cmake。这两个文件会在后面的程序中会分别影响二进制包和源码包的生成。
根据生成器的不同,CPack模块可能会产生两个新的编译目录 package 和 package_source。生成的二进制安装包可以通过CMake install()命令来安装,其中的DESTINATION选项必须是相对路径,否则安装文件会被cpack无视。
可以配置某些类型的二进制安装程序,以便用户可以选择单独的应用程序组件进行安装。有关详细信息,请参阅 CPackComponent 模块。
源码包会包含项目中所有的源文件,可以通过设置 CPACK_SOURCE_IGNORE_FILES 来排除不需要打包的文件。
CPack 生成器
CPack生成器由 CPACK_GENERATOR 变量来制定,该变量可以是一个字符串表示单个生成器,也可以是一个列表表示多个生成器。在运行cpack命令时,cpack会首相遍历-G 参数后接的生成器,如果没有该参数,则从CPackConfig.cmake文件中读取。对于每一个生成器,都会包含一个CPACK_PROJECT_CONFIG_FILE文件来产生生成器的包。
注:对于 CPackConfig.cmake 中 CPACK_GENERATOR 中列出的每个生成器,cpack 将在内部将 CPACK_GENERATOR 重置为当前正在使用的生成器,然后包含 CPACK_PROJECT_CONFIG_FILE。
Targets package and package_source
如果CMake与Makefile、NinJia或者Xcode生成器一起运行,则include(CPack)会生成一个目标包,这样就可以通过cmake --build命令而不是cpack来构建二进制安装程序了。同样include(CPack)会产生一个源码包,为了生成该源码包,用户需要使用 cmake的 --target 参数, make 的package_source或者ninja package_source来代替cpack -G TGZ --config CPackSourceConfig.cmake。如:
cmake --build . --target package_source
make package_source
ninja package_source
CPack生成器变量
在CMakeLists.txt文件中包含CPack模块之前,可以设置各种变量来自定义生成的安装程序。
注:这里只说明部分常用的变量,更多变量请见:Variables common to all CPack Generators
CPack DEB生成器
这个生成器生成的安装文件可以在Debian系统(如Ubuntu和Fedora)上运行。
参考资料
https://zhuanlan.zhihu.com/p/141956373
https://cmake.org/cmake/help/latest/manual/cpack.1.html
https://cmake.org/cmake/help/latest/module/CPack.html