On manually creating click packages

After my last post, praising how easy it is to manually create click packages even if QtCreator doesn’t support that for compiled apps yet, I got requests from various people asking me to share the knowledge. So here is how I did it:

* Build your application for the arm architecture. You can either use a pbuilder environment to create a armhf.deb package and extract it again afterwards or just compile your stuff on the phone (or in an arm chroot). I won’t go into much details on this as I assume everyone writing a C++ app knows how to compile it. Compiling it directly on the phone might be the easiest way to get some binaries for now. Just copy the whole source tree to the phone and just use qmake/cmake and make as used from the desktop.

* Create a new directory and copy all the reqired binaries into that. Also copy QML files, .desktop file and application icon into that directory. In the end, everything required by your application should be in there. Don’t put any stuff in there that shouldn’t end up in the package (e.g. .cpp files, .moc files etc)

* Test running your application from within this directory. Your application should be able to start up from there, not requiring anything to be installed to /usr or similar. In case your C++ code loads QML files, it needs to find them relative to the binary’s location.

* Make sure the .desktop file’s Exec entry starts up the application from the local directory, e.g. calling it as “./myapp” instead of just “myapp”. Also make sure the icon filename is relative to the location of the .desktop file.

* now create a manifest.json. Here’s an example (from uFit) of what it should look like:

{
"description": "Ubuntu FitBit app",
"framework": "ubuntu-sdk-13.10",
"hooks": {
"ubuntu-fitbit-app": {
"apparmor": "ubuntu-fitbit-app.json",
"desktop": "ubuntu-fitbit-app.desktop"
}
},
"maintainer": "Michael Zanetti ",
"name": "com.ubuntu.developer.mzanetti.ubuntu-fitbit-app",
"title": "uFit",
"version": "0.1"
}

* Create <appname>.json file. This one is responsible to request permissions for certain capabilities at AppArmor. This step is the equivalent to the one described here: http://developer.ubuntu.com/publish/packaging-click-apps/
Here’s the example of uFit:
{
"policy_groups": [
"networking"
],
"policy_version": 1
}

Add any additionally required policy_groups as a comma separated list. Check out the above link for a list of possible values.

* We’re almost done. It’s time to create the package:
# click build <directory>

This should produce the click package ready to be uploaded in the current directory. But wait, you probably want to test it on your phone before actually uploading it, right? So here’s how you do that:

# sudo click install com.ubuntu.developer.<yourID>_<packagename>_<version>.click
# sudo click register --user=phablet com.ubuntu.developer.<yourID>_<packagename> <version>

Now you should be able to find the app by searching the Application lens and you should be able to run it from there. If it doesn’t start, get to a commandline and do this:

# tail -f /home/phablet/.cache/upstart/unity8.log

Watch the output that happens when you try launching the app. It should tell you what’s wrong with it.

Hope this helps!

UPDATE
Very useful tip from Colin in the comments:
You can install and register in one step by passing –user=phablet to click install, but it’s better to just use “pkcon install-local foo.click”.

7 comments:

  1. Thanks for the info. Unfortuantely, it seems that your idea of simple is a bit different from mine :). Two questions that you may or may not know the answer to:

    1) If I create and install a click package on my desktop, will it run under the apparmor restrictions automatically, or is there something else I would need to do. My app needs filesystem access, so I really need to test that I’ve got the profile right!

    2) Given that I don’t have an ARM device to compile on and am unfamiliar with both building deb files and chroots, which would be the easiest for me to learn to do cross-compilation.

    Thanks again for the description — it’ll be a big help!

    1. What can be more simple as copying all the stuff you need into a single directory and calling “click build” on it? Ever tried packaging a an RPM or .deb?

      1) I would assume yes.
      In case you want to test how your app behaves in AppArmor, you can explicitly run it like this (replace the -p stuff with your appId):
      aa-exec -p com.ubuntu.developer.mzanetti.ubuntu-fitbit-app_ubuntu-fitbit-app_0.1 — ./myapp

      Also, not that if you install a click package on desktop you need to compile it for i686 or amd64 and package up that stuff.

      2) if you don’t have an arm device I suggest setting up a chroot:
      # sudo apt-get install pbuilderscripts
      # pcreate -a armhf -d saucy saucy-armhf
      Now you should have a saucy arm system in /var/cache/pbuilder/saucy-armhf.tgz. Extract that to some directory, but keeping file system permissions, so do it as root and use -p.
      # mkdir saucy-arm-chroot
      # cd saucy-arm-chroot
      # sudo tar -zxpf /var/cache/pbuilder/saucy-armhf.tgz
      # cd ..

      Now it’s time to enter the chroot:
      # sudo chroot saucy-arm-chroot /bin/bash

      That’s it. Everything you compile in here produces arm binaries.

      1. The only thing I’ve ever packaged were Python packages. The very phrase “cross-compilation” strikes fear into my heart! :)

        Thanks for the very detailed instructions — it’s much more than I was expecting or deserve. I’ll give it a go this evening and see what happens.

      2. The instructions for the chroot environment seem to have worked just fine. For the benefit of the home audience, I’ll point out that you also need to install the various things you need to compile your project in the chroot. I managed this by installing qt5-qmake, qtdeclarative5-dev, qt5-default, and their dependencies, though there may be a more minimal solution. (Presumably you could just install the ubuntu-sdk package and be done with it, but only if you have more bandwidth than I do.)

        Building the click packages seems to be working too, whether in the chroot or not, but installing them on a desktop is another issue. Colin’s pkcon command gives me a handful of critical GLib assertions followed by a Python execption: dbus.exceptions.UnknownMethodException: org.freedesktop.DBus.Error.UnknownMethod: Unknown method: CreateTransaction is not a valid method of interface org.freedesktop.PackageKit. The click install command worked until I added an apparmor profile; now I’m getting various error messages that depend on the version number I give the click package. I’ll ask about this on IRC tomorrow.

  2. You can install and register in one step by passing –user=phablet to click install, but it’s better to just use “pkcon install-local foo.click”.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>