1. Figure out the dependencies
Before one starts with the actual package building, one should cleanup and fix the projects source code itself. This basically means getting a rough overview of what the dependencies are and which of those are already available in Ubuntu. If something is not in Ubuntu it either needs to be moved into the source tree or packaged separately.
2. Write a Makefile and make sure that all targets work
You need to make sure that your Makefile can not only build the project, but also install it and handle PREFIX and DESTDIR properly, namely the following targets should work:
- ./configure --prefix=/tmp/foobar
- make install DESTDIR=/tmp/
- make clean
3. Native vs non-native packages
Deb packages come in two forms, native ones and non-native ones. The core difference is that non-native ones come with an .orig.tar.gz, that contains the original source code, and a patch file, that contains your changes, while native ones just come with a single tarball. Native packages make only sense for things for which the .deb release is the primary and only release in existence, for software that is supposed to be released via a normal .tar.gz release a native package are never the right choice.
To make it short: You want to build a non-native package.
4. Version numbers
Version numbers for packages are build in the form of: UPSTREAMVERSION-DEBIANREVISION
UPSTREAMVERSION is the version number of your package, i.e. 1.2.3, while DEBIANREVISION is normally just an integer giving the version of your deb package. The package build scripts will take the version number out of the debian/changelog file.
For packages that are based on a development version directly out of SVN, Git, etc. you want a non-standard version number that smoothly integrates with official releases To accomplish that you have basically two ways "0.1.2~svn1234" and "0.1.2+svn1234". The tide (~) character is special in that it lowers your version number, not increases it, so "0.1.2" is larger then "0.1.2~svn1234", which makes this numbering scheme extremely useful for pre-releases, beta version and all that stuff that comes before a final release. The plus (+) on the other side increases the version number, so "1.2.3" is small then "1.2.3+svn1234". This is useful for cases where the next release is still far of, but SVN contains some small bug fixes that you want to package.
If you are not sure about version numbers, you can use dpkg to test them:
dpkg --compare-versions "0.1.2" ">" "0.1.2~svn123" && echo "Yes" || echo "No"
5. Where to store the debian/ directory
Deb packages are build by having some meta data and scripts in a debian/ directory in the source code of your project, however you do not want to have the debian/ directory to actually be in your repository. The reason for that is that it muddles the borders between Ubuntu specific hacks and your main source tree. Things are cleaner and easier when you keep them separate and all package build tools basically assume that.
Luckily you don't have to keep things managed manually git-buildpackage will do most of the work for you and automatically track what changes you do to the upstream source tree. So here is how it works:
- build a normal tarball release of your source code
- go to an empty directory (named ubuntu/ here) and create in that directory a directory named after your project, we need two levels of directories here since git-buildpackage will store files in "../"
- go to ubuntu/project/ and call: git init
- call: git-import-orig -u 0.1.0 ../../path/to/project-0.1.0.tar.gz
6. Creating the initial debian/ directory
Once you have imported the upstream source into git, you can start creating the debian/ directory. dh_make is a tool that will provide some guidance in the process, but you can also just copy a debian/ directory from another project and modify it, which can often be easier. The following files are important:
- changelog: This contains the version number of the package as well as a comment for the release
- control: This contains metadata, such as the project name, a description, etc. the Build-Depends field is where you have to enter all the dependencies, the Dependencies for the binary itself can be figured out mostly automatically
- rules: This is the Makefile that will be used to build the package, you might notice that the default one is extremely short, containing not much more then "dh $@"
- copyright: This describes the copyright of the package
7. Fine tuning debian/rules
The debian/rules script will call dh and automatically try to guess what build system your program is using and call the appropriated scripts, when things don't work, you don't need to get rid of dh, instead you can override steps of the build process. To override the install process you would simply add a target like this to debian/rules:
override_dh_auto_install:
make install PREFIX="/usr" DESTDIR="$(CURDIR)/debian/xboxdrv"
To override the build process you would use override_dh_auto_build.
8. Building the package
If you think the debian/ directory is finished, you can start to build the package. Go to the top level directory and execute:
git-buildpackage --git-ignore-new
Normally when your repository contains uncommited changed, the process would fail, but --git-ignore-new allows it to continue. When everything went well, you should end up with a bunch of packages in "../", if stuff went wrong, you should have gotten a easy to read error message.
When running git-buildpackage it will do a "make clean" before each build, which can be annoying when you try to find an error late in the build process, to work around that you can also simply call debian/rules binary directly.
9. Testing the package
To test the package just install it with dpkg -i, you might also want to look at the content with dpkg-deb -c, if the build script contains a bug, its easy to have a few files gone missing, this way thats easy to spot.
10. Building the package in a clean environment
If you have successfully build and tested your package, you are not done yet. You also want to make sure that it builds and works on a clean installation. Luckily you don't have to install a new Ubuntu or manually mess around with chroot, the pbuilder script will do that automatically for you. Simply apt-get install pbuilder and then call:
sudo pbuilder --create
Once pbuilder is finished downloading and installing the necessary components, you might also want to run:
sudo pbuilder update --components "main restricted universe multiverse" --override-config
This will allow you to not only use standard Ubuntu packages, but also things from universe and multiverse, which you will likely need for any more complex package.
Once pbuilder is completly finished the actual package building is just a matter of:
sudo pbuilder --build yourpackage_version.dsc
pbuilder will automatically grab all the build dependencies and build your package, if successful it will put the results in /var/cache/pbuilder/results/.
11. Building source packages and tagging your repository
Once you are completly done with the testing and building in a clean environment you want to finish up and publish your results, to do that you have to build a source package and while at it, you can also tag your repository automatically with the right version number with:
git-buildpackage --git-tag --git-builder="debuild -S"
12. Uploading your packages
You don't want to upload a raw .deb, instead you want to provide a complete apt repository, luckily this process is completly automatic, all you need is create yourself an account at https://launchpad.net/ and upload your GPG key. Once done, you can simply upload your package with:
dput ppa:your_username/ppa package_version-1_source.changes
Launchpad will take the source code and build it automatically for i386 and amd64.
Note: I am not sure why dput wants sources.changes, while pbuilder is happy with .dsc.
13. Using your package
To finally use your finished and release package you just have to add the PPA to your apt sources, which can be done with:
sudo add-apt-repository ppa:your_username/ppa
sudo apt-get update
sudo apt-get install your_package
14. Getting your package accepted into the official Debian/Ubuntu repositories
[TODO]
Trouble
- Sometimes build files slip into the git repository, not sure when or why this happens, I guess it is at the git-import-orig step when you import into a non-cleaned working directory
- Some files tend to constantly get in the way, namely .pc, debian/${yourproject}/, debian/${yourproject}.debhelper.log and debian/${yourproject}.substvars not sure why they get left over and not cleaned up

1 comment:
Thanks for this write-up.
-- steve
Post a Comment