Using Docker to host ARM toolchain to cross-compile C code

By: (plus.google.com) +David Herron; Date: 2017-01-19 16:27

Tags: Docker » Cross Compilation » ARM Compilation » Emdebian

I'm starting up a project that will see me doing custom software development for an ARM single-board-computer running Linux. The recommendation isn't to do compiles ON the board, but instead to cross compile from a Linux workstation (Debian). But, I use a Mac laptop, as do most software engineers these days. While I could run VirtualBox to set up a Debian cross-compiling environment, Docker is much lighter weight. While Docker was originally targeted for deploying server applications, it is useful for packaging anything. In this case there's a ready-made set of Docker containers for cross-compilation including for ARM CPU's.

My likely ARM hardware vendor conveniently gave excellent instructions for setting up a Debian workstation for cross-compiling: (wiki.embeddedarm.com) http://wiki.embeddedarm.com/wiki/TS-7680#Debian_Configuration Those instructions rely on cross-compilation tools created by http://emdebian.org/ and while the Emdebian project is essentially dead, they seem to still be maintaining the cross-compilation tools. Even that's not 100% true (it seems) because the Emdebian website refers you over to (wiki.debian.org) https://wiki.debian.org/CrossToolchains for instructions for the latest Debian (Jessie). But then those instructions tell you to add the Emdebian repository to your APT sources. Fortunately it's not entirely important for this tutorial to understand the status of the Emdebian project. For whatever reason we are to still use the Emdebian repository to access the compilation toolchain.

Simple Emdebian cross-compiling Docker container

My first stab at a Docker image was to transliterate the instructions on (embeddedarm.com) EmbeddedARM.com into a simple Dockerfile. But as we'll see in a minute there's a simpler method.

FROM debian:jessie

RUN apt-get update && apt-get install -y \
    apt-utils \
    curl \
    build-essential \
    automake \
    autogen \
    bash \
    build-essential \
    bc \
    bzip2 \
    ca-certificates \
    curl \
    file \
    git \
    gzip \
    make \
    ncurses-dev \
    pkg-config \
    libtool \
    python \
    rsync \
    sed \
    bison \
    flex \
    tar \
    vim \
    wget \
    runit \
    xz-utils

RUN echo "deb http://emdebian.org/tools/debian jessie main" > /etc/apt/sources.list.d/emdebian.list
RUN curl http://emdebian.org/tools/debian/emdebian-toolchain-archive.key | apt-key add -
RUN dpkg --add-architecture armel
RUN apt-get update && apt-get install -y crossbuild-essential-armel

# The cross-compiling emulator
RUN apt-get update && apt-get install -y \
    qemu-user \
    qemu-user-static

Create an empty directory and save that as Dockerfile. This Dockerfile brings in a lot of useful command-line tools that developers normally use.

With this you can run.

docker build --tag emdebian-for-technologic .
docker run -it --volume `pwd`:/workdir emdebian-for-technologic bash

The first command builds the Dockerfile, giving the image name emdebian-for-technologic. The second gives you a running shell inside the container. Use ls to look in /usr/bin and you'll see commands with names like arm-linux-gnueabi-gcc that are the cross-compilation toolchain.

Then you can create a file named hello.c containing:

#include <stdio.h>
int main(){
    printf("Hello World\n");
}

Then compile and run it as so:

root@c8007516bb30:/workdir# arm-linux-gnueabi-gcc hello.c -o hello
root@c8007516bb30:/workdir# file hello
hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=007ea7c5826104168af839653c3075b474a4d084, not stripped
root@c8007516bb30:/workdir# ./hello
Hello World

We've proved that GCC produced for us an ARM binary for ARMv5. The last command works because we installed qemu-user-static and qemu-user. The qemu tools let you run binaries for other architectures, like ARM, on your regular x86 workstation.

Dockcross - simplifying cross compilation for a wide range of platforms

While that's useful and straight-forward, I promised there was a simpler method. The Dockcross project - (github.com) https://github.com/dockcross/dockcross - makes cross-compilation using a Docker container simple. They provide Docker images for a long list of CPU architectures, and a simple way to use their Docker images from a regular command-line.

The first step is to install Docker on your laptop - presumably you're running either Mac OS X and need to install (docs.docker.com) Docker for Mac, or you're using Windows and need to install Docker for Windows. Both are the modern currently recommended way to run Docker on a non-Linux workstation.

The next step is to set up Dockcross for the given cross-compilation target. Unfortunately it's not clear from the EmbeddedARM website whether to use ARMv5 or what. By reading the Dockerfiles in the Dockcross project I see that the armel architecture corresponds to ARMv5. Therefore I ran this:

docker run --rm dockcross/linux-armv5 >dockcross-linux-armv5
chmod +x dockcross-linux-armv5
mv dockcross-linux-armv5 ~/bin

I can then compile code like so:

dockcross-linux-armv5 bash -c '$CC hello.c -o hello'

And run it as so:

$ file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, not stripped
$ file hello.c
hello.c: ASCII c program text
$ dockcross-linux-armv5 ./hello
Hello World

Since the hello binary is compiled for ARM, it shouldn't work. But the Dockcross container includes qemu-user-static allowing the binary to run.

You can also get a command-line shell in the container with this command:

dockcross-linux-armv5 bash
« The MEADS missile defense system. Will Romania be part of it? Swagger tutorial -- How to add Swagger OpenAPI to your REST API documentation »
2016 Election Acer C720 Ad block AkashaCMS Amazon Amazon Kindle Amiga Android Anti-Fascism AntiVirus Software Apple Apple Hardware History Apple iPhone Apple iPhone Hardware April 1st Arduino ARM Compilation Astronomy Asynchronous Programming Authoritarianism Automated Social Posting Ayo.JS Bells Law Big Brother Big Finish Bitcoin Mining Black Holes Blade Runner Blogger Blogging Books Botnet Botnets Cassette Tapes Cellphones Christopher Eccleston Chrome Chrome Apps Chromebook Chromebooks Chromebox ChromeOS CIA CitiCards Citizen Journalism Civil Liberties Clinton Cluster Computing Command Line Tools Computer Hardware Computer Repair Computers Cross Compilation Crouton Cryptocurrency Curiosity Rover Cyber Security Cybermen Daleks Darth Vader Data backup Data Storage Database Database Backup Databases David Tenant DDoS Botnet Detect Adblocker Developers Editors Digital Photography Diskless Booting DIY DIY Repair DNP3 Do it yourself Docker Docker Swarm Doctor Who Doctor Who Paradox Drobo Drupal Drupal Themes DVD E-Books E-Readers Early Computers Election Hacks Electric Bicycles Electric Vehicles Electron Emdebian Encabulators Energy Efficiency Enterprise Node EPUB ESP8266 Ethical Curation Eurovision Event Driven Asynchronous Express Facebook Fake News Fedora VirtualBox File transfer without iTunes FireFly Fraud Freedom of Speech Gallifrey git Gitlab GMAIL Google Google Chrome Google Gnome Google+ Government Spying Great Britain Heat Loss Hibernate Hoax Science Home Automation HTTPS I2C Protocol Image Analysis Image Conversion Image Processing ImageMagick InfluxDB Infrared Thermometers Insulation Internet Internet Advertising Internet Law Internet of Things Internet Policy Internet Privacy iOS Devices iPad iPhone iPhone hacking Iron Man Iternet of Things iTunes Java JavaScript JavaScript Injection JDBC John Simms Journalism Joyent Kaspersky Labs Kindle Marketplace Lets Encrypt LibreOffice Linux Linux Hints Linux Single Board Computers Logging Mac OS Mac OS X MacOS X setup Make Money Online MariaDB Mars Matt Lucas MEADS Anti-Missile Mercurial Michele Gomez Micro Apartments Military Hardware Minification Minimized CSS Minimized HTML Minimized JavaScript Missy Mobile Applications MODBUS Mondas MongoDB Mongoose Monty Python MQTT Music Player Music Streaming MySQL NanoPi Nardole NASA Net Neutrality Node Web Development Node.js Node.js Database Node.js Testing Node.JS Web Development Node.x North Korea Online advertising Online Fraud Online Journalism Online Video Open Media Vault Open Source Governance Open Source Licenses Open Source Software OpenAPI OpenVPN Personal Flight Peter Capaldi Photography PHP Plex Plex Media Server Political Protest Postal Service Power Control Privacy Production use Public Violence Raspberry Pi Raspberry Pi 3 Raspberry Pi Zero Recycling Remote Desktop Republicans Retro-Technology Reviews Right to Repair River Song Robotics Rocket Ships RSS News Readers rsync Russia Russia Troll Factory Russian Hacking SCADA Scheme Science Fiction Search Engine Ranking Season 1 Season 10 Season 11 Security Security Cameras Server-side JavaScript Shell Scripts Silence Simsimi Skype Social Media Social Media Warfare Social Networks Software Development Space Flight Space Ship Reuse Space Ships SpaceX Spear Phishing Spring Spring Boot SQLite3 SSD Drives SSD upgrade SSH SSH Key SSL Swagger Synchronizing Files Telescopes Terrorism The Cybermen The Daleks The Master Time-Series Database Torchwood Total Information Awareness Trump Trump Administration Trump Campaign Ubuntu UDOO Virtual Private Networks VirtualBox VLC VNC VOIP Web Applications Web Developer Resources Web Development Web Development Tools Web Marketing Website Advertising Weeping Angels WhatsApp Window Insulation Wordpress YouTube YouTube Monetization