While Servo supports Android for a while now, it turned out cross compiling to ARM devices requires some additional work. Now that most of these patches have landed, it is possible to build for ARM with just some minor tweaks.
UPDATE 2: Most of the patches have landed, post updated.
UPDATE 3: The linker issue is now fixed (but, unfortunately there is an issue with the latest Skia).
UPDATE 4: Looks like the Skia issue was fixed, but another appeared in libexpat. Fortunately, there is a clean workaround for that.
Last update: 2015, Nov 2
For reference, in this post I’m going to use Servo at commit 73b52c0, which requires Rust version 2d0cbf3e3e25e092bd9e4c94d08e446b680869f0. You will need the Rust standart library of this particular version, compiled to ARM. The required version is stored in the file rust-snapshot-hash.
Unfortunately, you will probably have to build that yourself too, as ARM libs are not distributed with Rust yet. The first part of the on-board building guide describes how to do it. UPDATE: Now you should also be able to compile it by simply setting the appropriate configure flags.
You will also need the ARM system libraries, but you can copy them either from the system running on your board or from a downloaded distribution installer, eg. a Raspbian image.
Setting up a rootfs
First, I’m going to set up an Ubuntu 14.04 rootfs to build in a clean environment. You can safely skip this step (just don’t forget to change the paths later).
Then, add a new user inside the roots (again, you can skip this):
Prerequisites
All right, let’s install the ARM compiler. There are many kinds of toolchains (eg. optimized for a certain board, like the Raspberry Pi), but the default one is fine for me:
Install the Servo dependencies (copied from the README):
Note: if python-virtualenv is not found, install it like this:
Oh, and we will also need git:
Finally, download Servo, but leave it alone for now:
I’ve just pushed some ARM patches to Servo and its dependencies, which have not landed yet. Fortunately, we can use custom versions of these repos without messing up the main Servo (Cargo) directory, so we can apply these changes already.
I’m going to store these git repositories in servo_repos:
and download each dependency which have an unlanded patch and apply it.
UPDATE:: These patches have already landed, you can get them by mach cargo-update (see later), or manually:
Now we have to create a Cargo config file for Servo to tell the location of these repos:
This will solve the problem of unlanded patches. Now, some dependencies have ARM cross compile patches already, but Servo doesn’t use the latest version of these. To update them, we have to initialize the build system first:
which will download Rust and Cargo used by Servo, and creates the directory structure to where we will copy the Rust libraries in the next section.
Alternatively, you can just run ./mach build, which also does this for you, but the build itself will fail at this point.
Now that we have set up the build system, we can get the updated dependencies like this:
You can also specify a target Git hash for each package with the --precise flag. At the time of writing,
can also be used for getting the latest versions.
What you still have to do, is setting up the build system:
Installing libraries
We will need to install the Rust standart libraries for ARM if we want to cross compile programs written in Rust. Let’s exit from the rootfs for a minute:
and copy your ARM Rust libraries to the correct location:
Note: Your target directory might have a different Rust hash/version.
Note: In case you’ve skipped the preface, you have to build the Rust standard libraries of the version used by Servo for ARM
If you skip this step, you will get std-related errors when compiling Rust code
We will also need to install the ARM system libraries if we don’t want to get linker errors later:
If you are not working in a rootfs, just remove the rootfs-trusty part of the commands.
We’re done with the libraries, let’s go back into the rootfs:
There are two ‘missing header’ errors, for OpenSSL and Zlib. Apparently this is a packaging issue on certain distros. Anyway, you can fix it like this:
Building!
Finally! If you’ve followed the previous steps correctly, running
should build servo correctly, and you can find it at ./target/arm-unknown-linux-gnueabihf/debug/servo. Congratulations!
Finally! If you’ve followed the previous steps correctly, running
should give you
… a huge linker error. Don’t worry, we’ll fix this. It seems this is also a packaging problem on Ubuntu; some X11 linker flags are missing, and you will have to add them manually. Copy the failing command (starting from "arm-linux-gnueabihf-gcc" "-Wl,--as-needed" "-L" ... to ... "c" "-l" "m" "-l" "compiler-rt") to your favorite text editor, and first create a proper GCC command from it:
replace all "-l" " with "-l
replace all "-L" " with "-L
delete all "
And add these three flags to the end:
If you’re lucky, Servo will now build correctly and you can find it at ./target/arm-unknown-linux-gnueabihf/debug/servo. Congratulations!
Issues
Servo still has some visual (X11 and OpenGL) problems on embedded Linux, whether you build on board or cross compile.