en ru

How to Configure Devel Environment to Work on Gecko for Sailfishos

2014-03-20

It turned out that newcomers have difficulties with setting up their development environment to work on Gecko integration with Nemo, SailfishOS or any other Mer-based Linux. Hence this post.

Configure development environment

Gecko engine development for embedded devices is quite resource consuming. If you want to try it you’d better have a mighty computer running Linux and avoid virtualization. It’s better not to use the standard SailfishOS SDK, but to resort to Mer chroot-based SDK.

First of all you’ll need to install Mer platform SDK and enter into it. Look at this wiki page for details and follow the instructions till the part “Basic tasks”.

Then you’ll need to create and install a rootfs. More detailed instructions can be found here, but below is an extarct from there:

MerSDK$ sudo mkdir -p /parentroot/srv/mer/targets
MerSDK$ cd /tmp

Now in the current directory (which is /tmp) create a file mer-target-armv7hl.ks with the following content:

# -*-mic2-options-*- --arch=armv7hl -*-mic2-options-*-
lang en_US.UTF-8
keyboard us
timezone --utc UTC
part / --size 500 --ondisk sda --fstype=ext4
rootpw rootme

user --name mer  --groups audio,video --password rootme

repo --name=sailfish --baseurl=http://releases.jolla.com/releases/latest/jolla/armv7hl --save --debuginfo

%packages
glibc-devel
mesa-llvmpipe-libEGL-devel
mesa-llvmpipe-libGLESv2-devel
shadow-utils
rpm-build
meego-rpm-config
zypper
%end

%post
## rpm-rebuilddb.post from mer-kickstarter-configs package
# Rebuild db using target's rpm
echo -n "Rebuilding db using target rpm.."
rm -f /var/lib/rpm/__db*
rpm --rebuilddb
echo "done"
## end rpm-rebuilddb.post

## arch-armv7hl.post from mer-kickstarter-configs package
# Without this line the rpm don't get the architecture right.
echo -n 'armv7hl-meego-linux' > /etc/rpm/platform

# Also libzypp has problems in autodetecting the architecture so we force tha as well.
# https://bugs.meego.com/show_bug.cgi?id=11484
echo 'arch = armv7hl' >> /etc/zypp/zypp.conf
## end arch-armv7hl.post

%end

Then create a target:

MerSDK$ sudo mic create fs mer-target-armv7hl.ks -o /parentroot/srv/mer/targets \
                 --pkgmgr=zypp --arch=armv7hl --tokenmap=MER_RELEASE:latest
MerSDK$ sudo chown -R $USER /parentroot/srv/mer/targets/mer-target-armv7hl/

Now tweak the target to recognize you:

MerSDK$ cd /parentroot/srv/mer/targets/mer-target-armv7hl/
MerSDK$ grep :$(id -u): /etc/passwd >> etc/passwd
MerSDK$ grep :$(id -g): /etc/group >> etc/group

Configure it to work with Scratchbox2 together:

MerSDK$ cd /parentroot/srv/mer/targets/mer-target-armv7hl/
MerSDK$ sb2-init -d -L "--sysroot=/" -C "--sysroot=/" \
                 -c /usr/bin/qemu-arm-dynamic -m sdk-build -n -N \
                 -t / mer-target-armv7hl \
                 /opt/cross/bin/armv7hl-meego-linux-gnueabi-gcc
MerSDK$ sb2 -t mer-target-armv7hl -m sdk-install -R zypper ref --force

Clone web engine git repos to your local file system (e.g. into the local directory /home/rozhkov/tmp/mozilla-temp/):

$ mkdir -p /home/rozhkov/tmp/mozilla-temp
$ cd /home/rozhkov/tmp/mozilla-temp
$ git clone git@github.com:tmeshkova/xulrunner-package.git
$ cd xulrunner-package
$ ./pull.all.sh

After that install build requirements to the rootfs:

MerSDK$ cd /home/rozhkov/tmp/mozilla-temp/xulrunner-package
MerSDK$ grep --color=never BuildRequires mozilla-central/rpm/xulrunner-qt5.spec | \
        sed -e '/^#.*$/d' | \
        gawk -F: '{ print $2 }' | \
        tr ',' ' '| \
        xargs sb2 -t mer-target-armv7hl -m sdk-install -R zypper in
MerSDK$ grep --color=never BuildRequires qtmozembed/rpm/qtmozembed-qt5.spec | \
        sed -e '/^#.*$/d' | \
        gawk -F: '{ print $2 }' | \
        tr ',' ' '| \
        xargs sb2 -t mer-target-armv7hl -m sdk-install -R zypper in
MerSDK$ grep --color=never BuildRequires embedlite-components/rpm/embedlite-components-qt5.spec | \
        sed -e '/^#.*$/d' | \
        gawk -F: '{ print $2 }' | \
        tr ',' ' '| \
        xargs sb2 -t mer-target-armv7hl -m sdk-install -R zypper in
MerSDK$ grep --color=never BuildRequires sailfish-browser/rpm/sailfish-browser.spec | \
        sed -e '/^#.*$/d' | \
        gawk -F: '{ print $2 }' | \
        tr ',' ' '| \
        xargs sb2 -t mer-target-armv7hl -m sdk-install -R zypper in

Remove the packages that are not really needed for engine development:

MerSDK$ sb2 -t mer-target-armv7hl -m sdk-install -R \
             zypper rm qtmozembed-qt5 qtmozembed-qt5-devel \
                       xulrunner-qt5 xulrunner-qt5-devel

And finally build the stuff with the build.sh script::

MerSDK$ sb2 -t mer-target-armv7hl -m sdk-build ./build.sh -j -t mer

The option -j here makes build.sh build sailfish-browser binaries as well.

When everything is successfully built the script will show instructions on how to run the newly built browser:

...
make[1]: Leaving directory `/home/rozhkov/tmp/mozilla-temp/xulrunner-package/sailfish-browser/src'
make: Leaving directory `/home/rozhkov/tmp/mozilla-temp/xulrunner-package/sailfish-browser'

prepare run-time environment:
export LD_LIBRARY_PATH=/home/rozhkov/tmp/mozilla-temp/xulrunner-package/qtmozembed/objdir-mer/src
export QML_IMPORT_PATH=/home/rozhkov/tmp/mozilla-temp/xulrunner-package/qtmozembed/objdir-mer/qmlplugin5
export QML2_IMPORT_PATH=/home/rozhkov/tmp/mozilla-temp/xulrunner-package/qtmozembed/objdir-mer/qmlplugin5

run unit-tests:
export QTTESTSROOT=/home/rozhkov/tmp/mozilla-temp/xulrunner-package/qtmozembed/tests
export QTTESTSLOCATION=/home/rozhkov/tmp/mozilla-temp/xulrunner-package/qtmozembed/tests/auto/mer-qt5
export QTMOZEMBEDOBJDIR=/home/rozhkov/tmp/mozilla-temp/xulrunner-package/qtmozembed/objdir-mer
/home/rozhkov/tmp/mozilla-temp/xulrunner-package/qtmozembed/tests/auto/run-tests.sh

run test example:
/home/rozhkov/tmp/mozilla-temp/xulrunner-package/objdir-mer/dist/bin/qmlMozEmbedTestQt5  -fullscreen  -url about:license
/home/rozhkov/tmp/mozilla-temp/xulrunner-package/objdir-mer/dist/bin/sailfish-browser about:license

Due to a bug in gecko build scripts you might encounter an error message about missing config.status file after the build configuration phase. In this case just copy the file objdir-mer/config.status to your working directory and run build.sh again:

MerSDK$ cp objdir-mer/config.status .
MerSDK$ sb2 -t mer-target-armv7hl -m sdk-build ./build.sh -j -t mer

The best way to test the build is to mount the working directory into the device’s file system so that the path to the built binaries on the device is the same as in the host filesystem. For this you’ll need to have the package sshfs installed on the device:

[nemo@localhost-001 ~]$ mkdir tmp
[nemo@localhost-001 ~]$ sshfs rozhkov@192.168.2.14:/home/rozhkov/tmp tmp
[nemo@localhost-001 ~]$ devel-su
[root@localhost-001 nemo]$ cd /home
[root@localhost-001 home]$ ln -s nemo rozhkov
[root@localhost-001 home]$ exit
[nemo@localhost-001 ~]$ cd tmp/mozilla-temp/xulrunner-package
[nemo@localhost-001 xulrunner-package]$ export LD_LIBRARY_PATH=/home/rozhkov/tmp/mozilla-temp/xulrunner-package/qtmozembed/objdir-mer/src
[nemo@localhost-001 xulrunner-package]$ export QML_IMPORT_PATH=/home/rozhkov/tmp/mozilla-temp/xulrunner-package/qtmozembed/objdir-mer/qmlplugin5
[nemo@localhost-001 xulrunner-package]$ export QML2_IMPORT_PATH=/home/rozhkov/tmp/mozilla-temp/xulrunner-package/qtmozembed/objdir-mer/qmlplugin5
[nemo@localhost-001 xulrunner-package]$ /home/rozhkov/tmp/mozilla-temp/xulrunner-package/objdir-mer/dist/bin/sailfish-browser about:license

By now you should have working development environment. If you change code under mozilla-central/embedding/embedlite, qtmozembed, embedlite-components or sailfish-browser just run the build.sh script again:

MerSDK$ sb2 -t mer-target-armv7hl -m sdk-build ./build.sh -j -t mer

If you change something inside other gecko components, e.g. under mozilla-central/dom/events or mozilla-central/gfx, then you’ll need to rebuild the outdated object files too with the option -o:

MerSDK$ sb2 -t mer-target-armv7hl -m sdk-build ./build.sh -j -t mer -o dom/events,gfx

This way there is no need to rebuild all other object files. And if you’re working on the engine only then you might want to use the option -e of build.sh that makes the script to rebuild only the engine:

MerSDK$ sb2 -t mer-target-armv7hl -m sdk-build ./build.sh -e -t mer

Useful info

If you’re working on JS components don’t forget to reset the start up cache before testing your work:

[nemo@localhost-001 xulrunner-package]$ rm -fr ~/.mozilla/mozembed/startupCache/

If you need to switch on logging in the engine then define NSPR_LOG_MODULES environment variable:

[nemo@localhost-001 xulrunner-package]$ export NSPR_LOG_MODULES=TabChildHelper:5,EmbedLiteTrace:5,EmbedContentController:5

In order to see logging from components other than EmbedLite you’d need to have a so called debug build of xulrunner. Use the option -d of the build.sh script to create it.

Unfortunately the gecko build system is based on python which runs under qemu inside Scratchbox2 by default (unless you do x86 build). It is possible to accelerate python though. To achieve this you need to use a special Scratchbox2 mode sdk-build+pp and to add the option -r to build.sh:

MerSDK$ sb2 -t mer-target-armv7hl -m sdk-build+pp ./build.sh -r -j -t mer

Happy hacking!