-
Notifications
You must be signed in to change notification settings - Fork 156
Cross Compiling for Ubuntu 20.04 armhf with V8 8.x
This article describes how to cross-compile macchina.io (with V8 version 8.x) for an 32-bit ARM-based machine (armhf
architecture) running Ubuntu 20.04.
A Ubuntu 20.04 (bionic
) host system (VM) with the following packages installed:
- git
- build-essential
- libssl-dev
- python (3.x)
- crossbuild-essential-armhf
Cross-compiling V8 for a 32-bit ARM target needs a 32-bit toolchain on the host too.
So in addition to installing the cross-compiler for ARM, we also need to install support
for building and running 32-bit Intel (i386
) programs, as during the V8 build process,
code generators are built that must run with the same bit width as the target system.
First, we prepare the package manager to add i386
packages.
$ sudo dpkg --add-architecture i386
Then we add the i386
packages.
$ sudo apt install -y binutils-multiarch libc6-dev:i386 libstdc++-9-dev:i386 gcc-9-multilib g++-9-multilib
Then we need to prepare the package manager to install packages required for cross-compiling.
For example, the OpenSSL headers and libraries must be available for the `armhf` architecture.
$ sudo dpkg --add-architecture armhf
The Ubuntu packages for ARM are not available from the default Ubuntu package server, so we have
to add a new package source. Create a the file `/etc/apt/sources.list.d/arm-cross-compile-sources.list`
and add the following content:
deb [arch=armhf] http://ports.ubuntu.com/ focal main restricted deb [arch=armhf] http://ports.ubuntu.com/ focal-updates main restricted deb [arch=armhf] http://ports.ubuntu.com/ focal universe deb [arch=armhf] http://ports.ubuntu.com/ focal-updates universe deb [arch=armhf] http://ports.ubuntu.com/ focal multiverse deb [arch=armhf] http://ports.ubuntu.com/ focal-updates multiverse deb [arch=armhf] http://ports.ubuntu.com/ focal-backports main restricted universe multiverse
This will tell the package manager to look for packages for the specified architecture
(`armhf`) on `http://ports.ubuntu.com`.
Next, edit `/etc/apt/sources.list` and change the entries so that they are only
used for the `amd64` and `i386` architectures. This is done by inserting `[arch=amd64,i386]` after
every `deb` statement, e.g.:
See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu bionic main restricted
deb-src http://archive.ubuntu.com/ubuntu bionic main restricted
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu bionic-updates main restricted
deb-src http://archive.ubuntu.com/ubuntu bionic-updates main restricted
...
This change will prevent errors when updating the package index, since
`archive.ubuntu.com` only holds the packages for Intel architectures.
Next, update the package index:
$ sudo apt-get update
## Install the essential packages for building the host tools:
$ sudo apt-get install -y build-essential libssl-dev python python-is-python3
## Install the packages required for cross-compiling:
$ sudo apt-get install -y crossbuild-essential-armhf $ sudo apt-get install -y libssl-dev:armhf
# Building macchina.io
## Get macchina.io Sources from GitHub
$ git clone https://github.com/macchina-io/macchina.io.git
## Build the Host Tools
This will build the tools (e.g., *BundleCreator*) required for building macchina.io.
$ cd macchina.io $ make -s -j8 hosttools
This takes a couple of minutes.
Note: Depending on the number of CPU cores you have on your build machine, adjust the `-j8` argument accordingly.
## Build for Target
In order to build for the target, a build configuration file must be used.
You can find various build configuration files in `platform/build/config`.
Create a new build configuration file `X-Ubuntu-Focal-RPi` with the
following content:
LINKMODE ?= SHARED TOOL ?= arm-linux-gnueabihf POCO_TARGET_OSNAME = Linux POCO_TARGET_OSARCH ?= armv7l ARCHFLAGS ?= -march=armv7-a -mfloat-abi=hard -mfpu=neon-vfpv4
CC =
SHAREDLIBEXT = .so.$(target_version) SHAREDLIBLINKEXT = .so
CFLAGS = -std=c99
SYSFLAGS = -D_XOPEN_SOURCE=600 -D_REENTRANT -D_THREAD_SAFE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -DPOCO_HAVE_FD_EPOLL
-DPOCO_HAVE_ADDRINFO -DPOCO_HAVE_LIBRESOLV
SYSLIBS = -lpthread -ldl -lrt
You may need to change the `ARCHFLAGS` setting to match your target device.
To find out the CPU features on the target device, run:
$ cat /proc/cpuinfo
processor : 0 model name : ARMv7 Processor rev 0 (v7l) BogoMIPS : 10.00 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x3 CPU part : 0xc09 CPU revision : 0
Under `Features` you should see the available CPU features, specifically floating-point
support (like `neon`, `vfpv3` or `vfpv4`). If you build with CPU features that are
not available on the target machine (e.g., `vfpv4` on a Cortex-A8), the resulting
executable will abort with a `SIGILL` (illegal instruction).
The `POCO_CONFIG` environment (or Makefile) variable should contain the name
of the build configuration to use. Therefore, we run:
$ POCO_CONFIG=X-Ubuntu-Focal-RPi make -s -j8 DEFAULT_TARGET=shared_release
to build macchina.io for the target. The `DEFAULT_TARGET=shared_release` argument
instructs the build system to build the release executables only. If omitted,
the build system would build both debug and release executables.
Depending on build machine performance, this takes 20-30 minutes.
## Create Tarball for Transfer to Target
To build a directory structure and tarball that can be easily transferred to the
target device (e.g., via `scp`), use the `install_runtime` make target:
$ POCO_CONFIG=X-Ubuntu-Focal-RPi make -s install_runtime INSTALLDIR=/home/admin/macchina_runtime
This will create the following directory structure:
macchina_runtime/ lib/ bundles/ bin/ etc/
Then, pack the `macchina_runtime` directory into a tarball:
$ tar cfz macchina_runtime.tgz /home/admin/macchina_runtime
# Running macchina.io on the Target
Copy the tarball to the target (e.g., using `scp`) and expand it with:
$ tar xfz macchina_runtime.tgz
Before starting macchina.io, you have to set the `LD_LIBRARY_PATH` environment variable, so that the macchina.io shared libraries (both in the `lib` directory and in the `codeCache`) will be found.
$ export LD_LIBRARY_PATH=/path/to/macchina_runtime/lib:/path/to/macchina_runtime/bin/codeCache
You should also create the `codeCache` directory before you start macchina.io, so that the dynamic linker will find it. Otherwise, the first start of macchina.io may fail.
$ mkdir /path/to/macchina_runtime/bin/codeCache
Then you can start macchina.io:
$ /path/to/macchina_runtime/bin/macchina --config=/path/to/macchina_runtime/etc/macchina.properties