Bookworm armhf cross compile docker: Difference between revisions

From embeddedTS Manuals
No edit summary
No edit summary
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
Debian provides cross toolchains within their distribution for different architectures. If you are running a matching system you can  
Debian provides cross toolchains within their distribution for different architectures.  
 
For best portability we recommend using a container like docker to run a Debian 12 rootfs for the toolchain. This will allow a consistent toolchain to run from almost any Linux system that can run Docker. Keep in mind that while docker does run under OSX and Windows, these are run under a case insensitive filesystem which will cause problems with complex builds like the Linux kernel so a Linux host is still recommended.


For best portability we recommend using a container like docker to run a Debian 12 rootfs for the toolchain.  On any Linux system first install docker.
* Ubuntu/Debian:
* Ubuntu/Debian:
<source lang=bash>
<source lang=bash>
apt-get install docker -y
sudo apt-get install docker.io -y
</source>
</source>


* Fedora
* Fedora
<source lang=bash>
<source lang=bash>
dnf install docker -y
sudo dnf install docker -y
</source>
</source>
After installing docker on any distribution make sure your user is in the docker group:


<source lang=bash>
<source lang=bash>
Line 17: Line 20:
</source>
</source>


Make sure you can run docker's hello world image to verify it is working:
Make sure you can run docker's hello world image as your user to verify it is working:
<source lang=bash>
<source lang=bash>
docker run hello-world
docker run hello-world
</source>
</source>


Now create a file "/opt/docker-toolchain/docker-debian-bookworm-armhf/Dockerfile" with these contents:
Now create a file Dockerfile:
<source lang=bash>
sudo mkdir -p /opt/docker-toolchain/docker-debian-bookworm-armhf
# Use any preferred editor, vim/emacs/nano/etc
sudo nano /opt/docker-toolchain/docker-debian-bookworm-armhf/Dockerfile
</source>
<source lang=bash>
<source lang=bash>
# syntax = docker/dockerfile:1.2
# syntax = docker/dockerfile:1.2
Line 94: Line 102:
ENV LANG en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8
ENV LANGUAGE en_US.UTF-8
# Needed for make dtbs_check
RUN pip3 install dtschema
</source>
</source>
Next make a shell script to enter into this docker container. In /usr/local/bin/docker-debian-bookworm:
Next make a shell script to enter into this docker container. Create /usr/local/bin/docker-debian-bookworm:
<source lang=bash>
# Use any preferred editor, vim/emacs/nano/etc
sudo nano /usr/local/bin/docker-debian-bookworm
</source>
<source lang=bash>
<source lang=bash>
#!/bin/bash -e
#!/bin/bash -e
Line 107: Line 116:
export TAG=debian-bookworm-armdev
export TAG=debian-bookworm-armdev
SCRIPTPATH=$(readlink -f "$0")
SCRIPTPATH=$(readlink -f "$0")
DOCKERPATH=$(dirname "$SCRIPTPATH")/../docker/debian-bookworm
DOCKERPATH=/opt/docker-toolchain/docker-debian-bookworm-armhf/


DOCKER_BUILDKIT=1 docker build --tag "$TAG" "$DOCKERPATH" --quiet
DOCKER_BUILDKIT=1 docker build --tag "$TAG" "$DOCKERPATH" --quiet
Line 123: Line 132:
Make this executable, and call it:
Make this executable, and call it:
<source lang=bash>
<source lang=bash>
chmod a+x /usr/local/bin/docker-debian-bookworm
sudo chmod a+x /usr/local/bin/docker-debian-bookworm


# dont run as root
docker-debian-bookworm
docker-debian-bookworm
</source>
</source>
The first time this runs it will download a base Debian image, and run the above apt-get commands which may take around 10 or so minutes depending on your internet connection and disk speed. After it has run once, it will stay cached and adds almost no overhead to run.
This docker can be thought of as a very low overhead virtual machine that only has access to the directory where it is run.
For example, to build a simple c project, create a ~/Desktop/hello-world/hello.c:
<source lang=bash>mkdir -p ~/Desktop/hello-world/</source>
In ~/Desktop/hello-world/hello.c:
<source lang=c>
#include <stdio.h>
int main() {
    printf("Hello world!\n");
    return 0;
}
</source>
We can now use the docker in that directory to use Debian's cross compiler to create a binary that targets armhf:
<console>
user@hostname:~$ cd ~/Desktop/hello-world/
user@hostname:~/Desktop/hello-world$ docker-debian-bookworm
sha256:a92e70c3d7346654b34c0442da20ae634901fd25d1a89dd26517e7d1c1d00c47
debian_bookworm@a8ddfa54989f:/work$ ls
hello.c
debian_bookworm@a8ddfa54989f:/work$ arm-linux-gnueabihf-gcc hello.c -o hello
debian_bookworm@a8ddfa54989f:/work$ arm-linux-gnueabihf-strip hello
debian_bookworm@a8ddfa54989f:/work$ file hello
hello: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=ffda981721a1531418ed1da27238707851ae0126, for GNU/Linux 3.2.0, stripped
</console>

Latest revision as of 10:16, 24 October 2023

Debian provides cross toolchains within their distribution for different architectures.

For best portability we recommend using a container like docker to run a Debian 12 rootfs for the toolchain. This will allow a consistent toolchain to run from almost any Linux system that can run Docker. Keep in mind that while docker does run under OSX and Windows, these are run under a case insensitive filesystem which will cause problems with complex builds like the Linux kernel so a Linux host is still recommended.

  • Ubuntu/Debian:
sudo apt-get install docker.io -y
  • Fedora
sudo dnf install docker -y

After installing docker on any distribution make sure your user is in the docker group:

# Add your user to the docker group.  You may need to logout/log back in.
sudo usermod -aG docker $USER

Make sure you can run docker's hello world image as your user to verify it is working:

docker run hello-world

Now create a file Dockerfile:

sudo mkdir -p /opt/docker-toolchain/docker-debian-bookworm-armhf
# Use any preferred editor, vim/emacs/nano/etc
sudo nano /opt/docker-toolchain/docker-debian-bookworm-armhf/Dockerfile
# syntax = docker/dockerfile:1.2

FROM debian:bookworm

RUN dpkg --add-architecture armhf

RUN apt-get update && apt-get install -y \
    autogen \
    automake \
    bash \
    bc \
    bison \
    build-essential \
    bzip2 \
    ca-certificates \
    ccache \
    chrpath \
    cpio \
    curl \
    diffstat \
    fakeroot \
    file \
    flex \
    gawk \
    gcc-arm-linux-gnueabihf \
    git \
    gzip \
    kmod \
    libgpiod-dev:armhf \
    libncursesw5-dev \
    libssl-dev \
    libtool \
    libyaml-dev \
    locales \
    lz4 \
    lzop \
    make \
    multistrap \
    ncurses-dev \
    pkg-config \
    python3 \
    python3-cbor \
    python3-pexpect \
    python3-pip \
    qemu-user-static \
    rsync \
    runit \
    socat \
    srecord \
    swig \ 
    texinfo \
    u-boot-tools \
    zstd \
    unzip \
    vim \
    wget \
    xz-utils

# Provide a more friendly name
ENV debian_chroot debian_bookworm
RUN echo "PS1='\${debian_chroot}\\[\033[01;32m\\]@\\H\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ '" >> /etc/bash.bashrc

# Set up locales
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
        echo 'LANG="en_US.UTF-8"'>/etc/default/locale && \
        dpkg-reconfigure --frontend=noninteractive locales && \
        update-locale LANG=en_US.UTF-8
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8

Next make a shell script to enter into this docker container. Create /usr/local/bin/docker-debian-bookworm:

# Use any preferred editor, vim/emacs/nano/etc
sudo nano /usr/local/bin/docker-debian-bookworm
#!/bin/bash -e

# Enters a docker running Debian 12 Bookworm
# Any arguments are run in the docker, or if no arguments it runs a shell

export TAG=debian-bookworm-armdev
SCRIPTPATH=$(readlink -f "$0")
DOCKERPATH=/opt/docker-toolchain/docker-debian-bookworm-armhf/

DOCKER_BUILDKIT=1 docker build --tag "$TAG" "$DOCKERPATH" --quiet

exec docker run --rm \
	-it \
	--volume "$(pwd)":/work \
	--user $(id -g):$(id -u) \
	-w /work \
	-e HOME=/tmp \
	"$TAG" \
	$@;

Make this executable, and call it:

sudo chmod a+x /usr/local/bin/docker-debian-bookworm

# dont run as root
docker-debian-bookworm

The first time this runs it will download a base Debian image, and run the above apt-get commands which may take around 10 or so minutes depending on your internet connection and disk speed. After it has run once, it will stay cached and adds almost no overhead to run.

This docker can be thought of as a very low overhead virtual machine that only has access to the directory where it is run.

For example, to build a simple c project, create a ~/Desktop/hello-world/hello.c:

mkdir -p ~/Desktop/hello-world/

In ~/Desktop/hello-world/hello.c:

#include <stdio.h>

int main() {
    printf("Hello world!\n");
    return 0;
}

We can now use the docker in that directory to use Debian's cross compiler to create a binary that targets armhf:

user@hostname:~$ cd ~/Desktop/hello-world/
user@hostname:~/Desktop/hello-world$ docker-debian-bookworm
sha256:a92e70c3d7346654b34c0442da20ae634901fd25d1a89dd26517e7d1c1d00c47
debian_bookworm@a8ddfa54989f:/work$ ls
hello.c
debian_bookworm@a8ddfa54989f:/work$ arm-linux-gnueabihf-gcc hello.c -o hello
debian_bookworm@a8ddfa54989f:/work$ arm-linux-gnueabihf-strip hello
debian_bookworm@a8ddfa54989f:/work$ file hello
hello: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=ffda981721a1531418ed1da27238707851ae0126, for GNU/Linux 3.2.0, stripped