-
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
$ sudo apt update
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
# newer versions of the distribution.
deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu bionic main restricted
# deb-src http://archive.ubuntu.com/ubuntu bionic main restricted
## Major bug fix updates produced after the final release of the
## distribution.
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
$ sudo apt-get install -y build-essential libssl-dev python python-is-python3
$ sudo apt-get install -y crossbuild-essential-armhf
$ sudo apt-get install -y libssl-dev:armhf
$ git clone https://github.com/macchina-io/macchina.io.git --branch feature/v8-8.x
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.
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:
#
# X-Ubuntu-Focal--RPi
#
# Make settings for Raspberry Pi (2 or newer) Ubuntu 20.04
#
#
#
# General Settings
#
LINKMODE ?= SHARED
TOOL ?= arm-linux-gnueabihf
POCO_TARGET_OSNAME = Linux
POCO_TARGET_OSARCH ?= armv7l
ARCHFLAGS ?= -march=armv7-a -mfloat-abi=hard -mfpu=neon-vfpv4
#
# Define Tools
#
CC = $(TOOL)-gcc
CXX = $(TOOL)-g++
LINK = $(CXX)
LIB = $(TOOL)-ar -cr
RANLIB = $(TOOL)-ranlib
SHLIB = $(CXX) -shared -Wl,-soname,$(notdir $@) -o $@
SHLIBLN = $(POCO_BASE)/build/script/shlibln
STRIP = $(TOOL)-strip
DEP = $(POCO_BASE)/build/script/makedepend.gcc
SHELL = sh
RM = rm -rf
CP = cp
MKDIR = mkdir -p
#
# Extension for Shared Libraries
#
SHAREDLIBEXT = .so.$(target_version)
SHAREDLIBLINKEXT = .so
#
# Compiler and Linker Flags
#
CFLAGS = -std=c99 $(ARCHFLAGS)
CFLAGS32 =
CFLAGS64 =
CXXFLAGS = -std=gnu++14 -Wall -Wno-sign-compare $(ARCHFLAGS)
CXXFLAGS32 =
CXXFLAGS64 =
LINKFLAGS =
LINKFLAGS32 =
LINKFLAGS64 =
STATICOPT_CC =
STATICOPT_CXX =
STATICOPT_LINK = -static
SHAREDOPT_CC = -fPIC
SHAREDOPT_CXX = -fPIC
SHAREDOPT_LINK = -Wl,-rpath,$(LIBPATH)
DEBUGOPT_CC = -g -D_DEBUG
DEBUGOPT_CXX = -g -D_DEBUG
DEBUGOPT_LINK = -g
RELEASEOPT_CC = -O2 -DNDEBUG
RELEASEOPT_CXX = -O2 -DNDEBUG
RELEASEOPT_LINK = -O2
#
# System Specific Flags
#
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
#
# System Specific Libraries
#
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.
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
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