You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
5.7 KiB
Markdown

# Packaging Go Binaries for a Debian OS
This is a primer on Debian packaging for Go. Contained in this project are Makefile targets that are used to create a binary package (`.deb archive`) of the project.
## Tooling
Some key tools should be present on your system before you begin.
```
sudo apt-get install build-essential devscripts debhelper
```
This command installs:
- `build-essential`: A meta-package that pulls in the essential tools for compiling software, such as gcc and make.
- `devscripts`: A collection of scripts that are incredibly helpful for Debian package maintainers.
- `debhelper`: A suite of tools that simplifies the packaging process by automating common tasks.
It is assumed your Golang dependencies are already met.
## Source vs Binary Packages
A source package typically contains the source code of the upstream project in a `.tar.gz` file, patches made by the package maintainer, then a Makefile file `debian/rules` is used by the system to compile the code and create a binary package. These source packages cannot be directly installed, but they are highly portable and sometimes required for security auditing.
You are probably more familiar with binary packages. These are pre-compiled packages that are ready to install. They typically consist of the pre-compiled binary, configuration files, man pages, and other necessary data files. The contents are organized into a specific directory structure that a package manager (.e.g. `apt`) will place on to your file system.
Binary packages need to be compiled for a specific processor architecture (e.g. x86_64 ARM64). Most times these are built for a specific operating system and version too. A benefit to this process is that dev tools do not need to be installed for a user to make use of the package.
This project focuses on building a binary package.
## Package Files and Structure
When building a Debian package you must create a `debian/` directory which in a typical build process will contain a number of essential files.
- `debian/control`: Contains essential metadata about the source package and the binary package(s) it will create. This includes the package name, version, dependencies, maintainer information, and a description of the software
- `debian/rules`: This is an executable Makefile that automates the building of the package. It has targets for compiling the software (build), installing it into a temporary directory (install), and creating the final .deb archive(binary). Modern rules files are often very simple, relying on `debhelper` to do the heavy lifting
- `debian/changelog`: This file documents the changes made to the Debian package, not the upstream software. It follows a strict format and is used by the build tools to determine the package version.
- `debian/copyright`: This file specifies the copyright and license of the software. It's a legal requirement and should accurately reflect the licensing terms of the upstream source code and any modifications made for the Debian package.
- `debian/compat`: This file specifies the `debhelper` compatibility level, which ensures that the build process is consistent even as `debhelper` evolves.
- `debian/source/format`: This file indicates the source package format (e.g., 3.0 (quilt))
A binary package for can be constructed for Go with as little as a `control` and `changelog` file. Since this primer is focused on a minimal packaging process for your own golang project, we will focus on the `control` file and the `changelog`.
### Control File
The `debian/control` file
- control
### Changelog
The change log is not a change log of the upstream, it is a changelog of the Debian package. This file has a specific format that needs to be adhered to, or the build will fail.
A `debian/changelog` file is a plain text file with a series of entries, where the newest entry is always at the very top. Each entry has a precise format:
```
package-name (version) distribution(s); urgency=level
* Change details for the first change in this version.
(This can wrap to multiple lines if indented).
* Change details for the second change. This could be a bug fix.
(Closes: #bug-number)
-- Maintainer Name <maintainer@example.com> Day, dd Mon yyyy hh:mm:ss +zzzz
```
The `devscripts` package installed earlier can assist in automating the change log changes, and ensure that they correctly formatted.
## Debian Versioning Scheme
`[epoch:]upstream_version[-debian_revision]`
- `epoch`: small, rarely used integer that helps correct mistakes in past versioning by ensuring a new version is seen as "later" than an old one
- `upstream_version`: The main version number from the original software developer, which can contain alphanumeric characters and symbols like periods, hyphens, and colons
- `debian_revision` is appended by the package maintainer to signify changes to the packaging itself, such as updates to dependencies or build scripts, without any change to the upstream software
When assessing versions `dpkg`'s algorithm evaluates the string from left to right, with special rules for characters like the tilde (~), which indicates a pre-release version and sorts before a final release of the same number.
## A Manual Packaging Process Example
Let's assume we have a `foo` v0.1.0 program that we would like to offer as a debian package.
`go build -o ./build/foo .`
Create a the debian package structure.
```bash
mkdir -p ./dist/foo_0.1.0-1/DEBIAN
mkdir -p ./dist/foo_0.1.0-1/usr/local/bin
```
Copy the binary to the `usr/local/bin/` directory under our package namespace and ensure it's executable.
```bash
cp ./build/foo ./dist/foo_0.1.0-1/usr/local/bin/foo
chmod +x ./dist/foo_0.1.0-1/usr/local/bin/foo
```
Now create a `control` file under the `DEBIAN/` directory
```bash
touch ./dist/foo_0.1.0-1/DEBIAN/control
```
```
```