Home > Chromium OS, Texas Instruments OMAP 3 > Cross-compiling Berkelium (and Chromium) for ARM

Cross-compiling Berkelium (and Chromium) for ARM

Berkelium is a BSD licensed library that provides off-screen browser rendering via Google’s open source Chromium web browser.

It takes advantage of Chromium’s multiprocess rendering to isolate browsers from each other and can render to any buffer in memory. The user of the library can inject input and javascript code into web pages to control them, as well as listen for events generated by the page such as navigation events, load sequence events and paint events. Berkelium provides a small API for embedding a fully functional browser into any application.

This library is used by Xibo Digital Signage Player python client.

I’ll give the instructions I followed to build Berkelium and Chromium for ARM. For now the build works, but I have a problem running berkelium in the emulator.

First, you’ll need to install some tools and the development version of some libraries:

sudo apt-get install git-core subversion cmake doxygen gyp libnss3-dev libgconf2-dev libgnome-keyring-dev libgtk2.0-dev libgnome-keyring-dev libgtk2.0-dev libxtst-dev libpam-dev libxss-dev libdbus-glib-1-dev

Then retrieve berkelium source code (I’ve done that in ~/edev/beagleboard drectory):

git clone git://github.com/sirikata/berkelium.git
cd berkelium/externals
git clone git://github.com/sirikata/cxxtest.git

You’ll also need to install tools specific to Chromium (gclient):

cd  ~/edev/beagleboard/berkelium/build/
svn co http://src.chromium.org/svn/trunk/tools/depot_tools

In ~/edev/beagleboard/berkelium/, I’ve created arm-linaro.env with the environment variables:

export CROSSTOOL=arm-linux-gnueabi
export CXX=$CROSSTOOL-g++
export CC=$CROSSTOOL-gcc
export AR=$CROSSTOOL-ar
export AS=$CROSSTOOL-as
export RANLIB=$CROSSTOOL-ranlib

export SYSROOT=/home/jaufranc/edev/beagleboard/libs

export LDFLAGS="-L/usr/arm-linux-gnueabi/lib/ -L $SYSROOT/lib/ -L$SYSROOT/lib/arm-linux-gnueabi/ \
-lXext -lxcb -lXau -lXdmcp -lXcomposite -lxml2 -lz -lXdamage -lXfixes -lXinerama -lXrandr \
-lXcursor -lpcre -lselinux  -lxcb-shm -lxcb-render -lexpat -lORBit-2 -lXrender -lgmodule-2.0 \
-lgobject-2.0 -lgthread-2.0 -lglib-2.0 -lpixman-1 -lpng12 -lX11"

export CFLAGS="-I$SYSROOT/include -I$SYSROOT/include/nspr -I$SYSROOT/include/gtk-2.0 \
-I$SYSROOT/include/glib-2.0 -I$SYSROOT/usr/lib/arm-linux-gnueabi/glib-2.0/include \
-I$SYSROOT/include/cairo -I$SYSROOT/include/pango-1.0 -I$SYSROOT/include/gtk-2.0/include \
-I$SYSROOT/include/gdk-pixbuf-2.0 -I$SYSROOT/include/pixman-1 -I$SYSROOT/include/atk-1.0 \
-I$SYSROOT/include/nss -I$SYSROOT/include/freetype2 -I$SYSROOT/include/gconf/2 \
-Wno-error -mword-relocations"

export CXXFLAGS="-I$SYSROOT/include -I$SYSROOT/include/nspr -I$SYSROOT/include/gtk-2.0 \
-I$SYSROOT/include/glib-2.0 -I$SYSROOT/usr/lib/arm-linux-gnueabi/glib-2.0/include \
-I$SYSROOT/include/cairo -I$SYSROOT/include/pango-1.0 -I$SYSROOT/include/gtk-2.0/include \
-I$SYSROOT/include/gdk-pixbuf-2.0 -I$SYSROOT/include/pixman-1 -I$SYSROOT/include/atk-1.0 \
-I$SYSROOT/include/nss -I$SYSROOT/include/freetype2 -I$SYSROOT/include/gconf/2 \
-I$SYSROOT/include/gtk-unix-print-2.0 -I$SYSROOT/include/dbus-1.0 \
-I$SYSROOT/usr/lib/arm-linux-gnueabi/dbus-1.0/include/ -I$SYSROOT/include/gnome-keyring-1 \
-O3 -Wno-error -mword-relocations"

export GYP_DEFINES="target_arch=arm sysroot=$SYSROOT disable_nacl=1 linux_use_tcmalloc=0 \
armv7=1 arm_thumb=1 use_libjpeg_turbo=0"

Please note that I added some extra flags to CFLAGS and CXXFLAGS to work around issues:

  • -O3: This was required to pass compilation for one the library using ARM assembly code.
  • -Wno-error: This was to avoir warning interpreted as error issues
  • -mword-relocations: Not necessary to build chromium, but I had to enable this to build berkelium to work around this issue:
    /usr/lib/gcc/arm-linux-gnueabi/4.5.2/../../../../arm-linux-gnueabi/bin/ld: /home/jaufranc/edev/beagleboard/berkelium/build/chromium/src/out/Release/obj.target/ui/gfx/../../gfx/ui/gfx/rect.o: relocation R_ARM_THM_MOVW_ABS_NC against `a local symbol’ can not be used when making a shared object; recompile with -fPIC
    See [arm] building non-PIC libraries fails under ARMv7 mode for details.

I also have to disable libjpeg-turbo (libjpeg using NEON instructions) due to an older version being used in the version of chromium used by berkelium. See http://code.google.com/p/chromium/issues/detail?id=78707 if you want to fix this.

I also had to create ~/.gyp/include.gypi:

{
'variables': {
'target_arch': 'arm',
'sysroot': '/home/jaufranc/edev/beagleboard/libs',
'disable_nacl': 1,  # NaCL does not build for ARM.
'linux_use_tcmalloc': 0, # tcmalloc does not build for ARM.
'armv7': 1, # Optional, for targeting ARMv7.
'arm_thumb': 1, # Optional, for targeting thumb.  Combine with armv7 to target thumb2.
'arm_neon': 1, # Optional, to disable NEON. 1 is the default, and most people want to keep it that way.
'arm_fpu': 'vfpv3-d16', # Optional, to select which version of vfp to use if NEON is off. Default is vfpv3.
}
}

To avoid issues with some libraries that set the architecture to pentium4. Maybe adding arm_neon and arm_fpu to GYP_DEFINES would have done the trick as well.

To make sure the right headers where used, I ran the emulator (Qemu for Overo board running APIP) and installed the following development package in the board:

apt-get install libnss3-dev libgconf2-dev libgnome-keyring-dev libgtk2.0-dev libgnome-keyring-dev libgtk2.0-dev libxtst-dev libpam-dev libxss-dev libdbus-glib-1-dev libnspr4-dev libglib2.0-dev libjpeg-dev libasound2-dev libbz2-dev

Once this was complete, I close the emulation, mounted the rootfs and copied the required files to $SYSROOT:

cd ~/edev/beagleboard
sudo mount -o loop,offset=$[106496*512] overo_sd_alip.img mnt
cp mnt/usr/include/* libs/include -rf
mkdir -p libs/usr/lib/arm-linux-gnueabi/dbus-1.0/include/dbus
mkdir -p libs/usr/lib/arm-linux-gnueabi/gcc/arm-linux-gnueabi/4.5/include
cp /mnt//usr/lib/arm-linux-gnueabi/dbus-1.0/include/dbus/* libs/usr/lib/arm-linux-gnueabi/dbus-1.0/include/dbus
cp /mnt/usr/lib/arm-linux-gnueabi/gcc/arm-linux-gnueabi/4.5/include/* libs/usr/lib/arm-linux-gnueabi/gcc/arm-linux-gnueabi/4.5/include
sudo umount mnt

There was a problem due with ARM assembly code in ffmpeg with can be fixed by editing ~/edev/beagleboard/berkelium/build/chromium/src/third_party/ffmpeg/ffmpeg.gyp and adding -Wa,-mimplicit-it=always in the arm section.:

'-fPIC',
'-Wa,-mimplicit-it=always',
], ],

If you don’t do that and enable thumb2 (arch=armv7 + arm_thumb=1), you’ll get this type of error:

standard input}:20760: Error: thumb conditional instruction should be in IT block

Then I set the environment variables:

source arm.env

and try the build:

./util/build-chromium.sh

I would recommend you also export V=1 in order to see the command line used, otherwise you’ll just see the error messages in case of issues,

After the checkout part is completed and compilation start (CXX messages appear), I also had to manually set config.h for libsrtp:

cp config.h to build/chromium/src/third_party/libsrtp/config/

Here’s the content of config.h:

// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This is a stub config.h for libSRTP. It doesn’t define anything because
// build is configured by libsrtp.gyp.

#define HAVE_UINT64_T
#define HAVE_UINT32_T
#define HAVE_UINT16_T
#define HAVE_UINT8_T

This is probably the wrong way to do, and adding those to a gyp file would have been more appropriate.

After a few hours, Chromium build should be complete.

Since allocator and seccomp_sandbox are not compiled for ARM, you’ll have to remove those in FindChrome.cmake.

To avoid berkelium library to be linked with the dynamic icu library and get the following error at runtine:

root@linaro-alip:~# berkelium
berkelium: symbol lookup error: /usr/lib/liblibberkelium.so: undefined symbol: UCNV_TO_U_CALLBACK_STOP_46

edit CMakeFiles/libberkelium.dir/link.txt and replace -licu18n, -licuuc and -licudata by build/chromium/src/out/Release/ob.target/third_party/icu/libicu18n.a, build/chromium/src/out/Release/ob.target/third_party/icu/libicuuc.a and build/chromium/src/out/Release/ob.target/third_party/icu/libicudata.a, respectively.

If you use the default linked (ld.fdb), you’ll get a link error, so I temporarily configured the system to use the experimental gold linker:

pushd /usr/arm-linux-gnueabi/bin
sudo rm ld
sudo ln -s ld.gold ld
popd

After that edit CMakeLists.txt and disable the cxxtest code and you just need to cross-compile berkelium:

cmake . -DCMAKE_INSTALL_PREFIX=~/edev/beagleboard/libs/
make
make install

If you encounter this type of error during linking:

/usr/lib/gcc/arm-linux-gnueabi/4.5.2/../../../../arm-linux-gnueabi/bin/ld: fatal error: out of file descriptors and couldn’t close any

Change the opened file limit as follows:

ulimit -n 4096

So now the the build is complete let’s copy berkelium to the rootfs:

cd ~/edev/beagleboard
sudo mount -o loop,offset=$[106496*512] overo_sd_alip.img mnt
sudo cp libs/usr/bin/* mnt/usr/bin -rf
sudo cp libs/usr/lib/liblibberkelium.so mnt/usr/lib
sudo umount mnt

and let’s try it in qemu for overo (256MB is not enough memory for the debug version at least, that’s why I use 512 MB):

sudo qemu-system-arm -M overo -m 512 -drive file=./overo_sd_alip.img,if=sd,cache=writeback -clock unix -serial stdio -device usb-kbd -device usb-mouse

After xfce graphical user interface is loaded, start a terminal window and type berkelium. After a while a chrome like window should appear and you should be able to browse the internet.

Finally, please note the version of the binutils and gcc/g++ I used:

arm-linux-gnueabi-ld -v
GNU ld (GNU Binutils for Ubuntu) 2.21.0.20110327

arm-linux-gnueabi-gcc -v
gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu3)

If you use use the newest version of the binutils (2.21.53.20110810) and gcc/g++ (4.6.1), you’ll get different kind of errors including that one:

/usr/lib/gcc/arm-linux-gnueabi/4.6.1/../../../../arm-linux-gnueabi/bin/ld: this linker was not configured to use sysroots

This is related to https://bugs.launchpad.net/ubuntu/+source/armel-cross-toolchain-base/+bug/692987

I’ve also used the angstrom toolchain, but also went into different troubles (can’t remember which ones).

References:
http://code.google.com/p/chromium/wiki/LinuxBuildInstructions
http://code.google.com/p/chromium/wiki/LinuxBuildInstructionsPrerequisites
http://groups.google.com/a/chromium.org/group/chromium-os-discuss/browse_thread/thread/759144fb1c963570
https://wiki.linaro.org/Resources/HowTo/CrossBuildingChromiumBrowser

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter

Categories: Chromium OS, Texas Instruments OMAP 3 Tags: arm, beagleboard, berkelium, binutils, chromium, cross-compilation, libjpeg, linaro, overo, qemu
  1. Alfred
    April 1st, 2013 at 17:50 | #1

    Hi

    i ask aboud the location of the ~/.gyp folder
    i excute the steps of this tutorial when i serch the berkelium/build/chromium/src/third_party/ffmpeg/ffmpeg.gyp i dont I can not find .

    thank you

  2. Alfred
    May 30th, 2013 at 21:29 | #2

    i not recive a response for my question ??????????????????????????????????

  3. May 30th, 2013 at 22:02 | #3

    @Alfred
    I don’t know the answer. Maybe the code has changed since I wrote the article.

  1. April 25th, 2012 at 11:27 | #1