Packagecloud logo

Building debian packages with debuild

TL;DR

This post will walk you through creating a debian package from a simple hello world C program using debuild.

 

Setup

On a debian-based system, install the following programs:

$ sudo apt-get install devscripts build-essential lintian

The debuild tool

debuild is a convenient wrapper around dpkg-buildpackage, fakeroot, lintian, and debsign. It handles all the packaging linting, and signing for us. Let’s use it to package a simple “helloworld” program.

 

Our “Hello World” program

It consists of the source file main.c:

#include <stdio.h>  
int main (int argc, char *argv[]) {  
  printf("Hi\n");  
  return 0;
}  

And a Makefile:

helloworld:
	gcc main.c -o helloworld

install: helloworld
	install -m 0755 helloworld /usr/local/bin

 

Building and Testing

Let’s make sure everything works before we package it up.

Run make to build the program. This should create a helloworld binary you can execute by running ./helloworld.

You should see “Hi” printed to the screen.

Then, try installing the binary: run sudo make install and now helloworld should be in /usr/local/bin.

Remove our test binary before continuing:

$ sudo rm -rf /usr/local/bin/helloworld

 

Packaging our program

Note: debuild will make use of symlinks in it’s build process, so if you are using a Virtualbox or VMware Shared folder to build your package, it will not work.

Now that we’ve verified everything works, let’s create a debian package for it:

1. Create a debian/ folder

This is where all of our debian specific packaging files will go.

 

2. Create a debian/control file

This file describes your package using debian control fields. Below we have defined a binary package and a corresponding source package (from which the binary package can be repackaged):

Source: helloworld  
Maintainer: Julio Capote <julio@packagecloud.io>
Build-Depends: debhelper (>= 8.0.0)
Standards-Version: 3.9.3
Section: utils

Package: helloworld  
Priority: extra  
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}  
Description: a simple helloworld package
 Just prints "Hi", it's very useful.

 

3. Create a debian/changelog file

This file tracks all the changes to the package. You need a minimum of one entry to build a package.

The syntax of this file is tricky, so while you can create this file by hand, it’s recommended to use the debchange tool, or dch.

To initially create the changelog, type:

$ dch -i --create

This will bring up your $EDITOR and let you edit the fields. Make sure you change UNRELEASED to unstable. Check out the dch man page and the debian changelog policy for more details.

helloworld (0.0.1) unstable; urgency=low

  * Initial release.

 -- Julio Capote <julio@packagecloud.io>  Sun, 07 Jun 2015 22:07:56 -0700

 

4. Create a debian/rules file

This file tells debian specifically how to build your package. The most basic implementation just passes all calls to the original Makefile created above:

Note: Make sure you use hard tabs here, since it uses the same format as Makefile

#!/usr/bin/make -f  
%:  
	dh $@

 

5. Create a debian/copyright file

To pass lintian, you need a copyright file (however, it can be blank). Ours can be very simple:

Copyright 2015, Computology LLC.

 

6. Run debuild to build your package.

$ debuild -us -uc

 

Error!

If you were following along, you’ll notice the package doesn’t build and returns the following error:

install: cannot create regular file `/usr/local/bin/helloworld': Permission denied

This is because debuild ran make install and failed because it did not have permissions to write to /usr/local/bin/ (hardcoded in our Makefile above).

As you can imagine, most software will not package cleanly out of the box for reasons like the above. In such cases, a more specific debian/rules file will be needed. Let’s override the install directive of our Makefile during packaging in our debian/rules file:

#!/usr/bin/make -f  
%:  
	dh $@
override_dh_auto_install:
	install -D -m 0755 helloworld $$(pwd)/debian/helloworld/usr/local/bin/helloworld

Now run debuild -us -uc again and the package should build successfully. To see your built package, navigate backwards into the parent directory of the source folder. You should see:

helloworld_0.0.1_amd64.build    # build log file
helloworld_0.0.1_amd64.changes  # changelog and checksums
helloworld_0.0.1_amd64.deb      # binary package
helloworld_0.0.1.dsc            # source package
helloworld_0.0.1.tar.gz         # original source directory

 

Sign your package with GPG and debsign

Refer to our other post on this topic: GPG signing debian packages with debsign.

Conclusion

Creating debian packages gives you full control over how a program is compiled and the specific version being packaged. Uploading those packages to packagecloud lets you easily distribute them to all of your machines, exactly how you built it.

You might also like other posts...