Skip to content

Cross Compiling with CMake

Günter Obiltschnig edited this page Oct 13, 2022 · 1 revision

Introduction

The macchina.io REMOTE SDK and tools can be cross-compiled with CMake. In order to do that, a CMake toolchain file is required. The toolchain file tells CMake the name and path of the C++ compiler and a few other settings that may be required for cross-compiling.

When cross-compiling for an embedded Linux target, it may also be necessary to cross-compile OpenSSL first, if the platform's SDK does not already include the OpenSSL headers and libraries.

Note: if your toolchain does not support C++14 (e.g., GCC 4.8 or earlier), you may want to build the legacy-c++03 branch of the repository.

Cross-Compiling OpenSSL (1.1.1)

OpenSSL 1.1.1 can be cross-compiled for an embedded Linux target with the following commands.

Download and Extract OpenSSL

$ curl https://www.openssl.org/source/openssl-1.1.1q.tar.gz >openssl-1.1.1q.tar.gz
$ tar xfz openssl-1.1.1q.tar.gz

Configure and Cross-Compile OpenSSL

We assume that we will place the OpenSSL headers and libraries into the directory /home/build/openssl.

$ ./Configure linux-generic -DL_ENDIAN --prefix=/opt/build/openssl --openssldir=/opt/build/openssl

Optionally replace linux-generic32 with the proper OpenSSL os/compiler configuration (see ./Configure --help for a full list), e.g. linux-armv4 or linux-aarch64.

Then, build and install with:

$ make CROSS_COMPILE=arm-linux-

Replace arm-linux- with the name prefix of the cross-compiler you are using. Also, before running make, make sure that the cross-compiler executables (e.g., arm-linux-g++, etc.) are in your $PATH.

Finally, install with:

$ make install

This will place the headers, libraries and documentation in /opt/build/openssl (or whatever you have specified with the --prefix option to ./Configure).

Cross-Compiling the SDK and Tools

The CMake Toolchain File

In order to cross-compile with CMake, a toolchain file for the cross-compiling toolchain to be used has to be created.

In the simplest form, it looks like:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

#set(CMAKE_SYSROOT /opt/arm-linux/sysroot)
#set(CMAKE_STAGING_PREFIX /opt/arm-linux/staging)

set(tools /opt/arm-linux/bin)
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-g++)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

Save the toolchain file under the name arm-linux.toolchain in the top-level directory of the SDK (or somewhere else).

If your toolchain requires setting the SYSROOT and STAGING paths, you can uncomment the respective settings and set them appropriately. Otherwise, leave them commented-out.

In the above example we assume that the toolchain has been installed in /opt/arm-linux, with the compiler and other tools to be found in /opt/arm-linux/bin.

Cross-Compiling with CMake

Cross-compiling with CMake is not much different from a normal build, with the difference that the toolchain file has to be specified when running CMake.

$ mkdir cmake-build
$ cd cmake-build
$ cmake .. -DCMAKE_TOOLCHAIN_FILE=../arm-linux.toolchain -DOPENSSL_ROOT_DIR=/opt/build/openssl -DOPENSSL_USE_STATIC_LIBS=TRUE
$ make -s -j4

Note that in addition to the toolchain file, we also have to provide the OpenSSL directory where the cross-compiled OpenSSL libraries have been installed earlier. We also want to link OpenSSL statically, in order to avoid having to copy too many libraries to the target device (OPENSSL_USE_STATIC_LIBS=TRUE).

The resulting binaries will be in the cmake-build/bin directory. It's a good idea to strip them before copying them to the device.

$ arm-linux-strip bin/*