Saturday, January 14, 2017

The new Ubuntu SDK, part 2

[Update: Changed links to source code from https://launchpad.net/qtcreator-plugin-ubuntu and https://launchpad.net/ubuntu-sdk-tools to 
https://code.launchpad.net/~ubuntu-sdk-team/.... which is where the current tools probably live.]

Continuing from part 1, which shows how to use the current Ubuntu SDK from the command line, let's have a look at how does the build from the SDK IDE (rebranded Qt Creator) work.
There are two relevant packages:

The ubuntu-sdk-tools contains two tools: usdk-target and usdk-wrapper. Neither of these come with a man page, but usdk-target is quite useful on its own and was already described in the previous post.
One interesting thing is that usdk-target does not start the required containers. So, unless the Ubuntu SDK IDE has started it, the container needs to be started manually by lxc start.

To see  what Ubuntu SDK IDE does, one can peek into the sources of the qtcreator-plugin-ubuntu package. So, how does the Ubuntu SDK IDE run the C/C++ build? It turns out it's through the usdk-wrapper tool.

usdk-wrapper won't tell you how to use it as there's neither a man page, nor any help option. Looking into the sources reveals some strange things:
Also note that usdk-wrapper does start the container if it's not yet running (see BootContainerSync()).
So, what is this about? The purpose can be figured out from UbuntuClickTool::findOrCreateGccWrapper and friends in qtcreator-plugin-ubuntu. It creates symlinks to the usdk-wrapper with various names. The result is in ~/.config/QtProject/qtcreator/ubuntu-sdk:
$ ls -Rl desktop/ device-*
desktop/:
total 0
lrwxrwxrwx 1 foo foo 21 Dec 15 23:25 cmake → /usr/bin/usdk-wrapper
lrwxrwxrwx 1 foo foo 21 Dec 21 23:56 make → /usr/bin/usdk-wrapper
lrwxrwxrwx 1 foo foo 21 Dec 15 23:25 qmake → /usr/bin/usdk-wrapper
lrwxrwxrwx 1 foo foo 21 Dec 15 23:25 snapcraft → /usr/bin/usdk-wrapper
lrwxrwxrwx 1 foo foo 21 Dec 15 23:25 x86_64-linux-gnu-gcc → /usr/bin/usdk-wrapper

device-armhf:
total 0
lrwxrwxrwx 1 foo foo 21 Dec 16 00:06 arm-linux-gnueabihf-gcc → /usr/bin/usdk-wrapper
lrwxrwxrwx 1 foo foo 21 Dec 16 00:06 cmake → /usr/bin/usdk-wrapper
lrwxrwxrwx 1 foo foo 21 Dec 16 00:42 make → /usr/bin/usdk-wrapper
lrwxrwxrwx 1 foo foo 21 Dec 16 00:06 qt5-qmake-arm-linux-gnueabihf → /usr/bin/usdk-wrapper
lrwxrwxrwx 1 foo foo 21 Dec 16 00:06 snapcraft → /usr/bin/usdk-wrapper

device-i386:
total 0
lrwxrwxrwx 1 foo foo 21 Dec 15 23:31 cmake → /usr/bin/usdk-wrapper
lrwxrwxrwx 1 foo foo 21 Dec 15 23:31 i686-linux-gnu-gcc → /usr/bin/usdk-wrapper
lrwxrwxrwx 1 foo foo 21 Dec 21 23:56 make → /usr/bin/usdk-wrapper
lrwxrwxrwx 1 foo foo 21 Dec 15 23:31 qmake → /usr/bin/usdk-wrapper
lrwxrwxrwx 1 foo foo 21 Dec 15 23:31 snapcraft → /usr/bin/usdk-wrapper

So in the end qtcreator-plugin-ubuntu creates a directory for each kit, and in each a symlink named according to the tool (binary) to run in the container, pointing to usdk-wrapper. Set up in this way, running e.g. device-i386/cmake runs cmake in the container device-i386.

Looking into the source of usdk-wrapper reveals an interesting feature: It runs a regex replace on the output of the wrapped tool. Currently it maps strings that could be top-level directories in the container into paths valid outside the containers (the container root directory seems to be accessible as /var/lib/lxd/containers/$CONTAINER_NAME/rootfs/ outside the container).

This is a bold approach that is not necessarily correct:
$ mkdir -p test/device-armhf
$ cd test/device-armhf
$ ln -s /usr/bin/usdk-wrapper echo
$ ./echo test
test

So far, so good. Now try:
$ ./echo /variable
/var/lib/lxd/containers/device-armhf/rootfs/variable

Whoa! But I guess it works most of the time (especially taking into account the intended usage: running CMake or gcc).

So, to build using the Ubuntu SDK kits from the command line there are at least three options:
  • use lxc exec - a bit low level and requiring longer command line (to set the user and working directory), but it works
  • use usdk-target - quite easy to use, but requiring manual start of the used container
  • use usdk-wrapper - quite easy to use, but requires a setup with complex directory structure
Pick your weapon! :-)

No comments:

Post a Comment