DEB安装包的制作

deb是在Debian及其衍生版Ubuntu、Deepin等Linux系统中使用的应用程序安装包的文件格式,以.deb作为其扩展名。通过deb可以方便的分发、安装软件,同时有效管理软件依赖。

deb是在Debian及其衍生版Ubuntu、Deepin等Linux系统中使用的应用程序安装包的文件格式,以.deb作为其扩展名。通过deb可以方便的分发、安装软件,同时有效管理软件依赖。

deb文件结构

deb文件的本质是包含控制信息和应用程序安装数据的数据包,其中有三个文件。

  1. debian-binary - 文件内有一行数据用于标识软件包格式的版本,目前是2.0;
  2. 控制文档包 - 一个名为control.tar的文档包,包含维护脚本和软件包的名字、版本、依赖等信息,支持gzip或xz压缩;
  3. 数据文档包 - 一个名位data.tar的文档包,包含实际安装的应用程序文件,支持gzip或xz压缩。

使用ar命令解压deb文件,可以看到以上三个文件。

u@o1:~$ ar -x octave_5.2.0-1_amd64.deb
u@o1:~$ ls -l oct
total 1924
-rw-r--r-- 1 u u    2860 Aug 14 13:19 control.tar.xz
-rw-r--r-- 1 u u 1959252 Aug 14 13:19 data.tar.xz
-rw-r--r-- 1 u u       4 Aug 14 13:19 debian-binary

控制文档包中主要包含以下文件:

  • control:包含软件包的名称、版本、依赖项等信息;
  • md5sums:包含软件包中所有文件的MD5值,以检测损坏的文件;
  • conffiles:列出软件包中的配置文件。除非特别说明,否则更新期间不会覆盖配置文件;
  • preinst, postinst, prerm and postrm:软件安装或删除前、后需要执行的脚本;
  • shlibs:列出共享库的依赖列表。

其中,只有control是必须的文件,其余都可以根据需要使用。关于控制文件各自动的详细说明可查阅:5. Control files and their fields — Debian Policy Manual v4.6.1.0

制作deb软件包

制作deb包前需要,需要先准备好应用程序所需要的全部文件,可以通过编译或其他方式获得。然后按以下步骤制作软件包。

编译octave

mkdir build ; cd build
../octave-7.2.0/configure --prefix=/opt/octave-7.2.0 JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 CPPFLAGS=-I/usr/include/suitesparse:/usr/include/sunlinsol/ 'LDFLAGS=-L/usr/lib/x86_64-linux-gnu/ -Wl,-rpath=/usr/lib/x86_64-linux-gnu/ -L/usr/lib -Wl,-rpath=/usr/lib  -Wl,-rpath=/opt/octave-7.2.0/lib/octave/7.2.0/ -Wl,-rpath='\''$$ORIGIN/../lib/octave/7.2.0/'\''' --without-sundials_nvecserial
make -j8

创建工程目录,目录名可以是准备打包的deb包的名字如:octave_7.2.0_amd64

mkdir $HOME/octave_7.2.0_amd64

把应用程序文件复制到工程目录内,如果是源码编译可以使用make install安装到工程目录

make install DESTDIR=$HOME/octave_7.2.0_amd64

之后再创建控制文件目录DEBIAN,并增加control文件

mkdir $HOME/octave_7.2.0_amd64/DEBIAN
touch $HOME/octave_7.2.0_amd64/DEBIAN/control

如此,deb打包的工程目录便创建完成,其目录结果如下

./
├── DEBIAN
│   └──  control
└── opt
    └── octave-7.2.0
        ├── bin
        ├── include
        ├── lib
        ├── libexec
        └── share

其中./opt,是应用程序的文件所在的顶层目录。应用程序安装时,会把opt/及其中的文件复制到系统根目录。

编辑control文件

使用文本编辑器打开control文件对其进行编辑,其中需要包含以下字段:

  • Package – 应用程序的名字;
  • Version – 应用程序的版本号;
  • Architecture – 应用程序的所运行的CPU架构,amd64、arm64等;
  • Maintainer – 软件包维护者的名字和邮箱;
  • Description – 应用程序的简要说明

下面是一个示例:

Package: hello
Version: 1.0
Architecture: arm64
Maintainer: Internal Pointers <info@internalpointers.com>
Description: A program that greets you.
 You can add a longer description here. Mind the space at the beginning of this paragraph.

除了上面几个基本字段,还有Depends也是很重要的一个字段。Depends中指定了该应用程序正常运行所依赖的其他软件包。多个软件包间用英文逗号分隔,可以使用竖线|表示可选的软件包,在每个软包名的后可加括号注明所需要的版本号。

Depends: libbz2-1.0, libc6 (>= 2.29), libccolamd2 (>= 1:4.5.2), libqhull7, libqt5gui5 (>= 5.7.0) | libqt5gui5-gles (>= 5.7.0)

7. Declaring relationships between packages — Debian Policy Manual v4.6.1.0中还介绍了其他如Build-Depends等类型的依赖包设置。

依赖软件包的确定

一个应用程序可能会依赖很多运行库,如何准确的列出这些库的名字是很重要的。应该使用一些工具可以帮助deb包的制作者来查询这些依赖库的,不过我目前没有发现。参考资料[3]中有一个查询编译依赖库Build-Depends的方法,可以作为参考

  1. 如果使用configure生成makefile可以使用dpkg-depcheck查询编译依赖库

     dpkg-depcheck -d ./configure
    

    软件包名字以-dev结尾的是编译需要的包,程序运行时使用的依赖库的包名字没有-dev。可

  2. 使用objdumpdpkg -S查询可执行文件的依赖库名字

     # 查询依赖库文件名
     objdump -p /usr/bin/foo | grep NEEDED
     # 查询依赖库的deb包名
     dpkg -S libfoo.so.6
    
  3. 如果有旧版deb包可以参考旧版的的依赖来设置

本次打包octave使用的control文件

Package: gunoctave
Version: 7.2.0
Priority: extra
Section: universe/math
Architecture: amd64
Installed-Size: 1125848
Maintainer: GUN
Original-Maintainer: Debian Octave Group <team+pkg-octave-team@tracker.debian.org>
Depends: libamd2 (>= 1:4.5.2), libbz2-1.0, libc6 (>= 2.29), libccolamd2 (>= 1:4.5.2), libcholmod3 (>= 1:4.5.2), libcolamd2 (>= 1:4.5.2), libcxsparse3 (>= 1:4.5.2), libfftw3-double3 (>= 3.3.5), libfftw3-single3 (>= 3.3.5), libfltk-gl1.3 (>= 1.3.0), libfltk1.3 (>= 1.3.3), libgcc-s1 (>= 3.0), libgl1, libglpk40 (>= 4.59), libportaudio2 (>= 19+svn20101113), libqhull7, libqscintilla2-qt5-15 (>= 2.11.2), libqt5core5a (>= 5.12.2), libqt5gui5 (>= 5.7.0) | libqt5gui5-gles (>= 5.7.0), libqt5help5 (>= 5.9.0), libqt5network5 (>= 5.0.2), libqt5printsupport5 (>= 5.0.2), libqt5widgets5 (>= 5.11.0~rc1), libqt5xml5 (>= 5.0.2), libsndfile1 (>= 1.0.20), libstdc++6 (>= 9), libsuitesparseconfig5 (>= 1:5.0.0), libx11-6, zlib1g (>= 1:1.2.2), texinfo, libopenblas0-pthread, libspqr2, libgraphicsmagick++-q16-12, libgl2ps1.4, libarpack2, libqrupdate1, libhdf5-103
Recommends: gnuplot-qt | gnuplot-x11 | gnuplot-nox, libopenblas0 | libatlas3-base, pstoedit, epstool, default-jre-headless, octave-doc
Suggests: liboctave-dev
Breaks: liboctave3v5, liboctave4, liboctave5, liboctave6
Description: GNU Octave language for numerical computations
 Octave is a (mostly Matlab (R) compatible) high-level language, primarily
 intended for numerical computations. It provides a convenient command-line
 interface for solving linear and nonlinear problems numerically.
 .
 Octave can be dynamically extended with user-supplied C++ files.

生成deb包

使用dpkg-deb命令生成deb软件包

# dpkg-deb --build --root-owner-group  <directory> <package-dir>
dpkg-deb --build --root-owner-group octave_7.2.0_amd64 octave_7.2.0_amd64.deb

其中,--root-owner-group参数会让deb包中的所有的文件的所有者都是root。这样按照以上操作就可以生成一个deb软件安装包。

deb软件包测试

deb包制作好之后还需要进行以下必要的测试,如安装、卸载等。

安装测试

使用dpkgapt在没有安装该软件的目标系统上进行安装测试

# sudo dpkg -i <package>
sudo dpkg -i octave_7.2.0_amd64.deb
# 或者
# sudo apt install <package>
sudo apt install ./octave_7.2.0_amd64.deb

使用dpkg安装时,可能会遇到依赖错误的问题

dependency problems - leaving unconfigured

可以使用下面命令修复

sudo apt -f install

安装后可以看到/opt/目录下增加了octave-7.2.0及其子目录。同时可以测试程序是否可以正常运行,如提示缺失动态库检查是否安装,若未安装则需要安装并再次测试,同时把安装的软件包增加到control文件的Depends项中。

卸载测试

使用下面的某一命令卸载软件

# sudo dpkg -r <appname>
sudo dpkg -r octave
# sudo apt remove <appname>
sudo apt remove octave

卸载完成后可以查看系统中是否还有该软件

dpkg -l | grep octave

  1. deb (file format) - Wikipedia
  2. 5. Control files and their fields — Debian Policy Manual v4.6.1.0
  3. Chapter 4. Required files under the debian directory
  4. deb打包 - 光何 - 博客园
  5. Building binary deb packages: a practical guide - Internal Pointers
  6. Building - Octave
  7. 7. Declaring relationships between packages — Debian Policy Manual v4.6.1.0