Skip to content

Instantly share code, notes, and snippets.

@acmlira
Last active August 14, 2020 17:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save acmlira/3b0aac83ff442c3a6050eb6af7d860bf to your computer and use it in GitHub Desktop.
Save acmlira/3b0aac83ff442c3a6050eb6af7d860bf to your computer and use it in GitHub Desktop.
Cross-compiling CMake project with Docker

Docker basics: cross-compiling a CMake project

In this article you will understand how I built my own cross-compile tool for my CMake project for Linux systems with Docker. Obviously, you will need:

  1. Docker installed;
  2. Some CMake project.

Let's start!

Describing our image

Docker is a powerful tool of OS virtualization to deliver software in packages called containers. These containers are stored in the form of images (that can be distributed). Let's take advantage of these possibilities in cool project starting with Docker descriptor file, the Dockerfile. You can put this file at the aside of your project:

.
├─ Dockerfile
└─ project
   ├─ CMakeLists.txt
   ├─ include/
   │    └─ hello-world.h   
   └─ src/
        └─ hello-world.cpp

In our Dockerfile we will add the following lines:

ARG AARCH=arm32v7
FROM ${AARCH}/ubuntu

I will use an ubuntu base image ofarm32v7 architecture for my project to run on a Raspberry PI. in this syntax, ARG defines a parameter that will assume the value passed in the command line or the default value defined in the Dockerfile and ${AARCH} defines the use of the value assigned to the argument. The next line we will add the dependencies to compile our project:

RUN apt-get update && apt-get install build-essential cmake --no-install-recommends

The packages we are going to install are:

  • build-essential: this package will install the compiler and some interesting ones that we can use later;
  • cmake: our build tool. We also passed the --no-install-recommends flag for image be more lightweighter. Why? That's a subject for another day. Finally we will add the last line:
WORKDIR /build

This command will isolate our artifacts from the rest of the system files. Our Dockerfile must be:

ARG AARCH=arm32v7
FROM ${AARCH}/ubuntu

RUN apt-get update && apt-get install build-essential cmake --no-install-recommends

WORKDIR /build

Building our image

To build containers of different architectures we must execute this command:

sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

Our compile command will be:

sudo docker build -t project/cross-compile .

HINT: -t set the image label.

Compiling our project

Let's create a build directory in root:

mkdir -p build

The ls response should be something like:

build/   Dockerfile   project/

Our compile command will be:

sudo docker run -v ~/Projects/build:/build        \
                -v ~/Projects/project:/project    \
                -t project/cross-compile          \
                bash -c "cmake ../project && cmake --build ."

About the latest command args:

  • -v: shares files between two paths, <host>:<docker>;
  • -t: informs which image will be used;
  • bash -c: command execution string inside the Docker image.

From now on, everything generated inside the Docker build folder will be shared with our host build folder. All this because we share our host project sources with the Docker project folder. As WORKDIR was setted to /build in the command string, we had to return one directories level: cmake ../project.

Why CMake?

This article was all written from my experience with changing the TotalCross build system. TotalCross is a cross-platform free open source GUI creator. How about starting in just 8 minutes? See more about TotalCross, the fastest way to build GUI!

If you liked this article, please clap and share your comments below! Did you like the TotalCross project? Support us with a star!

Thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment