Boox M92 Development with Scratchbox2

From MobileRead
Jump to: navigation, search

Developing new software for the Onyx Boox M92 from scratch is not very complicated and thanks to the article on Boox M92 software development is pretty well documented. Porting existing software like Python or SQLite is a slightly harder challenge. Using the scratchbox2 build environment together with a Debian rootstrap is a pretty comfortable solution to that problem. In many scenarios it enables you to compile new software using previously compiled libraries as if working directly on an ARM machine without the need to set up a whole virtual machine.


[edit] Prerequisites

First of all, I assume you already installed the prebuilt toolchain and Onyx SDK following this guide: [1]. You maybe also want to compile the SDK (at least target build:arm:static) as described in the respective section of that article in order to get the latest version of the Onyx SDK. In that case you can "cd build/arm" and "make install" (inside the "booxsdk" directory) to merge the updated files with the precompiled Onyx SDK.

Furthermore, we will need some software. Most of it should be available from your distribution's repositories: fakeroot, qemu-arm (>=1.0), debootstrap, apt and dpkg. On a Fedora 17 machine all of this is directly available from the official repositories. If you are on a Debian or Ubuntu machine, you will have apt and dpkg from the start, fakeroot and debootstrap should be available from the repositories. For the latest version of qemu, the easiest solution seems to be retrieving the source tarball of version 1.0.X from the download section of and building qemu from source. Be sure to remember the location of the resulting "qemu-arm" binary.

[edit] Building scratchbox2 from source

Scratchbox2 is under heavy development ( At the moment, it's advisable taking the latest version from the 2.3_development branch. I warmly recommend not to use an outdated version from your distribution's repository.

First of all, you chose a directory to work and develop in, like DEV_HOME=$HOME/sbox2. The steps to build and set up scratchbox2 are pretty easy after that:

mkdir -p $DEV_HOME
git clone git://
cd scratchbox2 
git checkout -b 2.3_development origin/2.3_development
./configure --prefix="$DEV_HOME/install"
make install

[edit] Setting up scratchbox2

At this point, you find the scratchbox2 binaries in "$DEV_HOME/install/bin", so it's a good idea to add the following line to your ~/.bashrc:


This is the right moment to setup your first scratchbox2 target. You do this by chosing a directory, i.e. where you plan to create a debian rootstrap (see next section of this article). I chose "$DEV_HOME/rootfs" and thus I set up a target like this:

mkdir $DEV_HOME/rootfs
cd $DEV_HOME/rootfs
sb2-init -n -d -m emulate M92 "/opt/freescale/usr/local/gcc-4.4.4-glibc-2.11.1-multilib-1.0/arm-fsl-linux-gnueabi/bin/arm-fsl-linux-gnueabi-gcc"

This will make this target my default target (-d) called "M92". Most of the time, we will be happy with the "emulate" mode of scratchbox2, so I set it as the default mode (-m). And the last argument is the path to our cross-compiler. If your qemu installation is not in your $PATH, you may want to add something like "-c /path/to/qemu-arm" to the sb2-init command line.

[edit] Setting up a debian rootstrap

The biggest advantage of this whole scratchbox2 approach is the fact that Debian "armel" is binary compatible with our Boox M92. When porting software like Python or PyQt, it can be very useful to have a rootstrap with arbitrary access to header files and libraries to build against. Setting up a Debian rootstrap is very easy using the command "debootstrap" as follows:

cd $DEV_HOME/rootfs
fakeroot /usr/sbin/debootstrap --variant=scratchbox --foreign --arch armel wheezy "$DEV_HOME/rootfs"
sb2 -eR ./debootstrap/debootstrap --second-stage

It's very likely that "--second-stage" will fail in the first attempt. In most cases, it's already sufficient to execute it a second and third time - if that doesn't work for you, you can try to find out the reason by looking into "$DEV_HOME/rootfs/debootstrap/debootstrap.log". If the directory $DEV_HOME/rootfs/debootstrap vanished, everything went well and you can do the last steps to a working Debian rootstrap by issuing:

cd $DEV_HOME/rootfs
echo "deb wheezy main contrib non-free" > etc/apt/sources.list
echo "deb-src wheezy main contrib non-free" >> etc/apt/sources.list
sb2 -eR apt-get -y update
sb2 -eR apt-get -y upgrade
sb2 -eR apt-get -y install dialog locales
sb2 -eR dpkg-reconfigure locales

The last two commands are useful in order to eliminate disturbing error messages from apt-get output. Please note, that the "-e" option enables "emulate" mode and is not necessary, if you set this mode as the default in your sb2-init command line. The -R enables a fakeroot environment and is necessary with all commands that try to manipulate files inside your rootstrap.

[edit] Some post-setup tweaks

You can directly start using your scratchbox2 environment now. But there are some tweaks for a more comfortable experience. At first, you probably want to have access to your Onyx SDK in /opt/onyx/arm/ from inside sb2. To achieve this, you have to add the following line to the file $DEV_HOME/install/share/scratchbox2/modes/emulate/fs_rules.lua inside the emulate_mode_rules block (don't leave out the comma at the end!):

{prefix = "/opt/onyx", use_orig_path = true},

After that, there are still some environment variables to set. The most elegant way to do this is setting environment variables using "sb2-config", i.e.:

$ sb2
[SB2-prompt]$ sb2-config setenv ONYX_SDK_ROOT "/opt/onyx/arm"
[SB2-prompt]$ sb2-config setenv PATH "/opt/onyx/arm/bin:/opt/python/bin:$PATH"
[SB2-prompt]$ sb2-config setenv PKG_CONFIG_PATH "/opt/onyx/arm/lib/pkgconfig/"
[SB2-prompt]$ sb2-config setenv QMAKESPEC "/opt/onyx/arm/mkspecs/qws/linux-x86-g++/"
[SB2-prompt]$ sb2-config setenv LD_FLAGS "$LD_FLAGS  -I/opt/python/include"
[SB2-prompt]$ sb2-config setenv LD_LIBRARY_PATH "/opt/onyx/arm/lib:/usr/lib/arm-linux-gnueabi:/lib/arm-linux-gnueabi:/opt/python/lib"
[SB2-prompt]$ exit

The "/opt/python" paths in this example demonstrate how to cope with the fact, that you will want to build some software like Python for yourself without mixing up stuff with native Debian packages. Feel free to add whatever you'd like to use else.

Please note, that we are setting the variables inside an sb2 environment only because we have to consider, that the PATH variable already has an internal value in SB2 and we don't want to replace this, but we want to attach our paths to those standard values.

[edit] Alternative way to set environment variables using a shell script

In some cases it will be more practical to use a custom shell script in order to set certain variables on the fly and "ad hoc". For example, consider the following shell script in an executable file "$DEV_HOME/rootfs/bin/":

export QMAKESPEC="/opt/onyx/arm/mkspecs/qws/linux-x86-g++/"

Using the above shell script we will have to issue commands like "sb2 -R make install" when building software. Because that's a pretty long command line we want to have a shortcut for this. For example, you will want to add the following line to your ~/.bashrc:

alias sb2ox="sb2 -eR"

After that the command line looks like "sb2ox make install" and is indeed much better to handle.

[edit] Example: Cross-compiling Python and PyQt

To demonstrate how easy it is to port software using scratchbox2, I provide you with an already pretty complex example: building Python for Onyx Boox M92. First of all we need a working directory like "WORKDIR=$DEV_HOME/projects" - it shouldn't be inside your Debian rootstrap! You retrieve the Python 2.7.3 source tarball from the official Python homepage, place it in "$WORKDIR/src" and execute the following commands:

tar -C "$WORKDIR" -xzf "$WORKDIR/src/Python-2.7.3.tgz"
cd "$WORKDIR/Python-2.7.3"
sb2 ./configure --prefix=/opt/python
sb2 make
sb2 -R make install prefix=/opt/python

After that you have a readily compiled python in "$DEV_HOME/rootfs/opt/python" - no patches and no complicated set of options or parameters needed. If you want your version of Python to support zlib, bz2 or sqlite3, you simply have to install the required header files before building:

sb2 -R apt-get install zlib1g-dev libsqlite3-dev libbz2-dev

If you want to write gui applications with Python, you will also need PyQt. Because our Onyx Boox M92 uses embedded Qt or "QWS" instead of X11 and QWS is not officially supported by PyQt, you will have to apply some patches from [2]. The procedure looks like this:

cd "$WORKDIR" 
tar -xzf "src/sip-4.12.2.tar.gz"
cd "sip-4.12.2"
sb2 python
sb2 make
sb2 -R make install
cd "$WORKDIR" 
tar -xzf "src/PyQt-x11-gpl-4.8.5.tar.gz"
hg clone
cd pyqt4-for-embedded-linux/PyQt4-Qt-Embedded-Linux-patches
./ ../qpy ../../PyQt-x11-gpl-4.8.5/qpy
./ ../sip ../../PyQt-x11-gpl-4.8.5/sip
perl -i -0 \
   -pe 's/WS_X11/WS_QWS/g;' \
   -pe 's/qt_sip_flags = \[\]/qt_sip_flags = ["-x","PyQt_Accessibility","-x","PyQt_Cursor", \
      "-x","PyQt_ImageFormat_JPEG","-x","PyQt_Picture", \
      "-x","PyQt_PrintDialog","-x","PyQt_Printer", \
      "-x","PyQt_ProgressDialog","-x","PyQt_QWS_Cursor", \
      "-x","PyQt_SessionManager","-x","PyQt_Sound"]/g;' \
cd "PyQt-x11-gpl-4.8.5"
mkdir "compiling"
cd "compiling"
sb2 python ../ --confirm-license --verbose --no-qsci-api --no-designer-plugin
sb2 make
sb2 -R make install

After that you have a working PyQt installation in your Python installation in "$DEV_HOME/rootfs/opt/python". Because the M92 has an Eink screen, GUI programmers have to directly cope with the display drivers via the onyx_* libraries from the Onyx SDK. In order for our PyQt tools to show any effect on the M92's screen, we will need a Python API for those Onyx libraries. And an approach to such an API has been made with PyOnyx, see also [3]. PyOnyx can now be easily compiled using the following steps:

cd "$WORKDIR" 
git clone git://
cd PyOnyx
mkdir compiling
cd compiling
sb2 python ../
sb2 make
sb2 -R make install

[edit] Troubleshooting

[edit] Set standard user inside the sb2 environment

If you have set up a Debian rootstrap, sb2 will look up your user name in /etc/passwd of your target. But when running sb2 (without option -R) you will be identificated with the UID you use on your host machine. Thus, your sb2 prompt might contain something like "I have no name!" (because there doesn't exist a user of that name in your target machine). To fix this you have to copy the respective line from your host's /etc/passwd to your target's /etc/passwd.

Personal tools

MobileRead Networks