Toolchain Container Images: Difference between revisions
Pzimmermann (talk | contribs) No edit summary |
Jneuhauser (talk | contribs) →Images with native Debian GCC toolchain: Drop duplicate |
||
(5 intermediate revisions by 2 users not shown) | |||
Line 5: | Line 5: | ||
For cross developing of applications we provide Docker container images with preinstalled toolchains. | For cross developing of applications we provide Docker container images with preinstalled toolchains. | ||
You need to have Docker installed ([https://docs.docker.com/engine/install/ How to install Docker]), in our [[Virtual Machine for Application Development|VM for Application Development]] starting with Stretch Vxx Docker is preinstalled and preconfigured. | |||
You need to have Docker installed ([https://docs.docker.com/engine/install/ How to install Docker]), in our VM starting with Stretch Vxx Docker is preinstalled and preconfigured. | |||
The container images are available [https://hub.docker.com/ Docker Hub]. | The container images are available [https://hub.docker.com/ Docker Hub]. | ||
You can check which commands are executed for each layer in an image, and thus the installed packages, by clicking a specific tag in the Tag tab of an image on [https://hub.docker.com/ Docker Hub]. | |||
Here is an example for the image [https://hub.docker.com/layers/dhelectronics/debian-build-essential/stretch-amd64/images/sha256-12438156065c6cda9e5edcc8e25e553d78a9f14c2eaaadc7e7069e2515b93911?context=repo dhelectronics/debian-build-essential:stretch-amd64]. | |||
'''Note''': For userspace application development, we recommend using the ELBE/Yocto-SDK which came with your root filesystem. | '''Note''': For userspace application development, we recommend using the ELBE/Yocto-SDK which came with your root filesystem. | ||
Line 18: | Line 20: | ||
At the Docker repository <tt>[https://hub.docker.com/r/dhelectronics/debian-build-essential dhelectronics/debian-build-essential]</tt> images with the standard native GCC toolchain of Debian are located. | At the Docker repository <tt>[https://hub.docker.com/r/dhelectronics/debian-build-essential dhelectronics/debian-build-essential]</tt> images with the standard native GCC toolchain of Debian are located. | ||
The images are based on the Debian (slim-varaiant) image with <tt>cmake</tt>, <tt>ccache</tt>, <tt>curl</tt>, <tt>bc</tt>, <tt>lzop</tt>, <tt>xz-utils</tt> | The images are based on the Debian (slim-varaiant) image with <tt>cmake</tt>, <tt>ccache</tt>, <tt>curl</tt>, <tt>bc</tt>, <tt>lzop</tt>, <tt>xz-utils</tt>, <tt>jq</tt> and other tools additionally installed. | ||
The Debian GCC toolchain is installed via the package <tt>debian-build-essential</tt>. | The Debian GCC toolchain is installed via the package <tt>debian-build-essential</tt>. | ||
Line 30: | Line 32: | ||
* If your host is on Debian '''stretch or earlier''', you have to include the usermode emulator into the container at the start of your container. This can be done with a bind mount. Add the option <tt>--mount type=bind,src=/usr/bin/qemu-arm-static,dst=/usr/bin/qemu-arm-static</tt> to the run command of the container. | * If your host is on Debian '''stretch or earlier''', you have to include the usermode emulator into the container at the start of your container. This can be done with a bind mount. Add the option <tt>--mount type=bind,src=/usr/bin/qemu-arm-static,dst=/usr/bin/qemu-arm-static</tt> to the run command of the container. | ||
* If your host is on Debian '''buster or later''', this works automaticly. You don't have to alter the run command of the container. | * If your host is on Debian '''buster or later''', this works automaticly. You don't have to alter the run command of the container. | ||
Note that running a conatiner on emulated hardware affects the performance of the compiler. | |||
Tests have indicated that building the Linux kernel with one thread on the native armhf compiler running on an amd64 machine with emulation is about 9 times slower than building the same kernel with one thread on the same machine via a crossbuild compiler. | |||
For easing the use with the [[Toolchain_Container_Images#Use_the_symlink_wrapper|symlink-wrapper]] script, aliases for <tt>make</tt> and <tt>cmake</tt> are created: <tt>make-container</tt> and <tt>cmake-container</tt>. These can be used at the symlink-script as additional symlinks which won't collide with the host system's <tt>make</tt> and <tt>cmake</tt> so that the complete build can run inside one container. | |||
=== Images with Debian crossbuild GCC toolchain === | |||
At the Docker repository <tt>[https://hub.docker.com/r/dhelectronics/debian-cross-build-essential dhelectronics/debian-cross-build-essential]</tt> images with the Debian GCC toolchain for crosscompiling are located. | |||
All images are based on the debian images (slim varaiant) and run on an amd64 host. The standard Debian crossbuild toolchain is used. This toolchain is installed via the package <tt>crossbuild-essentail-armhf</tt>. | |||
The packages <tt>bc</tt>, <tt>bison</tt>, <tt>build-essential</tt>, <tt>ca-certificates</tt>, <tt>ccache</tt>, <tt>cmake</tt>, <tt>curl</tt>, <tt>flex</tt>, <tt>git</tt>, <tt>jq</tt>, <tt>ketchup</tt>, <tt>libssl-dev</tt>, <tt>lzop</tt> and <tt>xz-utils</tt> additionally installed, so that the images are suited to build the Linux kernel. | |||
The | The tags have the schema '''<tt>DIST</tt>-<tt>ARCH</tt>''': | ||
* '''<tt>DIST</tt>''': Determines which debian version the container image is based on. | |||
* '''<tt>ARCH</tt>''': Determines which the architecture for which the cross toolchain builds. Note that the architecture names of Docker are used as an example Debian's <tt>armhf</tt> corresponds to <tt>arm32v7</tt>. | |||
For easing the use with the [[Toolchain_Container_Images#Use_the_symlink_wrapper|symlink-wrapper]] script, aliases for <tt>make</tt> and <tt>cmake</tt> are created: <tt>make-cross</tt> and <tt>cmake-cross</tt>. These can be used at the symlink-script as additional symlinks which won't collide with the host system's <tt>make</tt> and <tt>cmake</tt> so that the complete build can run inside one container. | |||
=== | === Images with Linaro/ARM toolchain === | ||
These images use the toolchain of Linaro (up to GCC 7) or ARM (beginning with GCC 8) | At the Docker repository <tt>[https://hub.docker.com/r/dhelectronics/linaro-cross-build dhelectronics/linaro-cross-build]</tt> images with the Linaro/ARM GCC toolchain for crosscompiling are located. | ||
These images use the toolchain of Linaro (up to GCC 7) or ARM (beginning with GCC 8) and uses the debian-slim image as a basis for this image. | |||
The toolchain is installed inside <tt>/opt</tt> and the <tt>PATH</tt>-variable is extened to include the directory with the binaries of the toolchain. | The toolchain is installed inside <tt>/opt</tt> and the <tt>PATH</tt>-variable is extened to include the directory with the binaries of the toolchain. | ||
The packages <tt>bc</tt>, <tt>bison</tt>, <tt>build-essential</tt>, <tt>ca-certificates</tt>, <tt>ccache</tt>, <tt>cmake</tt>, <tt>curl</tt>, <tt>flex</tt>, <tt>git</tt>, <tt>jq</tt>, <tt>ketchup</tt>, <tt>libssl-dev</tt>, <tt>lzop</tt> and <tt>xz-utils</tt> additionally installed, so that the images are suited to build the Linux kernel. | |||
The tags have the schema '''<tt>DIST</tt>-<tt>ARCH</tt>-<tt>VERSION</tt>''': | |||
* '''<tt>DIST</tt>''': Determines which debian version the container image is based on. | |||
* '''<tt>ARCH</tt>''': Determines which the architecture for which the cross toolchain builds. Note that the architecture names of Docker are used as an example Debian's `armhf` corresponds to <tt>arm32v7</tt>. | |||
* '''<tt>VERSION</tt>''': Determines which version of the toolchain is used. There are two kinds of versions: '''<tt>X.Y\[.Z\]-yyyy.mm</tt>''' does explictly point to a specific version of the toolchain. '''<tt>X</tt>''' points to the latest version of the major version of the toolchain, of which a image is existing. It is possible that some versions of the toolchain are skipped. | |||
For easing the use with the [[Toolchain_Container_Images#Use_the_symlink_wrapper|symlink-wrapper]] script, aliases for <tt>make</tt> and <tt>cmake</tt> are created: <tt>make-cross</tt> and <tt>cmake-cross</tt>. These can be used at the symlink-script as additional symlinks which won't collide with the host system's <tt>make</tt> and <tt>cmake</tt> so that the complete build can run inside one container. | |||
== Using the containers == | == Using the containers == | ||
Line 56: | Line 73: | ||
You can start the container with the current work directory mounted into the container: | You can start the container with the current work directory mounted into the container: | ||
<tt>$ docker run -it --rm --mount type=bind,src= | <tt>$ docker run -it --rm --mount type=bind,src=$(pwd)/,dst=$(pwd) --workdir $(pwd) --user $(id -u):$(id -g) dhelectronics/linaro-cross-build:buster-arm32v7-8.3-2019.03</tt> | ||
After the container has started a console is open, now you can run any command to build the application (e.g. <tt>make all</tt>). | After the container has started a console is open, now you can run any command to build the application (e.g. <tt>make all</tt>). | ||
Line 65: | Line 82: | ||
Alternativly you can call the build command directly at the run command of the container: | Alternativly you can call the build command directly at the run command of the container: | ||
<tt>$ docker run -it --rm --mount type=bind,src= | <tt>$ docker run -it --rm --mount type=bind,src=$(pwd)/,dst=$(pwd) --workdir $(pwd) --user $(id -u):$(id -g) dhelectronics/linaro-cross-build:stretch-arm32v7-6.3.1-2017.05 make all</tt> | ||
=== Use the symlink wrapper === | === Use the symlink wrapper === | ||
We created a python script called <tt>[[Docker Symlink Wrapper|docker-symlink-wrapper.py]]</tt> (Not yet downloadable). | We created a python script called <tt>[[Docker Symlink Wrapper|docker-symlink-wrapper.py]]</tt> (Not yet downloadable). | ||
This script can create symlinks which point | This script can create symlinks which point to a container. | ||
If | Technicly, these symlinks point to the script. | ||
It is possible to set the tag of the container image which should be started. This example uses the | If the script called over a symlink, it looks up which container should be called. | ||
This container is then started with the name of the symlink as command to execute. | |||
All arguments are passed to the container, If something is piped into STDIN, it is passed into the container, too. | |||
It is possible to set the tag of the container image which should be started. | |||
This example uses the <tt>linaro-cross-build</tt>-toolchain, what the commands are doing exactly, [[Docker_Symlink_Wrapper#Available_Commands|look at the documentation of the symlink wrapper]]. | |||
To create the symlinks, you need a JSON file which defines the needed things about the container images: | To create the symlinks, you need a JSON file which defines the needed things about the container images: | ||
<nowiki>{ | <nowiki>{ | ||
"symlinks":[ | |||
"arm-linux-gnueabihf-as", | |||
"arm-linux-gnueabihf-ld", | |||
"arm-linux-gnueabihf-gcc", | |||
"arm-linux-gnueabihf-g++", | |||
"arm-linux-gnueabihf-ar", | |||
"arm-linux-gnueabihf-nm", | |||
"arm-linux-gnueabihf-strip", | |||
"arm-linux-gnueabihf-objcopy", | |||
"arm-linux-gnueabihf-objdump", | |||
"make-cross", | |||
"cmake-cross" | |||
], | |||
"registry":"", | |||
"image":"dhelectronics/linaro-cross-build", | |||
"tag":"buster-arm32v7-8", | |||
"installpath":"/usr/local/bin" | |||
}</nowiki> | }</nowiki> | ||
Line 106: | Line 130: | ||
<nowiki>docker-symlink-wrapper.py list-versions cross-build</nowiki> | <nowiki>docker-symlink-wrapper.py list-versions cross-build</nowiki> | ||
To set the tag (= version of the toolchain) of the container, there is a command. As an example if you want to use Linaro | To set the tag (= version of the toolchain) of the container, there is a command. As an example if you want to use version 6.3.1-2017.05 of the Linaro toolchain (based on Debian stretch): | ||
<nowiki>sudo docker-symlink-wrapper.py set-version cross-build stretch-arm32v7-6.3.1-2017.05</nowiki> | |||
=== Remove images which aren't needed anymore === | |||
If you want to delete a container image which you do not need anymore you can enter: | |||
<tt>docker image rm <imagename+tag></tt> | |||
If you download a newer version of an image, the old version won't be automaticly removed, the old image won't be accessible by its name and tag. This kind of image is called "dangling image". To remove all dangling images (so they won't take any space on disk) you can enter | |||
< | <tt>docker image prune</tt> | ||
== Extend the container with libraries == | == Extend the container with libraries == | ||
Line 119: | Line 153: | ||
You can a new container image which includes the needed library. | You can a new container image which includes the needed library. | ||
For this you need to create a new Dockerfile inside an empty container. | For this you need to create a new Dockerfile inside an empty container. | ||
Here is an example <tt>Dockerfile</tt> to include the C/C++ libraries of mosquitto (MQTT-broker/client) into the <tt>debian-build-essential</tt>: | Here is an example <tt>Dockerfile</tt> to include the C/C++ libraries of mosquitto (MQTT-broker/client) into the <tt>debian-build-essential</tt> image: | ||
<nowiki>FROM dhelectronics/debian-build-essential:buster-arm32v7 | <nowiki>FROM dhelectronics/debian-build-essential:buster-arm32v7 |
Latest revision as of 11:03, 27 October 2022
DH electronics provides Docker images with preinstalled toolchains.
Introduction
For cross developing of applications we provide Docker container images with preinstalled toolchains. You need to have Docker installed (How to install Docker), in our VM for Application Development starting with Stretch Vxx Docker is preinstalled and preconfigured. The container images are available Docker Hub.
You can check which commands are executed for each layer in an image, and thus the installed packages, by clicking a specific tag in the Tag tab of an image on Docker Hub. Here is an example for the image dhelectronics/debian-build-essential:stretch-amd64.
Note: For userspace application development, we recommend using the ELBE/Yocto-SDK which came with your root filesystem. This is because the SDKs comes with all needed development headers and libraries for its respective root filesystem.
Available Toolchains
Images with native Debian GCC toolchain
At the Docker repository dhelectronics/debian-build-essential images with the standard native GCC toolchain of Debian are located.
The images are based on the Debian (slim-varaiant) image with cmake, ccache, curl, bc, lzop, xz-utils, jq and other tools additionally installed. The Debian GCC toolchain is installed via the package debian-build-essential.
Tags consists of a combination of the used version of Debian and the architecture of the image (e.g. buster-amd64). Currently there is any combination of the Debian versions jessie, stretch and buster with the architectures amd64, arm32v5 and arm32v7 is possible. Note that Docker uses another names for distinguishing the different architectures of ARM processors: arm32v5 corresponds to Debian's armel while arm32v7 corresponds to Debian's armhf architecture.
You can use QEMU's user mode emulation for running the ARM-containers on an amd64-machine, the resulting software of a build still runs on the respective ARM architecture. To use this you have to install the packages binfmt-support and qemu-user-static on the host. To activate this for the container:
- If your host is on Debian stretch or earlier, you have to include the usermode emulator into the container at the start of your container. This can be done with a bind mount. Add the option --mount type=bind,src=/usr/bin/qemu-arm-static,dst=/usr/bin/qemu-arm-static to the run command of the container.
- If your host is on Debian buster or later, this works automaticly. You don't have to alter the run command of the container.
Note that running a conatiner on emulated hardware affects the performance of the compiler. Tests have indicated that building the Linux kernel with one thread on the native armhf compiler running on an amd64 machine with emulation is about 9 times slower than building the same kernel with one thread on the same machine via a crossbuild compiler.
For easing the use with the symlink-wrapper script, aliases for make and cmake are created: make-container and cmake-container. These can be used at the symlink-script as additional symlinks which won't collide with the host system's make and cmake so that the complete build can run inside one container.
Images with Debian crossbuild GCC toolchain
At the Docker repository dhelectronics/debian-cross-build-essential images with the Debian GCC toolchain for crosscompiling are located.
All images are based on the debian images (slim varaiant) and run on an amd64 host. The standard Debian crossbuild toolchain is used. This toolchain is installed via the package crossbuild-essentail-armhf. The packages bc, bison, build-essential, ca-certificates, ccache, cmake, curl, flex, git, jq, ketchup, libssl-dev, lzop and xz-utils additionally installed, so that the images are suited to build the Linux kernel.
The tags have the schema DIST-ARCH:
- DIST: Determines which debian version the container image is based on.
- ARCH: Determines which the architecture for which the cross toolchain builds. Note that the architecture names of Docker are used as an example Debian's armhf corresponds to arm32v7.
For easing the use with the symlink-wrapper script, aliases for make and cmake are created: make-cross and cmake-cross. These can be used at the symlink-script as additional symlinks which won't collide with the host system's make and cmake so that the complete build can run inside one container.
Images with Linaro/ARM toolchain
At the Docker repository dhelectronics/linaro-cross-build images with the Linaro/ARM GCC toolchain for crosscompiling are located.
These images use the toolchain of Linaro (up to GCC 7) or ARM (beginning with GCC 8) and uses the debian-slim image as a basis for this image. The toolchain is installed inside /opt and the PATH-variable is extened to include the directory with the binaries of the toolchain. The packages bc, bison, build-essential, ca-certificates, ccache, cmake, curl, flex, git, jq, ketchup, libssl-dev, lzop and xz-utils additionally installed, so that the images are suited to build the Linux kernel.
The tags have the schema DIST-ARCH-VERSION:
- DIST: Determines which debian version the container image is based on.
- ARCH: Determines which the architecture for which the cross toolchain builds. Note that the architecture names of Docker are used as an example Debian's `armhf` corresponds to arm32v7.
- VERSION: Determines which version of the toolchain is used. There are two kinds of versions: X.Y\[.Z\]-yyyy.mm does explictly point to a specific version of the toolchain. X points to the latest version of the major version of the toolchain, of which a image is existing. It is possible that some versions of the toolchain are skipped.
For easing the use with the symlink-wrapper script, aliases for make and cmake are created: make-cross and cmake-cross. These can be used at the symlink-script as additional symlinks which won't collide with the host system's make and cmake so that the complete build can run inside one container.
Using the containers
Open console inside the container
You can start the container with the current work directory mounted into the container:
$ docker run -it --rm --mount type=bind,src=$(pwd)/,dst=$(pwd) --workdir $(pwd) --user $(id -u):$(id -g) dhelectronics/linaro-cross-build:buster-arm32v7-8.3-2019.03
After the container has started a console is open, now you can run any command to build the application (e.g. make all). When the build is finished, you can quit the console with CTRL+D.
Call the buildsystem at container start
Alternativly you can call the build command directly at the run command of the container:
$ docker run -it --rm --mount type=bind,src=$(pwd)/,dst=$(pwd) --workdir $(pwd) --user $(id -u):$(id -g) dhelectronics/linaro-cross-build:stretch-arm32v7-6.3.1-2017.05 make all
Use the symlink wrapper
We created a python script called docker-symlink-wrapper.py (Not yet downloadable). This script can create symlinks which point to a container. Technicly, these symlinks point to the script. If the script called over a symlink, it looks up which container should be called. This container is then started with the name of the symlink as command to execute. All arguments are passed to the container, If something is piped into STDIN, it is passed into the container, too. It is possible to set the tag of the container image which should be started.
This example uses the linaro-cross-build-toolchain, what the commands are doing exactly, look at the documentation of the symlink wrapper.
To create the symlinks, you need a JSON file which defines the needed things about the container images:
{ "symlinks":[ "arm-linux-gnueabihf-as", "arm-linux-gnueabihf-ld", "arm-linux-gnueabihf-gcc", "arm-linux-gnueabihf-g++", "arm-linux-gnueabihf-ar", "arm-linux-gnueabihf-nm", "arm-linux-gnueabihf-strip", "arm-linux-gnueabihf-objcopy", "arm-linux-gnueabihf-objdump", "make-cross", "cmake-cross" ], "registry":"", "image":"dhelectronics/linaro-cross-build", "tag":"buster-arm32v7-8", "installpath":"/usr/local/bin" }
Then you can call the symlink script with superuser privileges to create the symlinks:
sudo docker-symlink-wrapper.py install cross-build install.json
Now the symlinks are installed and every call to arm-linux-gnueabihf-gcc and the other symlinks will go into the container. Note that when calling a symlink only the current working directory is mounted into the container! If you want to compile a file, you have to be inside the directory of the file or one of its parent directories.
To get the list of available versions of the toolchain you can use the following command:
docker-symlink-wrapper.py list-versions cross-build
To set the tag (= version of the toolchain) of the container, there is a command. As an example if you want to use version 6.3.1-2017.05 of the Linaro toolchain (based on Debian stretch):
sudo docker-symlink-wrapper.py set-version cross-build stretch-arm32v7-6.3.1-2017.05
Remove images which aren't needed anymore
If you want to delete a container image which you do not need anymore you can enter:
docker image rm <imagename+tag>
If you download a newer version of an image, the old version won't be automaticly removed, the old image won't be accessible by its name and tag. This kind of image is called "dangling image". To remove all dangling images (so they won't take any space on disk) you can enter
docker image prune
Extend the container with libraries
Note: If you only need libraries which came on your root filesystem, we recommend using the ELBE/Yocto-SDK which came with this root filesystem. In the SDK the corresponding headers and libraries are already preinstalled.
Create a modified container image
You can a new container image which includes the needed library. For this you need to create a new Dockerfile inside an empty container. Here is an example Dockerfile to include the C/C++ libraries of mosquitto (MQTT-broker/client) into the debian-build-essential image:
FROM dhelectronics/debian-build-essential:buster-arm32v7 RUN apt-get update && apt-get install -y --no-install-recommends libmosquitto-dev libmosquittopp-dev
Now you can create the new container image with:
docker build -t your-custom-image:latest .
After that the container can be started like any other container. If you want to use the symlink script, you have to create your own JSON file to create the symlinks. The symlinks of the normal debian-build-essential container images have to be removed because they would collide with each other (unless you install the symlinks into another directory but then the symlink which comes first inside the PATH enviornmental variable will be prefered over the other which can cause unwanted behavior).
Install libraries at runtime
When you run a console inside the container, you can run apt to install addional libraries. Note that when the container is removed, any changes to the container are lost.
Include libraries and headers into your project folder
You can include needed libraries and headers into a sub directory of your project directory which is mounted into the container. So you do not need to modify the image or the container at runtime.