Debian package structure: what changed
Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.
| Old | New | Line | |
|---|---|---|---|
| 1 | 1 | Installations on Debian are provided as files with .deb extension. This article discusses how to build them manually. | |
| 2 | 2 | ||
| 3 | 3 | If you would like to bring your program to Debian distributions, see how to make a [[Debian upstream]] source. | |
| 4 | 4 | ||
| 5 | 5 | ## General | |
| 6 | 6 | ||
| 7 | 7 | ### Two types of packages | |
| 8 | 8 | ||
| 9 | 9 | There are two types of packages, a source package and a binary package. This article is about the binary packages. They are a convenient way to bundle up pre-compiled binaries ready to be supplied directly to an end user. However, distributions like Debian and Ubuntu will not accept to add a binary package in their repositories, they require a [[Debian package source|source package]] that can be used to build the binary version on demand. The [[Debian package source|source package]] is somewhat more difficult to assemble and is subject to a number of technical and legal rules before being acceptable to the major Linux distributions. | |
| 10 | 10 | ||
| 11 | 11 | ### Preparing the package | |
| 12 | 12 | ||
| 13 | 13 | In a Debian binary package, the installation files are compressed using **dpkg-deb** command. You can view the content of the resulting .deb files as any other compressed archive by right-clicking them and opening them with the archive manager. | |
| 14 | 14 | ||
| 15 | 15 | To make a .deb file, you need to prepare a directory structure with the appropriate files. This will be called the staging directory and expressed in this article with the variable `${STAGING_DIR}`. You can replace it with the adequate folder or define this variable in a script. | |
| 16 | 16 | ||
| 17 | 17 | You can for example create the staging directory as a subdirectory of the current folder. The simplest script would be: | |
| 18 | 18 | ||
| 19 | 19 | `STAGING_DIR=./staging`\ | |
| 20 | 20 | `mkdir ${STAGING_DIR}` | |
| 21 | 21 | ||
| 22 | 22 | Though if you write a script, it may be run from another location. So instead, you can ensure that the variable contains the subdirectory relative to the script with the following: | |
| 23 | 23 | ||
| 24 | 24 | `` cd `dirname $0` ``\ | |
| 25 | 25 | `STAGING_RELATIVEDIR="./staging"`\ | |
| 26 | 26 | `STAGING_DIR=$(readlink --canonicalize "${STAGING_RELATIVEDIR}")` | |
| 27 | 27 | ||
| 28 | 28 | Also you may need to remove the existing staging directory to make sure it is empty: | |
| 29 | 29 | ||
| 30 | 30 | `rm -rf "${STAGING_DIR}"`\ | |
| 31 | 31 | `mkdir "${STAGING_DIR}"` | |
| 32 | 32 | ||
| 33 | 33 | The content of this directory is explained in the rest of this article. | |
| 34 | 34 | ||
| 35 | 35 | ### Finalizing the staging directory | |
| 36 | 36 | ||
| 37 | 37 | Read the section *Directory structure* to add all the necessary files. Then you can finalize the directory. | |
| 38 | 38 | ||
| 39 | 39 | The directories and files are supposed to be read-only in the package. To ensure that's the case, you can before calling **dpkg-deb** do the following: | |
| 40 | 40 | ||
| 41 | 41 | `find "${STAGING_DIR}" -type d -exec chmod 0755 {} \; #set directory attributes`\ | |
| 42 | 42 | `find "${STAGING_DIR}" -type f -exec chmod 0644 {} \; #set data file attributes`\ | |
| 43 | 43 | `find "${STAGING_DIR}/usr/bin" -type f -exec chmod 0755 {} \; #set executable attributes` | |
| 44 | 44 | ||
| 45 | 45 | When you have all file in the staging directory, you can determine the installed size and add it to the **control** file: | |
| 46 | 46 | ||
| 47 | 47 | `SIZE_IN_KB="$(du -s ${STAGING_DIR} | awk '{print $1;}')"`\ | |
| 48 | 48 | `echo "Installed-Size: ${SIZE_IN_KB}" >> "${STAGING_DIR}/DEBIAN/control"` | |
| 49 | 49 | ||
| 50 | 50 | ### Creating the Deb archive | |
| 51 | 51 | ||
| 52 | 52 | Once the directory structure is ready, you can create the archive with: | |
| 53 | 53 | ||
| 54 | 54 | `dpkg-deb --root-owner-group --build "${STAGING_DIR}" "${PACKAGE_NAME}.deb"` | |
| 55 | 55 | ||
| 56 | 56 | Or for older versions of dpkg-deb: | |
| 57 | 57 | ||
| 58 | 58 | `fakeroot dpkg-deb --build "${STAGING_DIR}" "${PACKAGE_NAME}.deb"` | |
| 59 | 59 | ||
| 60 | 60 | `${STAGING_DIR}` is the path to the directory structure to compress. `${PACKAGE_NAME}` is the filename to use for the archive. | |
| 61 | 61 | ||
| 62 | 62 | Generally you will create the package as a regular user, not with the *root* account. But installation files must not belong to a specific user. Using `--root-owner-group` option or **fakeroot** prefix will save in the archive that the files belong instead to *root*. | |
| 63 | 63 | ||
| 64 | 64 | After that, you will probably not need the staging directory anymore, you can thus delete it: | |
| 65 | 65 | ||
| 66 | 66 | `rm -rf "${STAGING_DIR}"` | |
| 67 | 67 | ||
| 68 | 68 | ### Checking the archive | |
| 69 | 69 | ||
| 70 | 70 | Once you've created the package, you can check it follows the guidelines with the command **lintian**: | |
| 71 | 71 | ||
| 72 | 72 | `lintian "${PACKAGE_NAME}.deb" --info` | |
| 73 | 73 | ||
| 74 | 74 | Here is the list of potential problems: <https://lintian.debian.org/tags.html> | |
| 75 | 75 | ||
| 76 | 76 | With Lazarus, you will get by default the `hardening-no-pie` (and `hardening-no-bindnow` warnings in mentors). To avoid such warnings, add the following compiler options in the project options: | |
| 77 | 77 | ||
| 78 | 78 | `-Cg`\ | |
| 79 | 79 | `-k-pie`\ | |
| 80 | 80 | `-k-znow` | |
| 81 | 81 | ||
| 82 | 82 | ## Directory structure | |
| 83 | 83 | ||
| 84 | 84 | Here is the structure of the staging directory that you need to prepare. | |
| 85 | 85 | ||
| 86 | 86 | `staging`\ | |
| 87 | 87 | ` ├─ DEBIAN`\ | |
| 88 | 88 | ` └─ usr`\ | |
| 89 | 89 | ` ├─ bin`\ | |
| 90 | 90 | ` └─ share`\ | |
| 91 | 91 | ` ├─ project1 #resources of your package`\ | |
| 92 | 92 | ` ├─ applications #shortcut`\ | |
| 93 | 93 | ` ├─ pixmaps #default icon`\ | |
| 94 | 94 | ` ├─ icons`\ | |
| 95 | 95 | ` │ └─ hicolor #icons of various sizes`\ | |
| 96 | 96 | ` ├─ doc`\ | |
| 97 | 97 | ` │ └─ project1 #information about your package`\ | |
| 98 | 98 | ` └─ man #user manual`\ | |
| 99 | 99 | ` └─ man1 #index` | |
| 100 | 100 | ||
| 101 | 101 | ### DEBIAN directory | |
| 102 | 102 | ||
| 103 | 103 | The name of this directory is uppercase. It needs to contain one file called **control**. Here is an example for a package called **project1** at version 2.0. | |
| 104 | 104 | ||
| 105 | 105 | `Section: graphics`\ | |
| 106 | 106 | `Priority: optional`\ | |
| 107 | 107 | `Maintainer: myname <myname@webserver.com>`\ | |
| 108 | 108 | `Homepage: `[`https://www.project1.com`](https://www.project1.com)\ | |
| 109 | 109 | `Package: project1`\ | |
| 110 | 110 | `Architecture: amd64`\ | |
| 111 | 111 | `Version: 2.0`\ | |
| 112 | 112 | `Depends: libatk1.0-0 (>= 1.12.4), libc6 (>= 2.2.5), libcairo2 (>= 1.2.4), libgdk-pixbuf2.0-0 (>= 2.22.0), libglib2.0-0 (>= 2.12.0), libgtk2.0-0 (>= 2.24.0), libpango-1.0-0 (>= 1.18.0), libx11-6`\ | |
| 113 | 113 | `Description: This is a test project.`\ | |
| 114 | 114 | ` Long description blah blah blah.` | |
| 115 | 115 | ||
| 116 | 116 | Sample values for **Section**: comm, database, devel, editors, electronics, fonts, games, graphics, math, web, net, news, science, sound, utils, video. | |
| 117 | 117 | ||
| 118 | 118 | The **Architecture** field is the one used to compile the program. To know the current architecture, use the following command: | |
| 119 | 119 | ||
| 120 | 120 | `dpkg --print-architecture` | |
| 121 | 121 | ||
| 122 | 122 | The **Depends** field contains the list of Linux libraries used. You can get this list with the following commands run in the directory of your binary file: | |
| 123 | 123 | ||
| 124 | 124 | `mkdir debian #need a debian directory`\ | |
| 125 | 125 | `touch debian/control #with one control file in it`\ | |
| 126 | 126 | `dpkg-shlibdeps -O project1 #supposing your binary is called project1` | |
| 127 | 127 | ||
| 128 | 128 | You can then remove the almost empty *debian* folder if you don't use it. | |
| 129 | 129 | ||
| 130 | 130 | This will output the dependencies (after the equal sign): | |
| 131 | 131 | ||
| 132 | 132 | `shlibs:Depends=libatk1.0-0 (>= 1.12.4), libc6 (>= 2.2.5), libcairo2 (>= 1.2.4), libgdk-pixbuf2.0-0 (>= 2.22.0), libglib2.0-0 (>= 2.12.0), libgtk2.0-0 (>= 2.24.0), libpango-1.0-0 (>= 1.18.0), libx11-6` | |
| 133 | 133 | ||
| 134 | 134 | To be complete, it should be noted that all these packages are not absolutely necessary, because several packages on this list may already be part of the dependencies - and therefore be part of the installation - of another package listed in this same list (see \[<https://wiki.freepascal.org/Deploying_Your_Application#Tip%3A%5Dto> cross-check, and eliminate superfluous dependencies). | |
| 135 | 135 | ||
| 136 | 136 | ### usr/bin directory | |
| 137 | 137 | ||
| 138 | 138 | This directory contains the binary file and only this file (*for information, avoid underscore in the name of your project - for example, dpkg-deb refuses it - because the package name should follow this regex: \${PackageName}_\${Version}_\${Arch}.deb, e.g. dpkg-dev_1.19.0.5ubuntu2_all.deb*). All resources files need to go in *usr/share/project1*. To access resources, your program can use a relative path like *../share/project1*. | |
| 139 | 139 | ||
| 140 | 140 | The directory *usr/local/bin* is invalid in a package[1](https://lintian.debian.org/tags/file-in-usr-local.html) because *local* is used for projects compiled locally and installed using their Makefile. | |
| 141 | 141 | ||
| 142 | 142 | ### Resources directory | |
| 143 | 143 | ||
| 144 | 144 | It will be called *usr/share/project1* if the package name is "project1".\ | |
| 145 | 145 | You can put here all the data files needed by your program. Note that they will be read-only. | |
| 146 | 146 | ||
| 147 | 147 | ### Configuration directory | |
| 148 | 148 | ||
| 149 | 149 | There are other places to store [[Multiplatform Programming Guide|configuration files]]. Configuration files should be originally created by the application itself (with default values), if they do not exist when the application starts. | |
| 150 | 150 | ||
| 151 | 151 | ### usr/share/applications directory | |
| 152 | 152 | ||
| 153 | 153 | To add your application to the Linux menu, you need to add a file called **project1.desktop** containing: | |
| 154 | 154 | ||
| 155 | 155 | `[Desktop Entry]`\ | |
| 156 | 156 | `Name=Project1`\ | |
| 157 | 157 | `Comment=Cool project`\ | |
| 158 | 158 | `Icon=project1`\ | |
| 159 | 159 | `Exec=project1`\ | |
| 160 | 160 | `Terminal=false`\ | |
| 161 | 161 | `Type=Application`\ | |
| 162 | 162 | `Categories=Graphics`\ | |
| 163 | 163 | `GenericName=Project1`\ | |
| 164 | 164 | `Keywords=feature1; feature2; feature3` | |
| 165 | 165 | ||
| 166 | 166 | This file is similar to a shortcut to your program. | |
| 167 | 167 | ||
| 168 | 168 | The **Categories** field is similar to the one in the **control** file. It can be for example: Communication, Database, Development, Editors, Electronics, Fonts, Games, Graphics, Math, Internet, Networking, News, Science, Sound, Utility, Video. | |
| 169 | 169 | ||
| 170 | 170 | The keywords help search through applications. | |
| 171 | 171 | ||
| 172 | 172 | Note that you need to provide the icon as a PNG file, either in the directory *usr/share/pixmaps* or in *usr/share/icons/hicolor*. | |
| 173 | 173 | ||
| 174 | 174 | #### usr/share/pixmaps directory | |
| 175 | 175 | ||
| 176 | 176 | Will contain the single-size icon of your menu shortcut in PNG format called **project1.png**. A medium size like 48x48 will be fine. | |
| 177 | 177 | ||
| 178 | 178 | #### usr/share/icons/hicolor directory | |
| 179 | 179 | ||
| 180 | 180 | Will contain the multi-size icon. Here is the directory structure: | |
| 181 | 181 | ||
| 182 | 182 | `icons`\ | |
| 183 | 183 | ` └─ hicolor`\ | |
| 184 | 184 | ` ├─ 8x8`\ | |
| 185 | 185 | ` │ └─ apps`\ | |
| 186 | 186 | ` ├─ 16x16`\ | |
| 187 | 187 | ` │ └─ apps`\ | |
| 188 | 188 | ` ...` | |
| 189 | 189 | ||
| 190 | 190 | There is a subdirectory for each possible size. You can display all the sizes currently defined on your system by writing: | |
| 191 | 191 | ||
| 192 | 192 | `ls /usr/share/icons/hicolor` | |
| 193 | 193 | ||
| 194 | 194 | In each apps folder, put an image with always the same name. If you project is called project1 then it will be called **project1.png** for most folders. In the scalable and symbolic folders you can put an SVG file. | |
| 195 | 195 | ||
| 196 | 196 | ### Documentation directory | |
| 197 | 197 | ||
| 198 | 198 | It will be called *usr/share/doc/project1* if your the package name is "project1". | |
| 199 | 199 | ||
| 200 | 200 | The folder contains the **changelog.Debian.gz** and **copyright** files and optionally the **README** file. | |
| 201 | 201 | ||
| 202 | 202 | #### changelog file | |
| 203 | 203 | ||
| 204 | 204 | The minimum changelog would be: | |
| 205 | 205 | ||
| 206 | 206 | `project1 (1.0) unstable; urgency=low`\ | |
| 207 | - | ||
| 207 | + | ||
| 208 | 208 | ` * Initial release`\ | |
| 209 | - | ||
| 209 | + | ||
| 210 | 210 | ` -- myname <myname@webserver.com> Tue, 19 May 2020 11:06:00 +0100` | |
| 211 | 211 | ||
| 212 | 212 | You can add many lines starting with * to indicate the list of changes in the version. The spaces at the beginning of the line are necessary. Only the line indicating the version starts directly at the beginning of the line. | |
| 213 | 213 | ||
| 214 | 214 | The latest version must be at the top of the file. | |
| 215 | 215 | ||
| 216 | 216 | The changelog must be compressed with maximum compression. To do that, supposing you already have the uncompressed **changelog** file, compress it with the following command: | |
| 217 | 217 | ||
| 218 | 218 | `gzip -9 -n usr/share/doc/project1/changelog.Debian` | |
| 219 | 219 | ||
| 220 | 220 | The -9 -n options are necessary for the package to follow the guidelines. | |
| 221 | 221 | ||
| 222 | 222 | #### copyright file | |
| 223 | 223 | ||
| 224 | 224 | If you provide the Deb package yourself, it is not mandatory to use the machine-readable format, however it will prepare you for publishing the package in Debian distributions. See: [[Debian package source|copyright in Debian package structure]]. | |
| 225 | 225 | ||
| 226 | 226 | ### usr/share/man directory | |
| 227 | 227 | ||
| 228 | 228 | Contains the user manual that you can view with the **man** command. It must contain at least **project1.1.gz** in the *man1* subdirectory, which will be the index page of your manual. | |
| 229 | 229 | ||
| 230 | 230 | The syntax is a bit peculiar. There are some tools to help but you still need to know the syntax. | |
| 231 | 231 | ||
| 232 | 232 | - description of the syntax: <https://liw.fi/manpages/> | |
| 233 | 233 | - editor with wizard and WYSIWYG preview mode: **gmanedit** | |
| 234 | 234 | - live preview editor (toggle to AN mode): <https://roperzh.github.io/grapse/> | |
| 235 | 235 | ||
| 236 | 236 | Here is a sample file: | |
| 237 | 237 | ||
| 238 | 238 | `.TH Project1 1 "19 May 2020" "" Project1`\ | |
| 239 | 239 | `.SH NAME`\ | |
| 240 | 240 | `Project1 - My cool project`\ | |
| 241 | 241 | `.SH SYNOPSIS`\ | |
| 242 | 242 | `.B project1`\ | |
| 243 | 243 | `[PARAMETER]`\ | |
| 244 | 244 | `.SH DESCRIPTION`\ | |
| 245 | 245 | `What my program does.`\ | |
| 246 | 246 | `.PP`\ | |
| 247 | 247 | `More description.` | |
| 248 | 248 | ||
| 249 | 249 | The manual, like the changelog, must be compressed using the following command: | |
| 250 | 250 | ||
| 251 | 251 | `gzip -9 -n usr/share/man/man1/project1.1` | |
| 252 | 252 | ||
| 253 | 253 | The -9 -n options are necessary for the package to follow the guidelines. | |
| 254 | 254 | ||
| 255 | 255 | --- | |
| 256 | 256 | *From the Free Pascal wiki, page "Debian package structure", as it stood on 2022-01-02 after a change by FTurtle, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
