Tuesday, August 24, 2010

Is packaging new software hard?

EDIT 1: Sorry Planet readers. I tried adding a "read more" thing to shorten it, but apparently that doesn't change the RSS feed, just the blog's front page. And yes, I will fix up the Ubuntu Wiki later.



A common answer to my question about why people aren't packaging is that packaging is hard and the wiki is kind of lacking. Debhelper 7 and Source Version 3.0 (the new Debian packaging format) make things a lot easier.


So is it hard? In the common case, no.


EDIT 2:Switched from "native" to "quilt" since as pointed out in comments, it makes for a smaller upload and debuild can deal with directly-applied patches in the case that you don't know how to use quilt.



Assuming the software you want to package uses something like Python distutils ( python setup.py build && sudo python setup.py install) or Autotools (./configure && make && sudo make install), Debhelper 7 makes things really straightforward.



Backing up, there are 4 files necessary in the debian/ directory:



  • rules

  • control

  • copyright


  • changelog


There are two more files you can include that act as a sort of metadata for what sort of package you're making:



  • compat

  • source/format



Assuming you want to make a Source Version 3.0 quilt package with Debhelper 7 (this is pretty normal these days):



  1. Rename the original source tarball to have the form <package name>_<upstream version>.orig.tar.gz

  2. Unpack the source and change into the unpacked directory: tar xf foo_bar.orig.tar.gz && cd foo


  3. Make a debian directory and enter it: mkdir debian && cd debian/

  4. Now it's time for those files


EDIT TO ADD

Generation


Good news: The version of dh-make in Debian SVN appears to support Debhelper 7.


Bad news It doesn't parse command line arguments properly.



In the meantime, you can use the old one to generate everything but the debian/rules file. If only a single deb will be produced, and it's under the GPLv3, that'd be dh_make -c gpl3 -s Then you'll just delete files not listed above and the debian/rules file and instead put in a debian/rules containing what I'm about to tell you below.


PS: I'm told dh_make is a pretty unclean way to do things. It's probably best if you just copy and paste the examples, then modify.



debian/rules


The boilerplate debian/rules file for standard build systems when you don't need to pass special configure options is:



#!/usr/bin/make -f

%:
dh $@

Note that that is a tab, not a bunch of spaces, before the "dh". This used to be the most difficult file to write, which is why I used to use dh_make to generate it. Debhelper 7 made it so much easier!



debian/control


This one is long, but it's pretty easy to fill in the blanks. It's the only file of the bunch for which you might continue to need a reference. Here's how the control file should look:



Source: foo
Section: bar
Priority: optional
Maintainer: Foo <foo@example.com>
Build-Depends: eeny-dev, meeny-dev, miney, moe, debhelper (>= 7)
Standards-Version: 3.9.1
Homepage: http://foo-project.org

Package: foo
Architecture: all
Depends: eeny, meeny, miney, moe
Description: does stuff
Foo does stuff blah blah blah blah to make things easier for users to
do whatever they need to do. Long description here.

Source package stanza


  • Source: Put the source package's name. This should be the same as the package name on the orig.tar.gz.


  • Section: For the list of valid Sections, see the Debian Policy Manual section on this. In Debian, you will put something like "non-free/kde" while in Ubuntu only the subsection (kde) is listed and the archive admins put it into the right section. In Debian, if the section is main, just list the subsection.

  • Priority: "optional" is what you want for most applications. Again, see the Debian Policy Manual section on Priorities for other options.


  • Maintainer: your name and email address if you are submitting to Debian, or if you are submitting to Ubuntu, put "Ubuntu Developers <ubuntu-devel@lists.ubuntu.com>"

  • Standards Version: current one (as of August 2010) is 3.9.1, and you shouldn't be starting from an out-of-date one


  • Homepage: the project's homepage

Binary package stanza


Now for the binary packages generated by the source package. For most applications, there will only be one binary package generated, but if there's more than one, just repeat the second stanza of this file once for each one, of course changing the values on each line.



  • Package: name of the binary package (the deb). Use logical names. If there's only one, feel free to repeat the source package's name.

  • Architecture:
    • all: if it can be built once and run anywhere (common for Python)


    • any: if it needs to be built everywhere

    • Otherwise, a list of architectures

  • Description: put a short description after the colon that can fill in the blank at the end of "$PACKAGE_NAME _____" with a short verb phrase (< 80 characters). On the lines below, put the long description with a single space at the beginning of each line. If you want a blank line, put a space and a period.


Build-Depends and Depends


I kept skipping the bit about Build-Depends and Depends. For these, you want to list the names of other binary packages (not source packages!). If a particular version is needed, parentheses and mathematical symbols (like where I put "debhelper (>= 7)") are used.


Usually -dev packages will be in the Build-Depends since that's where header files are in Debian and Ubuntu while non-dev packages will be in the binary package's Depends. You don't need to figure this stuff out completely on your own. The upstream README and INSTALL files should list what libraries are needed. If they're not, complain to upstream about bad documentation!



If you don't know what package provides a certain library, sudo apt-get install apt-file &&apt-file update then use apt-file search to find what package provides it.


Notes



These are the required lines. There are more available in the Debian Policy Manual (I keep referring to that, huh? It's useful!), such as Recommends and Suggests. How do these compare with Depends?

  • Depends: absolutely must be installed in order for the software to work

  • Recommends: useful and common to have with the package but not completely necessary.


  • Suggests: you want apt to notify the user that there's some other software that's kind of useful to use with it

Recommends are installed by default in Debian and Ubuntu nowadays, but some people disable them using sudo apt-get install --no-install-recommends foo, so the difference between Depends and Recommends is important. There are more less-commonly-used package relationships too, but you can read the Policy Manual for that.



PS: If you're packaging a Python app, "${python:Depends}" goes in the binary package's Depends line to avoid typing it all out.


I always find writing a good description to be the hardest part.



debian/copyright


The debian/copyright file is a pretty straightforward fill-in-the-blank.


This package was debianized by Your Name <you@example.com> on
Tue, 24 Aug 2010 20:05:25 -0400

It was downloaded from http://example.com


For the timestamp, run date -R and copy that in there. Make sure the copyrights are listed next, something like this (the COPYING or LICENSE file should have this at the top):


Copyright
© 2010, Author Name <author@example.com>

Double check this by running licensecheck -r in the top level code directory.



License:
The code files in this package are under the GNU General Public License
version 3:
| This program is free software: you can redistribute it and/or modify
| it under the terms of the GNU General Public License as published by
| the Free Software Foundation, either version 3 of the License, or
| (at your option) any later version.

| This program is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU General Public License for more details.

| You should have received a copy of the GNU General Public License
| along with this program. If not, see <http://www.gnu.org/licenses/>.

The full text of the GNU General Public License version 3 is available on
Debian systems in /usr/share/common-licenses/GPL-3.

Depending on licensecheck's output, you may need to list multiple licenses.



debian/changelog


This is the easiest of the files that require you to do any thought. Run dch -i --create, fix your email name and email address to match who you are, and put in an explanation. In future, you'll just run dch -i to add another entry. Explain what you did to the package. In this case, it'll likely just be "Initial release" which is pretty simple. dch should set the right version number. It'll look something like:



foo (0:1.0-0ubuntu1) maverick; urgency=low

* Initial release

-- Your Name <you@example.com> Tue, 24 Aug 2010 20:05:25 -0400

The first bit is the same as the source package name and will automatically be filled in. The part in parentheses is the package version. It is in the form <epoch>:<upstream version>-<debian version>ubuntu<ubuntu version>



If you're doing the initial packaging, the epoch is 0, and the upstream version will be automatically filled in from the .orig.tar.gz.


  • Debian: Debian version will be 1

  • Ubuntu: Debian version is 0 and Ubuntu version is 1


  • PPA: put 0s for both of those and add +ppa1 (or +yournick1 or whatever)

Next comes the version of Debian or Ubuntu for which you are packaging. Leave urgency at low for now. You're packaging an app, not the kernel. It just affects how quickly the build servers get around to it, and abusing this field will make people Not Happy.



Other files



For the debian/source/format and debian/compat files, just run echo "7" > compat and mkdir source && echo "3.0 (quilt)" > source/format



Time to build!



The hard part is done, and that really wasn't very hard given it's pretty much just fill-in-the-blank the whole way. Now to build and test. My preferred way to test builds is to use pbuilder. It uses a minimal chroot, so your build-dependencies get tested too.



  1. Install the build dependencies you listed in debian/control

  2. sudo apt-get install pbuilder ubunt-dev-tools devscripts (If I missed any, tell me in comments)


  3. Generate the source package: debuild -S—a .debian.tar.gz, a .dsc, and a .changes file will show up in the same directory as the .orig.tar.gz

  4. Make a pbuilder to build your package: ln -s /usr/bin/pbuilder-dist ~/pbuilder-maverick && ~/pbuilder-maverick create—substitute in whatever version of Debian/Ubuntu you are building for (same as you listed in changelog)


  5. Build the source package: ~/pbuilder-maverick build ../foo*.dsc—.debs will be output in ~/pbuilder/maverick_result


PS: The "make a pbuilder" step only has to be done once per release on which you intend to ever build. Keep it up to date with ~/pbuilder-maverick update



If it all builds successfully, congrats! If it doesn't, either you forgot a build dependency or it's not a wonderfully straightforward application and you should visit #ubuntu-packaging on Freenode or #debian-mentors on OFTC for help debugging. We're friendly!



Test


Install the debs and test it out.



Upload


You'll need to sign the package before you can upload it anywhere, if it didn't get signed when you ran debuild (the output would have told you if it did). Generate a GPG key and use debsign -k<your key ID> foo*.changes to sign it. If you're working on Ubuntu, add your key to Launchpad or if Debian add it to Debian Mentors. Then run dput mentors foo*.changes for Debian Mentors or dput revu foo*.chanes for Ubuntu's REVU (where new packages are reviewed by MOTU for inclusion in the archive). You'll get feedback from a mentor or a MOTU, improve your package based on that, and then someone will sponsor it. Or you can upload to a PPA with dput ppa:user/ppa foo*.changes

No comments:

Post a Comment