There is some information available on the Ubuntu developer portal on building Click applications. But this mostly covers pure QML applications or QML applications with a C++ shared library, all with the Ubuntu SDK IDE (rebranded Qt Creator).
If you care about what is happening below this level, there is not that much info available, at least not in one place. I found:
- Great blog post on the click command. This explains what happens below the hood when creating or upgrating "kits" (chroots with toolchains) and building.
- Click specification (the source being here). This defines what a click package contains, how it relates to deb packages, how it's installed, etc. Unfortunately it doesn't contain all that is actually required of a Click package to work on a phone with Ubuntu.
- Click security. This discusses the AppArmor file that needs to be included and how it's referred to from the manifest.
So I thought I'd experiment with building Click packages a bit.
Let's try to create a minimal (sort-of) working Click package.
The simplest package can be created from a directory containing the following files:
- manifest.json
- $APPNAME.desktop
- $APPNAME.png (or some other format) - the icon used by to display the app in the launcher
- $APPNAME.apparmor - an AppArmor file specifying capabilities the application requires
- the application itself
A minimal manifest.json looks like this:
{ "name": "zub.hello-world", "title": "Click minimal app", "description": "Test of a minimal click package.", "version": "1.0", "maintainer": "Author <author email>", "architecture": "armhf", "framework": "ubuntu-sdk-15.04", "hooks": { "hello-world": { "apparmor": "hello-world.apparmor", "desktop": "hello-world.desktop" } } }
The name field specifies the name of the package. There are some rules for what the name has to fulfill, one of these being it must be lower case. If you break the rules, launching the package on the phone from Ubuntu SDK IDE fails with the not-so-helpful error message:
** (process:14951): WARNING : Unable to find keyfile for application 'PlainProjectTest.zub_PlainProjectTest_0.1'**
The conventions for package names are not clear for me. Canonical uses names like com.canonical.scopes.bbc or com.ubuntu.camera (so, the Java way), but many third-party packages use names like falldown.rpadovani, neverputt.lb or shorts-app.mrqtros (reverse of the Java style).
The architecture is either all (for pure QML apps that contain no native code), or a single architecture name (for phones what would typically be armhf), or even an array of architectures for multi-arch click packages.
The hooks key is important. It contains a dictionary of application names mapped to the respective AppArmor file and desktop file.
A minimal desktop file can look like this:
[Desktop Entry] Name=hello-world Icon=./hello-world.png Exec=hello-world Terminal=false Type=Application X-Ubuntu-Touch=true
Setting Terminal=true would cause the package to fail to build. Launching apps in terminal is not supported on the phone. What a pity. :)
A minimal AppArmor file looks like this:
{ "policy_groups": [ ], "policy_version": 1.3 }
Typically the policy_groups array would contain an array of policy groups to allow access to e.g. sound playback or network. In the simplest situation nothing extra is requested and the array can be empty.
Let's use the following C++ source (hello-world.cpp) to build the application binary:
#includeint main() { std::cout << "Hello World!" << std::endl; }
To build it manually the following could be used (assuming framework 15.04 & armhf target):
$ click chroot -a armhf -f ubuntu-sdk-15.04 run arm-linux-gnueabihf-g++ hello-world.cpp -o hello-world
The command consists of:
$ click chroot -a armhf -f ubuntu-sdk-15.04 run ...
which runs whatever follows the run argument inside a chroot for given arch and framework, and the actual compilation for armhf target:
... arm-linux-gnueabihf-g++ hello-world.cpp -o hello-world
The result is an armhf binary hello-world built in the current directory. (There are restrictons on which directories are accessible in the chroot.)
Copy the binary to the directory that contains the rest of the future package. The directory for building the minimal package should now contain the following files:
- the application binary: hello-world
- apparmor file: hello-world.apparmor
- desktop file: hello-world.desktop
- application icon: hello-world.png
- click manifest: manifest.json
$ click build pkg_source
This should build the click package, e.g.:
Now executing: click-review ./zub.hello-world_1.0_armhf.click ./zub.hello-world_1.0_armhf.click: pass Successfully built package in './zub.hello-world_1.0_armhf.click'.
Hooray! To install the package on a phone, connect the phone via USB, unlock the phone (i.e. wake the phone up and unlock the lock screen, otherwise adb - which is what phablet-shell uses - does not connect), then run phablet-shell (contained in the package phablet-tools) to get a shell on your phone. Copy (e.g. via scp) the .click package to the phone, then in the phone's shell, install the package by:
pkcon install-local --allow-untrusted zub.hello-world_1.0_armhf.click
Why not install via click install? I don't know, but it seems to fails on the phone.
The new application should show up in the application list (sometimes it doesn't and refresh by pulling down at the top of the application list is required).The app icon should launch the application but as the application itself only outputs a line of text on standard output there is nothing to be seen.
It is possible to run the application manually on the phone, either using the Terminal application on the phone, or via phablet-shell. All click packages are installed in /opt/click.ubuntu.com/$PackageName/$PackageVersion. So the hello world can be launched via the command /opt/click.ubuntu.com/zub.hello-world/1.0/hello-world.
No comments:
Post a Comment