Cross-Compiling Splash-3
How to cross-compile the Splash-3 benchmark for use with gem5
Something happened which I never thought would: Someone was trying to use my MSci project for similar work. I always assumed the project would only ever be read by my supervisor and the second marker, so having someone else be interested was really exciting!
As part of this, the person ran into the same problems I had, e.g. gem5 can be finicky to set up, configuring the Linux kernel is a daunting task, and cross-compiling is more like repeatedly hitting things with a hammer until it eventually (hopefully) works.
When I was doing my MSci project, I used the Splash-3 benchmark. However, I also cheated a bit in terms of cross-compiling it: I had a native ARMv8 dev-board available which, when cross-compiling got difficult, I used to compile the benchmark and then simply copied over the files, thereby avoiding cross-compiling altogether. This is obviously not always an option, so I decided to have a more serious go at trying to get this working. After all, papers seemed to use it with similar setups to mine, so it had to be possible, right?
Preparation and initial setup
Before we get started, the following setup is assumed:
- OS: Linux of some variant
- Guest platform (where we are cross-compiling from): x86_64
- Host platform (where we are cross-compiling to): ARMv8
- Some sort of cross-compiling toolchain, e.g. the
GNU cross-toolchain for A-profile cores,
stored in its own directory (I keep mine in
$HOME/xtools
).
For convenience, I also like to
export ARMv8_XTOOLS="$HOME/xtools/gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-"
which defines an environment variable ARMv8_XTOOLS
to more easily be able to
access the toolchain. (The exact value will be different if you’re using a
different cross-compiling toolchain). With this, to run gcc
simply run:
$ ${ARMv8_XTOOLS}gcc --version
It should give you:
aarch64-none-linux-gnu-gcc (GNU Toolchain for the A-profile Architecture 10.2-2020.11 (arm-10.16)) 10.2.1 20201103
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Clone the Splash-3 benchmark and cd
into the top directory:
$ git clone git@github.com:SakalisC/Splash-3
$ cd Splash-3
You used to have to make some changes to a number of Makefiles, but this has
been fixed as of this PR and
so the repository should be mostly be good to go immediately. However, the
volrend
benchmark is extra finicky to get working, so we need to do something
else first.
Cross-compiling libtiff
The volrend
benchmark relies on libtiff
. Unfortunately, the version included
with Splash-3 does not like being cross-compiled. This can be fixed by
downloading and cross-compiling a version from the official website (thanks to
Chris Sakalis
for that idea).
From the root of the Splash-3 repo, start by cd
-ing into the
codes/apps/volrend/
directory. Then download, copy, and unzip a recent version
of libtiff
from
the official download page.
This extracts a tiff-
version
directory, which I like to rename to
libtiff-
version
, just to keep things consistent:
$ mv -v {,lib}tiff-<version>
$ cd libtiff-<version>
(Replacing <version>
with the version number you downloaded.)
Create an install directory in which to put the cross-compiled library (the name doesn’t matter, as long as you keep it consistent):
$ mkdir install_dir
To configure libtiff
for cross-compiling, without shared libraries, and using
a custom install path, run:
$ PATH="$(dirname ${ARMv8_XTOOLS}):${PATH}" \
./configure --disable-shared --host="aarch64-none-linux-gnu" \
prefix="${PWD}/install_dir" exec_prefix="${PWD}/install_dir"
Explanation:
PATH="$(dirname ${ARMv8_XTOOLS}):${PATH}"
– sets thePATH
(where the shell looks for executables, checking the first path first) to include the cross-compile toolchain directory (obtained usingdirname
). We couldexport
this newPATH
and then restore it when we’re done, but since it’s only for a couple of instructions, I prefer to do this../configure
– runs the includedconfigure
script.--disable-shared
– disables the use of shared libraries. This can be critical for use with things like gem5 where the shared libraries may not be available on the virtual disk.--host="aarch64-none-linux-gnu"
– specifies the name of the platform we are cross-compiling for. A useful hint is the prefix of all the executables in the cross-compile toolchain.prefix="${PWD}/install_dir" exec_prefix="${PWD}/install_dir"
– specifies that we want the results to be installed in theinstall_dir
directory in the current directory.
Then, to actually compile and install, run:
$ PATH="$(dirname ${ARMv8_XTOOLS}):${PATH}" \
make prefix="${PWD}/install_dir" exec_prefix="${PWD}/install_dir"
$ PATH="$(dirname ${ARMv8_XTOOLS}):${PATH}" \
make install prefix="${PWD}/install_dir" exec_prefix="${PWD}/install_dir"
Depending on your hardware, the initial make
may take a couple of minutes.
Patching volrend
To use the new libtiff
with volrend
, we need to make a couple of changes:
- If you haven’t already,
cd
back up fromlibtiff-<version>
tovolrend
:$ cd ..
- Delete (or move, if you prefer that) the old
libtiff
:(note the omission of$ rm -rf libtiff
<version>
, do not delete your new version!) - Create a symlink to the custom
libtiff
install directory so thatvolrend
still finds the expected libraries (this is slightly hacky, but it works):$ ln -sv libtiff-<version>/install_dir/lib libtiff
- Modify the
volrend
Makefile to not destroy the work we just did, and to correctly compile and link against the newlibtiff
:- Remove
libtiff/libtiff.a
fromOBJS
. - In
CFLAGS
, change-I./libtiff
to-I./libtiff/../include
(not the prettiest, I know; feel free to leave a comment in the website repo discussion if you have a better idea) and append to the end of line:-ltiff -lm
. - In
LDFLAGS
, append to the end of the line:-lm
. - Remove the
libtiff/libtiff.a
target and its recipe. - Add an
all
target depending on$(OBJS)
which compilesVOLREND
:all: $(OBJS) $(MAKE) VOLREND
- Remove the
$(MAKE) -C libtiff clean
line from theclean
target’s recipe. - (If you feel unsure about making the changes above yourself,
here is a patch you can apply
by copying it to the
codes
directory and runningfrom the$ patch -p0 < splash3-volrend-makefile-patch.diff
codes
directory.)
- Remove
Cross-compiling Splash-3 (finally)
Having configured and cross-compiled an entirely different, but necessary, thing and made some modifications to integrate it, we can now finally cross-compile Splash-3.
If you haven’t already, cd
back up to the codes
directory.
As with libtiff
, we need to disable shared libraries since they may not be
available on gem5. To do this, append -static
to CFLAGS
in
Makefile.config
.
Now we then get to reap the fruits of doing the tedious setup: Just run
$ TOOLCHAIN_PREFIX="${ARMv8_XTOOLS}" make
And everything should (hopefully) just compile nicely.
I hope this was helpful. Trying to figure out other people’s build process in
order to do something slightly convoluted can be frustrating, but then finally
seeing the make
output just scroll by without any problems is great! ^^