All the code in the world is useless if no one can use it.

I’ve looked into packaging a few times in the past, but was always scared off by the complexity of Autotools. I’m a novice to the linux filesystem, and wasn’t sure what I wanted to do, let alone how to do it. Today, I took another stab, this time using MonoDevelop’s packaging features.

The first step to creating a package is to create the Application launcher. In MonoDevelop, you can do with by right-clicking on your executable project, selecting “Create New File”, and choosing a “Desktop Application Launcher”. This creates a .desktop file within your project, and gives you a nice GUI for editing it. You’ll want to change the “Name” to a human-readable name for your project (i.e. “Cardinal” instead of “cardinal”), and add at least one category in the “Menu Entry” tab. I chose the “Educational software” category for Cardinal.

Just creating the .desktop file isn’t enough–you need to tell MonoDevelop to include it when the package is installed. Right-click on the .desktop file, and select “Properties”. Check the box labeled “Include in deploy”. And you’re set!

Now that we have our launcher, we’re ready to create our package. Right-click on the Solution that you want to package, and select Tools > Create Package. On the next screen, it will ask you what kind of package you would like to create. For Cardinal, I chose a tarball, because that is the type of bundle that I am most familiar with. In the next screen, make sure all projects are checked. On the final screen, I accepted the default values. I would like to have changed the configuration from “Debug” to “Release”, but make yelled at me when I tried this. Something about Cardinal.Interface still being in Debug mode, it’s something that I need to look into. Finally, click “Create” to create the tarball in the solution’s directory.

Tarballs are nice because they work on any linux distribution. But typically, users don’t install software from source. In fact, we discourage them from doing so, since it is outside of the package manager’s control. So we need to create packages for specific distributions. The two most common formats are .deb (Debian) and .rpm (Red Hat). I use Ubuntu, a Debian derivative, so I decided to start with a .deb.

First, you probably want to move the tarball outside of the main directory for your source code. Extract it, and rename your tarball from *.tar.gz to *.orig.tar.gz. Then cd to the extracted directory, and run the command “dh_make”. When it asks you what type of package you want to create, type “i” for independent. dh_make will then create a /debian directory inside the current directory containing lots of useful template files. cd to this directory.

Debian has an excellent and detailed description of what goes in this directory here. If you need details, that is where you should look. I’m just going to give a quick summary of what I put in the (extremely simple) package for Cardinal.

We don’t need most of the example files, so do “rm *.ex *.EX” to get rid of them. I also got rid of “README.*” and “docs”, since I don’t yet have anything to put in them. This should leave 5 files: changelog, compat, control, copyright, and rules. If you’re like me and learn best by example, you can check out Cardinal’s versions of these files here. I borrowed heavily from Docky’s packaging to create them–here is a summary of each:

  • compat and rules don’t need to be modified, you don’t have to touch them.
  • copyright contains the license for the software. The best way to explain the format is with an example, so check out Cardinal’s copyright file.
  • control contains most of the metadata for the package, including the dependencies. The best way to understand is to read Debian’s explanation, or to check out the example in cardinal.
  • changelog is the only file that will be different for each release. It is just what it sounds like: a list of changes. The format is pretty self-explanatory from the example file. The one thing that tripped me up at first is that changelog actually specifies the name of the distribution that you are packaging for. So if you’re packaging for Ubuntu 10.04, for example, change “unstable” (Debian unstable) to “lucid” (Ubuntu 10.04 Lucid Lynx). Also, if you’re uploading to a PPA, you’re going to want to increment the version number each time. I.e., if you first uploaded with “cardinal (0.1-1)”, next time it should be “cardinal (0.1-2)”.

Once we’re done with /debian, we want to create the .deb file with the “debuild” command. If you’re uploading to a PPA, you want to use “debuild -S” to create a source package, rather than a binary package–Launchpad builds it for you. After working for a while, debuild will ask you for the password to your private key, to sign the package.

If all goes well, you’re done! You have a brand new shiny debian package, which you can distribute to your users for easy installation. If you want to upload it to a PPA (which is a good idea, since you’ll be able to update it), use this command: “dput [the name of your PPA] [the .changes file that was created by debuild]“. Note that this only works on Ubuntu Karmic+.

And that is how you package a Gtk# Application for Linux using MonoDevelop! I’m sure it’s done quite poorly–this is my first foray into packaging–so please leave a comment if there’s something I can improve or clarify! I wont get offended, and I appreciate your help.