Creating a Debian package of a Go project

Go is all the rage these days, and I decided to give it a try. And as my company uses Debian packages to distribute our software, I need to package my new Go-written project for Debian. Mark Stapelberg has done a lot of leg work to find the best (and official!) ways of packaging Go projects for Debian. His Go Packaging page on the Debian wiki explains the “official” Debian way to build such a package, but it is painfully sparse when it comes to the technical details of how to build a Debian package of a Go project. So this is my ils of how to build a Debian package of a Go project. So this is my attempt to clarify some of the technical questions and their answers as I have them while building my first Debian/Go package.

This document is a work-in-progress, and I will be updating it as I progress with my Go/Debian project.

If you find any inaccuracies or outdated info on this page, please contact me, so that I can update it!

First, some background on Go development. This ought to be familiar to any Go developer, but some details are Debian-specific. From How to Write Go Code, we learn that all of our Go projects ought to live in a single, specific, directory structure, as such:

bin/
    hello                          # command executable
    outyet                         # command executable
pkg/
    linux_amd64/
        github.com/golang/example/
            stringutil.a           # package object
src/
    github.com/golang/example/
        .git/                      # Git repository metadata
	hello/
	    hello.go               # command source
	outyet/
	    main.go                # command source
	    main_test.go           # test source
	stringutil/
	    reverse.go             # package source
	    reverse_test.go        # test source

The important thing for us is to know which part of this tree comprises our Debian package. In the above directory tree, each of hello/, outyet/, and stringutil/ has the potential to be a Debian package. If we were to add debian/ directories to each of these, we would end up with the following structure for src/:

src/
    github.com/golang/example/
        .git/                      # Git repository metadata
	hello/
            debian/
	    hello.go               # command source
	outyet/
            debian/
	    main.go                # command source
	    main_test.go           # test source
	stringutil/
            debian/
	    reverse.go             # package source
	    reverse_test.go        # test source

Within the debian/ directory, you can create a standard Debian package using whatever means you prefer. I will only discuss the changes that are necessary for a Go project.

If your package will be used by others, you’ll want to follow the official Debian Go packaging guidelines, and use dh-golang which require you to Build-Dep on all of your dependencies (as normal!), and you should use the default debian/rules file. This will set your $GOPATH to /usr/share/gocode during the build process.

If, however, you are building a Go package just for your personal, internal use, or for testing purposes, you may wish to build a Debian package which has dependencies which are not packaged for Debian. This is a bit trickier (since it’s not supported by the official tools), and will result in a package that is unacceptable for the Debian (or Ubuntu) mirrors. But it can be quite useful, and this is precisely what I wanted to do. To do this, I started with the default debian/rules file linked above, then added a few changes. This is what I came up with:

#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
GOPATH := $(shell cat ~/.gorc /etc/gorc 2> /dev/null | grep ^GOPATH= | head -n1 | cut -d'=' -f2)

GO := GOPATH=$(GOPATH) go
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1

export DH_GOPKG := efsgithub.securewebportal.net/dc/golang-dc/dc-ldap

%:
	dh $@ --buildsystem=golang --with=golang

override_dh_auto_build:
	echo start
	$(GO) get
	$(GO) build
	echo end

override_dh_auto_test:
	$(GO) test

override_dh_auto_clean:
#       List any files built by your project here, to be removed by the 'clean' process
#	rm ...
	dh_auto_clean

With this debian/rules file, it is necessary to create a file, either ~/.gorc or /etc/gorc which contains, at least, a single line specifying your $GOPATH (in Bash syntax). Mine looks like this:

GOPATH=/home/jonhall/go

For additional reading:

Leave a Reply

Your email address will not be published.