Once again about deb packages
Deb packages are a very convenient tool, especially if you know how to use it. I will try to share my own experience in this matter.
To start creating deb packages, you need to install several packages:
In order for dh_make and other utilities to work with the source folder, you need to bring it into a specific form.
The folder should be named package name . Those. if I have a Plugins folder with program version 0.1, then I create a folder called plugins-0.1 .
Now you need to create an archive with this folder. The archive must contain * .orig.tar.gz in the name , i.e.:
The final preparatory step is to create a debian folder with many utility files in the source folder . To do this, you need to run the command:
In the process of executing this command, a question will be asked about what type of archive we are creating, the simplest is single.
All package configuration is done by editing files in the debian directory . Consider the files that we will use:
In addition to these files, a lot of * .ex files will be created in the debian folder which are examples for configuring various things, but we will not use them and therefore we need to delete them.
This file contains the package change history and the current package version. Let's look at its contents:
At the beginning is the name of the package - libvksplugins , then its version. The version is divided into two parts by the symbol “-”. The first part shows the version of the program in the package, the second "revision" of the package. Revision is a package version, i.e. if there was no such package before, then the revision is 1. If the package with this version of the program was already there, but there have been changes in it, then the revision is increased.
The word unstable indicates that the package is not stable, i.e. It has not been tested properly on user machines.
The word urgency = low indicates the urgency of the change. Because there is no urgency, then the value is low . If we were making a package to fix a serious vulnerability or error, then the value could be set tohigh .
After the first line is an empty line, followed by the first entry:
In Debian, changelog is used to automatically close errors in error tracking systems in software products. Because in this case, I do not use such a system, then this line takes the form:
The last line is the signature of the person who made the recording. It contains the name and address, as well as the date of change.
After installing the deb package, the changelog file is installed in
The debian / control file is the main config when creating a deb package. Here is an example of such a file:
It can be seen that the file is divided into sections using empty lines. Each section describes one package created from the source folder. Let's consider them in order:
Source This section says that you need to create a package of source codes. The parameter specified is libvksplugins , which means that the source package will be called libvksplugins .
Priority This section sets the priority of the packet. Because Since the system can do well without a new package, the section value is set to optional . Those. This package is not required for installation. Read more about priorities here .
MaintainerThis section describes the contacts of the person creating the package. Its format is quite simple and does not require additional description.
Build-Depends One of the most important sections that installs package dependencies. The dependencies specified in this section must be met in order to be able to assemble the package. Those. The list of dependencies for assembly and installation may vary.
It can be seen that the dependencies are debhelper (> = 9), cmake . The debhelper (> = 9) dependency is set for all packages by default. It is needed for the correct operation of programs of the form dh_ * .
The second cmake element was added because the source folder contained the CMakeLists.txt file, i.e. the build system uses the CMake build system . In order to find out what dependencies a program has, you can read its documentation. Alternatively, you can use the dpkg-depcheck command . This command should run like this:
But, because when using CMake there is no configuration script, then I use it like this:
Of the noteworthy here, it can be noted: The rest are data dependencies. Moreover, cmake is already in the list of build dependencies. In principle, you can leave it as is or indicate the version used:
At the same time, the version of cmake that needs to be used is indicated in CMakeLists.txt:
I think that the developer knows better, and therefore I indicate the version from CMakeLists.txt. For Qt 4, everything is clear with version numbers, but to clear our conscience, we’ll check their versions:
Those. for Qt 4 we specify version 4.8.6:
Standards-Version The version of the standard by which the file was created. This value does not need to be changed.
Section . Section for the package, i.e. A group of packages that performs a single task. The Debian Policy Section 2.4 describes this issue in more detail.
Homepage Project homepage . Because I wrote this code and it has no page, just delete this line.
Vcs- * Links to project repositories. I don’t have them either, so I delete these lines.
Other packages After the file section where the source package is described, there are sections that describe other packages created from the source package. The scheme for creating packages:
From the scheme it can be seen that from the sources of the program, I want to get 4 packages:
The question is, why are there so many packages? There can be several answers to it, if you read the relevant discussions on stackoverflow.com, then the main idea of the partition is that most users do not need header files and documentation, so the separation of these files helps reduce network load and installation speed of programs.
My personal answer to this question is that such a partition helps to structure the program according to how I want to work with it. For development, I will put the dev package, but not for use.
In addition to the packages described above, you can create a dbg package with a debug build of the program. This can come in handy if the program crashes and you have a debugger on hand. However, I still could not understand how to do this.The documentation does not answer this question. If you do as described in it, then I either get an empty package or get a bunch of errors during assembly.
The diagram in the figure above shows that the source package is called libvksplugins_source , however, the control file indicates that the source package will be called libvksplugins . In fact, it will really be called libvksplugins , and a package with binaries will be called libvksplugins ... deb . The essence of this confusion is that the source package is a tar archive and service files, while the binary package is an archive with the deb extension.
Configuring the library package Let's look carefully at the description of the library package:
The Architecture parameter sets the architecture of the package being built. The value any means that after assembling the binaries, the necessary architecture will be substituted by the build system. Those. on a 64 bit machine, you get a package ..._ amd64 ... and on 32-bit package ..._ ... the i386 .
For packages containing scripts or texts, you must specify the value as all .
The third line describes the dependencies of the package being created. Here is how it is described in the 4th chapter of the Debian Novice Developer's Guide:
Those. this line indicates that the package collector will determine the dependencies.
The last section of this section is a description of the package. The first line contains a brief description, the subsequent lines contain a more detailed description. A detailed description must have a specific format:
Setting up the header file package The package with header files will be called libvksplugins-dev, here is its description: In this example, the Depends line is interesting . It states that this package will depend on the package of the libvksplugins library , and ( = $ {binary: Version} ) indicates that a strict coincidence of the versions of the binary package and the development package is necessary. This is an important point because the header files must strictly correspond to the binaries. Setting up the documentation package Together with the library, documentation is supplied so that it is in a separate package, we add its description: Everything should be clear here.
This file is an analogue of the Makefile for building packages. By default, it is created in the following form:
It can be seen that this is a bash script with Makefile syntax. The only interesting design here is
This is a template that, for all purposes, calls the dh command, passing arguments to it. To build a package, it is important that the text dh $ @ be read with a tab character. Those. indentation is not spaces, but tabulation.
Because Since the sources use the CMake build system, you need to change this entry as follows:
After we have specified in debian / control which packages we want to receive, we need to specify which files to put in which package. To do this, for each package name from the control file , you need to create two files in the debian folder . The first one should be called the package .dirs , and the second one the package .install . The essence of the files is that the first indicates which folders to create for the package, and the second, which files to include in the package.
Let's look at their contents:
An important point is the lack of an initial fraction in the paths and the absence of a fraction at the end of the path to the folder. After checking where CMake installs the library files, you can create the following files:
Because my sources, then I don’t have any additional descriptions and limitations of copyright, so I delete all the extra files from the debian directory.
After configuration, the assembly of packages is quite simple, you need to run the command in the project folder (which includes the debian subfolder):
The -us -uc options indicate that you do not need to sign the created packages with the gpg key. They can be omitted if the default gpg signature key is configured. I did not understand how to specify the default signature key. If everything went well, then we have a bunch of packages in the folder above:
If you have read up to here, then you love to read.
This text is the result of my experience implementing deb packages at work. Experience has shown that the presence of a network repository (reprepro) and careful version tracking make it possible to update and test various software versions on a fleet of 30 machines with Astra Linux 1.3, 1.4 and Elbrus OS without any problems.
Training
To start creating deb packages, you need to install several packages:
$ sudo apt-get install dh_make
Preparing the source folder
In order for dh_make and other utilities to work with the source folder, you need to bring it into a specific form.
The folder should be named package name . Those. if I have a Plugins folder with program version 0.1, then I create a folder called plugins-0.1 .
$ ls
VKSPlugins
$ mv VKSPlugins/ libvksplugins-0.1
$ ls
libvksplugins-0.1
Now you need to create an archive with this folder. The archive must contain * .orig.tar.gz in the name , i.e.:
$ tar -zcf libvksplugins_0.1.orig.tar.gz libvksplugins-0.1
$ ls
libvksplugins-0.1 libvksplugins_0.1.orig.tar.gz
The final preparatory step is to create a debian folder with many utility files in the source folder . To do this, you need to run the command:
$ cd libvksplugins-0.1/
$ dh_make
Type of package: single binary, indep binary,
multiple binary, library, kernel module, kernel patch?
[s/i/m/l/k/n] l
Maintainer name : User Name
Email-Address : user@name.ru
Date : Wed, 19 Aug 2015 14:55:53 +0300
Package Name : libvksplugins
Version : 0.1
License : blank
Type of Package : Single
Hit to confirm:
Skipping creating ../libvksplugins_0.1.orig.tar.gz because it already exists
Done. Please edit the files in the debian/ subdirectory now. plugins
uses a configure script, so you probably don’t have to edit the Makefiles.
In the process of executing this command, a question will be asked about what type of archive we are creating, the simplest is single.
About Package Type
In fact, the documentation says choosing only the single option . Because I could not understand all the requirements for a package of type library but I am quite happy with the result, the description goes on about a package of type library .
Package setup
All package configuration is done by editing files in the debian directory . Consider the files that we will use:
- changelog - package history.
- control - the main package config;
- rules - analogue of the Makefile for the package;
In addition to these files, a lot of * .ex files will be created in the debian folder which are examples for configuring various things, but we will not use them and therefore we need to delete them.
changelog
This file contains the package change history and the current package version. Let's look at its contents:
$ cat changelog
libvksplugins (0.1-1) unstable; urgency=low
* Initial release (Closes: #nnnn)
-- User Name Wed, 19 Aug 2015 15:03:51 +0300
At the beginning is the name of the package - libvksplugins , then its version. The version is divided into two parts by the symbol “-”. The first part shows the version of the program in the package, the second "revision" of the package. Revision is a package version, i.e. if there was no such package before, then the revision is 1. If the package with this version of the program was already there, but there have been changes in it, then the revision is increased.
The word unstable indicates that the package is not stable, i.e. It has not been tested properly on user machines.
The word urgency = low indicates the urgency of the change. Because there is no urgency, then the value is low . If we were making a package to fix a serious vulnerability or error, then the value could be set tohigh .
After the first line is an empty line, followed by the first entry:
* Initial release (Closes: #nnnn)
In Debian, changelog is used to automatically close errors in error tracking systems in software products. Because in this case, I do not use such a system, then this line takes the form:
* Initial release
Comment
When checking the package with the lintian program , the absence of Closes: #XXXX is considered an error.
The last line is the signature of the person who made the recording. It contains the name and address, as well as the date of change.
After installing the deb package, the changelog file is installed in
/usr/share/doc/<пакет>/changelog.Debian.gz
control
The debian / control file is the main config when creating a deb package. Here is an example of such a file:
$ cat control
Source: libvksplugins
Priority: optional
Maintainer: User Name
Build-Depends: debhelper (>= 9), cmake
Standards-Version: 3.9.5
Section: libs
Homepage:
#Vcs-Git: git://anonscm.debian.org/collab-maint/plugins.git
#Vcs-Browser: http://anonscm.debian.org/?p=collab-maint/plugins.git;a=summary
Package: libvksplugins-dev
Section: libdevel
Architecture: any
Depends: libvkspluginsBROKEN (= ${binary:Version}), ${misc:Depends}
Description:
Package: libvkspluginsBROKEN
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description:
It can be seen that the file is divided into sections using empty lines. Each section describes one package created from the source folder. Let's consider them in order:
Source This section says that you need to create a package of source codes. The parameter specified is libvksplugins , which means that the source package will be called libvksplugins .
Priority This section sets the priority of the packet. Because Since the system can do well without a new package, the section value is set to optional . Those. This package is not required for installation. Read more about priorities here .
MaintainerThis section describes the contacts of the person creating the package. Its format is quite simple and does not require additional description.
Build-Depends One of the most important sections that installs package dependencies. The dependencies specified in this section must be met in order to be able to assemble the package. Those. The list of dependencies for assembly and installation may vary.
It can be seen that the dependencies are debhelper (> = 9), cmake . The debhelper (> = 9) dependency is set for all packages by default. It is needed for the correct operation of programs of the form dh_ * .
The second cmake element was added because the source folder contained the CMakeLists.txt file, i.e. the build system uses the CMake build system . In order to find out what dependencies a program has, you can read its documentation. Alternatively, you can use the dpkg-depcheck command . This command should run like this:
$ dpkg-depcheck -d ./configure
But, because when using CMake there is no configuration script, then I use it like this:
$ mkdir build && cd build
$ dpkg-depcheck -d cmake ../
.....
Packages needed:
libxml2:amd64
cmake
libkrb5support0:amd64
language-pack-ru-base
libnettle4:amd64
.....
libedit2:amd64
libtasn1-6:amd64
qt4-qmake
libgssapi-krb5-2:amd64
libhcrypto4-heimdal:amd64
.....
libroken18-heimdal:amd64
libsqlite3-0:amd64
libqt4-dev
libssl1.0.0:amd64
.....
Of the noteworthy here, it can be noted: The rest are data dependencies. Moreover, cmake is already in the list of build dependencies. In principle, you can leave it as is or indicate the version used:
cmake
qt4-qmake
libqt4-dev
$ apt-cache show cmake | grep Version:
Version: 2.8.12.2-0ubuntu6
At the same time, the version of cmake that needs to be used is indicated in CMakeLists.txt:
$ cat CMakeLists.txt | grep cmake_minimum
cmake_minimum_required(VERSION 2.8.4)
I think that the developer knows better, and therefore I indicate the version from CMakeLists.txt. For Qt 4, everything is clear with version numbers, but to clear our conscience, we’ll check their versions:
$ apt-cache show qt4-qmake | grep Version:
Version: 4:4.8.6+git49-gbc62005+dfsg-1ubuntu1.1
Version: 4:4.8.6+git49-gbc62005+dfsg-1ubuntu1
$ apt-cache show libqt4-dev | grep Version:
Version: 4:4.8.6+git49-gbc62005+dfsg-1ubuntu1.1
Version: 4:4.8.6+git49-gbc62005+dfsg-1ubuntu1
Those. for Qt 4 we specify version 4.8.6:
Build-Depends: debhelper (>= 9), cmake (>= 2.8.4), qt4-qmake (>= 4.8.6), libqt4-dev (>= 4.8.6)
Standards-Version The version of the standard by which the file was created. This value does not need to be changed.
Section . Section for the package, i.e. A group of packages that performs a single task. The Debian Policy Section 2.4 describes this issue in more detail.
Homepage Project homepage . Because I wrote this code and it has no page, just delete this line.
Vcs- * Links to project repositories. I don’t have them either, so I delete these lines.
Other packages After the file section where the source package is described, there are sections that describe other packages created from the source package. The scheme for creating packages:
From the scheme it can be seen that from the sources of the program, I want to get 4 packages:
- source package
- a package with a binary (the library itself);
- development package (header files);
- package with documentation.
The question is, why are there so many packages? There can be several answers to it, if you read the relevant discussions on stackoverflow.com, then the main idea of the partition is that most users do not need header files and documentation, so the separation of these files helps reduce network load and installation speed of programs.
My personal answer to this question is that such a partition helps to structure the program according to how I want to work with it. For development, I will put the dev package, but not for use.
In addition to the packages described above, you can create a dbg package with a debug build of the program. This can come in handy if the program crashes and you have a debugger on hand. However, I still could not understand how to do this.The documentation does not answer this question. If you do as described in it, then I either get an empty package or get a bunch of errors during assembly.
The diagram in the figure above shows that the source package is called libvksplugins_source , however, the control file indicates that the source package will be called libvksplugins . In fact, it will really be called libvksplugins , and a package with binaries will be called libvksplugins ... deb . The essence of this confusion is that the source package is a tar archive and service files, while the binary package is an archive with the deb extension.
Configuring the library package Let's look carefully at the description of the library package:
Package: libvksplugins
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Library for creating plugins with VKS 2
This library provides a mechanism for creating plugins
to use in project VKS 2.
The Architecture parameter sets the architecture of the package being built. The value any means that after assembling the binaries, the necessary architecture will be substituted by the build system. Those. on a 64 bit machine, you get a package ..._ amd64 ... and on 32-bit package ..._ ... the i386 .
For packages containing scripts or texts, you must specify the value as all .
The third line describes the dependencies of the package being created. Here is how it is described in the 4th chapter of the Debian Novice Developer's Guide:
The dh_shlibdeps utility calculates binary package dependencies on shared libraries. It generates a list of ELF executables and shared libraries that it finds for each binary package. This list is substituted for $ {shlibs: Depends} .
The dh_perl utility computes Perl dependencies. It generates a list of perl or perlapi dependencies for each binary package. This list is substituted for $ {perl: Depends} .
Some debhelper package commands may add dependencies to your generated package. Each command generates a list of required packages for each binary package. This list is substituted for
$ {misc: Depends} .
Utilitydh_gencontrol generates a DEBIAN / control file for each binary package, replacing $ {shlibs: Depends} , $ {perl: Depends} , $ {misc: Depends} , etc. with the resulting values.
Those. this line indicates that the package collector will determine the dependencies.
The last section of this section is a description of the package. The first line contains a brief description, the subsequent lines contain a more detailed description. A detailed description must have a specific format:
- The line should begin with a space;
- The string should not be longer than 80 characters;
- An empty line must begin with a space and consist of a period character.
Setting up the header file package The package with header files will be called libvksplugins-dev, here is its description: In this example, the Depends line is interesting . It states that this package will depend on the package of the libvksplugins library , and ( = $ {binary: Version} ) indicates that a strict coincidence of the versions of the binary package and the development package is necessary. This is an important point because the header files must strictly correspond to the binaries. Setting up the documentation package Together with the library, documentation is supplied so that it is in a separate package, we add its description: Everything should be clear here.
Package: libvksplugins-dev
Section: libdevel
Architecture: any
Depends: libvksplugins (= ${binary:Version}), ${misc:Depends}
Description: Development package for libvksplugins
This package provides development files for
library libvksplugins.
.
Also, it contains pkg-config file, to use.
Package: libvksplugins-doc
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Documentation for libvksplugins
Package contains html documentation files for libvksplugins
rules
This file is an analogue of the Makefile for building packages. By default, it is created in the following form:
$ cat rules
#!/usr/bin/make -f
# See debhelper(7) (uncomment to enable)
# output every command that modifies files on the build system.
#DH_VERBOSE = 1
# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*
DPKG_EXPORT_BUILDFLAGS = 1
include /usr/share/dpkg/default.mk
# see FEATURE AREAS in dpkg-buildflags(1)
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
# see ENVIRONMENT in dpkg-buildflags(1)
# package maintainers to append CFLAGS
#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
# package maintainers to append LDFLAGS
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
# main packaging script based on dh7 syntax
%:
dh $@
# debmake generated override targets
# This is example for Cmake (See http://bugs.debian.org/641051 )
#override_dh_auto_configure:
# dh_auto_configure -- \
# -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)
It can be seen that this is a bash script with Makefile syntax. The only interesting design here is
%:
dh $@
This is a template that, for all purposes, calls the dh command, passing arguments to it. To build a package, it is important that the text dh $ @ be read with a tab character. Those. indentation is not spaces, but tabulation.
Because Since the sources use the CMake build system, you need to change this entry as follows:
%:
dh $@ --buildsystem=cmake
Package Contents
After we have specified in debian / control which packages we want to receive, we need to specify which files to put in which package. To do this, for each package name from the control file , you need to create two files in the debian folder . The first one should be called the package .dirs , and the second one the package .install . The essence of the files is that the first indicates which folders to create for the package, and the second, which files to include in the package.
Let's look at their contents:
$ cat libvksplugins-dev.dirs
usr/lib
usr/include
$ cat libvksplugins-dev.install
usr/include/*
usr/lib/lib*.a
usr/lib/lib*.so
usr/lib/pkgconfig/*
usr/share/pkgconfig/*
An important point is the lack of an initial fraction in the paths and the absence of a fraction at the end of the path to the folder. After checking where CMake installs the library files, you can create the following files:
$ for item in $(ls libvksplugins*); do echo "$item:"; cat $item; done
libvksplugins-dev.dirs:
usr/include/dep572
usr/lib/pkgconfig
libvksplugins-dev.install:
usr/include/dep572/plugins/*
usr/lib/dep572/lib*.so
usr/lib/pkgconfig/*
libvksplugins.dirs:
usr/lib/dep572
libvksplugins-doc.dirs:
usr/share/doc/libplugins-0.1
libvksplugins-doc.install:
usr/share/doc/libplugins-0.1/*.tgz
libvksplugins.install:
usr/lib/dep572/lib*.so.*
Completion of setup
Because my sources, then I don’t have any additional descriptions and limitations of copyright, so I delete all the extra files from the debian directory.
Package assembly
After configuration, the assembly of packages is quite simple, you need to run the command in the project folder (which includes the debian subfolder):
$ dpkg-buildpackage -rfakeroot -us -uc
The -us -uc options indicate that you do not need to sign the created packages with the gpg key. They can be omitted if the default gpg signature key is configured. I did not understand how to specify the default signature key. If everything went well, then we have a bunch of packages in the folder above:
$ ls -l ../
итого 748
drwxrwxr-x 10 user user 4096 авг. 20 10:46 libvksplugins-0.1
-rw-rw-r-- 1 user user 2210 авг. 20 10:47 libvksplugins_0.1-1_amd64.changes
-rw-r--r-- 1 user user 6418 авг. 20 10:47 libvksplugins_0.1-1_amd64.deb
-rw-rw-r-- 1 user user 1504 авг. 20 10:46 libvksplugins_0.1-1.debian.tar.xz
-rw-rw-r-- 1 user user 1008 авг. 20 10:46 libvksplugins_0.1-1.dsc
-rw-rw-r-- 1 user user 36713 авг. 19 14:52 libvksplugins_0.1.orig.tar.gz
-rw-r--r-- 1 user user 3262 авг. 20 10:47 libvksplugins-dev_0.1-1_amd64.deb
-rw-r--r-- 1 user user 699564 авг. 20 10:47 libvksplugins-doc_0.1-1_all.deb
Conclusion
If you have read up to here, then you love to read.
This text is the result of my experience implementing deb packages at work. Experience has shown that the presence of a network repository (reprepro) and careful version tracking make it possible to update and test various software versions on a fleet of 30 machines with Astra Linux 1.3, 1.4 and Elbrus OS without any problems.