* Add ranges * Initial Hugo setup * Work in progress * Added selection for local or remote site * Updated to 'light' theme * Changed to using Hextra Hugo theme * Changed to using Hextra Hugo theme * Changed to Hextra Hugo theme * Change to Hextra Hugo theme * Updated Hugo setup. * Updated Hugo setup. # Conflicts: # docs/releases/_index.md * Work in progress * Added new fonts Added new documentation * Latest documentation updates * Latest documentation updates # Conflicts: # docs/containers/array.md # docs/containers/array_view.md # docs/containers/array_wrapper.md # docs/containers/bip_buffer_spsc_atomic.md # docs/containers/bitset.md # docs/containers/indirect_vector.md # docs/containers/vector.md # docs/getting-started/compilers.md * Added bloom_filter markdown doc * Added more documentation Updated CSS for light and dark modes * Fixed some menus Added mode documentation files * Updated CSS rules Added badges to home page Added uniqur_ptr + pool tutorial * Fixed formatting on the home page markdown Modified light amd dark code formatting * Updated unique_ptr-with-pool * Added container and shared message tutorials * Updates to documentation * Added const_multimap * Updated source-formatting.md * Added initial raw text files form Web site editor * Innore coverage build directory * Exported raw text documentation files from the web site editor * Hugo updates * Added Hugo intalation and markdown descriptions * More addition to the documentation * Added closure.md and updates to delegate.md * Added format.md * Added documentation for etl::delegate_observable, etl::function, Base64 codec * Added io_port documentation * Added basic_format_spec * Added documentation for string_stream and string utilities. * Added more documentation Updated the documentation CSS * Added documentation for clocks, day, duration * Added more documentation for chrono classes Updated callouts * More chrono documentation * Completed chrono documentation * Maths functions documentation * Completed maths documentation * Completed maths documentation * Completed maths documentation * Completed maths documentation * Added multiple documentation files * Added iterator.md * Added debug_count.md and versions.md * Added debug_count.md and versions.md * Added more documentation * More documentation * Added some design pattern documentation Modified some of the layout files Modified the About documentation * Converted more documentation pages Modified the site CSS * Added more documentation Moced some documentation files to new directories * Added more documentation Tweaks to CSS * Added callback_timer_deferred_locked documentation * Added callback_timer_locked documentation * More documentation updates * More documentation updates * More documentation updates * New documentation files. Harmonised file name format * New documentation files. * Multiple document updates * Multiple document updates * Final conversion of web pages * Updates before PR * Updates before PR * Updates before PR # Conflicts: # docs/blog/_index.md * Final pre PR updates * Updates to message framework documentation * Renamed directory * Fix spelling * Added author and date to blog files Moved documentation files merged from development * Fixed 'Description' typo * Fix typos # Conflicts: # docs/IO/io_port.md # docs/containers/sets/const-multiset.md # docs/containers/sets/const-set.md # docs/maths/correlation.md # docs/maths/gamma.md * Renamed two files to lower case * Minor renaming * Added author and date * Updated callout on bresenham_line.md Added support for showing the ETL version on the documentation first page, by copying the version.txt file as a hugo asset. Updated the Python 'update_release.py' to copy 'version.txt' * Replace space in filename with hyphen. Added more information to hugo-commands.md * Replace space in filename with hyphen. Added more information to hugo-commands.md # Conflicts: # docs/getting-started/view-the-docs-locally/hugo-commands.md * Added a link to pseudo_moving_average.md * Updated title pages for groups * Fixed missing 404 for non-existent pages * Fixed coordinate variable names in the 'Calculating the intersection' example --------- Co-authored-by: Roland Reichwein <Roland.Reichwein@bmw.de> Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com> Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.co.uk>
9.9 KiB
| title | weight |
|---|---|
| Docker for Development | 3 |
Overview
The ETL repository ships a set of Docker-based development environments under
.devcontainer/. They give every contributor an identical, reproducible toolchain
regardless of host operating system. Three flavours are provided:
| Flavour | Path | Purpose |
|---|---|---|
| Default | .devcontainer/ |
Day-to-day development (Microsoft C++ dev-container base image) |
| Compiler-specific | .devcontainer/gcc09/ … .devcontainer/gcc15/, .devcontainer/clang7/ … .devcontainer/clang21/ |
Test against a specific GCC or Clang version |
| s390x big-endian | .devcontainer/s390x/ |
Cross-compile and run tests on an s390x target via QEMU |
All containers include CMake, Make, Git, Python 3, cogapp (the code generator used by ETL), clang-format 18, and treefmt.
Prerequisites
- Docker (or Docker Desktop) – any recent version that supports
docker buildanddocker run. - VS Code with the Dev Containers extension (optional, but recommended for the smoothest experience).
- Git – to clone the repository.
Quick Start
Using the helper script
The fastest way to get a shell inside the default container from the project root:
./scripts/run-docker.sh
This script performs two steps:
- Builds the image from
.devcontainer/Dockerfileand tags itetl. - Runs an interactive container that bind-mounts the repository at
/home/vscode/etlso that edits made inside the container are visible on the host (and vice versa).
You are dropped into a Bash shell as the vscode user with the working
directory set to the repository root.
Using VS Code Dev Containers
- Open the repository folder in VS Code.
- When prompted, click Reopen in Container – or run the command Dev Containers: Reopen in Container from the command palette.
- VS Code reads
.devcontainer/devcontainer.json, builds the image, and attaches to the running container automatically.
To open a specific compiler variant instead, run
Dev Containers: Open Folder in Container… and pick the sub-folder (e.g.
.devcontainer/gcc14/), or use the command palette action
Dev Containers: Open Named Container Configuration… and select the desired
name (e.g. "Gcc 14", "Clang 18").
Default Development Container
The file .devcontainer/Dockerfile is a multi-purpose image used by the
default configuration and by every compiler-specific variant (they simply
override the BASE_IMAGE_NAME build argument).
Base image
mcr.microsoft.com/devcontainers/cpp:2
The exact digest is pinned in devcontainer.json so that builds are
reproducible even if the upstream tag is updated.
Installed tools
The Dockerfile installs the following on top of the base image:
| Tool | Purpose |
|---|---|
python3, pip |
Runtime for helper scripts |
python3-cogapp / cogapp |
ETL code generator |
git |
Version control |
wget |
Downloading additional tooling |
cmake, make |
Build system |
clang-format (v18) |
Source formatting (see source-formatting.md) |
treefmt (v2.4.1) |
Single-command formatting wrapper |
Reproducible builds with Debian snapshots
The default configuration sets the build argument
DEBIAN_SNAPSHOT=20260223T000000Z. When this value is not "none", the
Dockerfile rewrites the APT sources to point at
snapshot.debian.org/archive/debian/<timestamp>, ensuring that every
contributor installs identical package versions. Compiler-specific variants
that are based on upstream gcc:* or silkeh/clang:* images set
DEBIAN_SNAPSHOT=none because those images manage their own package sources.
Compiler-Specific Containers
Each sub-folder under .devcontainer/ contains a devcontainer.json that
reuses the same Dockerfile (../Dockerfile) but overrides the
BASE_IMAGE_NAME build argument to select a different compiler.
GCC variants
| Folder | Base image | Name |
|---|---|---|
gcc09/ |
gcc:9 |
Gcc 09 |
gcc10/ |
gcc:10 |
Gcc 10 |
gcc11/ |
gcc:11 |
Gcc 11 |
gcc12/ |
gcc:12 |
Gcc 12 |
gcc13/ |
gcc:13 |
Gcc 13 |
gcc14/ |
gcc:14 |
Gcc 14 |
gcc15/ |
gcc:15 |
Gcc 15 |
Clang variants
| Folder | Base image | Name |
|---|---|---|
clang7/ |
silkeh/clang:7 |
Clang 7 |
clang8/ |
silkeh/clang:8 |
Clang 8 |
clang9/ |
silkeh/clang:9 |
Clang 9 |
clang10/ |
silkeh/clang:10 |
Clang 10 |
clang11/ |
silkeh/clang:11 |
Clang 11 |
clang12/ |
silkeh/clang:12 |
Clang 12 |
clang13/ |
silkeh/clang:13 |
Clang 13 |
clang14/ |
silkeh/clang:14 |
Clang 14 |
clang15/ |
silkeh/clang:15 |
Clang 15 |
clang16/ |
silkeh/clang:16 |
Clang 16 |
clang17/ |
silkeh/clang:17 |
Clang 17 |
clang18/ |
silkeh/clang:18 |
Clang 18 |
clang19/ |
silkeh/clang:19 |
Clang 19 |
clang20/ |
silkeh/clang:20 |
Clang 20 |
clang21/ |
silkeh/clang:21 |
Clang 21 |
All compiler-specific variants set DEBIAN_SNAPSHOT to "none" because they
rely on the upstream image's own package sources.
s390x Big-Endian Cross-Compilation
The s390x container lives in .devcontainer/s390x/ and has its own
Dockerfile (it does not reuse the default one). It is based on
debian:trixie and installs:
- QEMU user-mode emulation (
qemu-user-static,qemu-user,binfmt-support) - s390x cross-compilation toolchain (
gcc-s390x-linux-gnu,g++-s390x-linux-gnu) - CMake, Make, Ninja, Git, wget
Container setup
Open .devcontainer/s390x/ as a Dev Container in VS Code, or build manually:
docker build -t etl-s390x .devcontainer/s390x
docker run -it --rm -v .:/workspaces/etl -w /workspaces/etl etl-s390x
CMake toolchain
A CMake toolchain file is provided at
.devcontainer/s390x/toolchain-s390x.cmake. It sets:
CMAKE_SYSTEM_PROCESSORtos390x- Cross-compilers
s390x-linux-gnu-gcc/g++ CMAKE_CROSSCOMPILING_EMULATORto/usr/bin/qemu-s390x-static
The VS Code Dev Container configuration already passes this toolchain file
via cmake.configureArgs, so CMake Tools picks it up automatically.
Running tests under QEMU
Because the toolchain file sets CMAKE_CROSSCOMPILING_EMULATOR, CTest
automatically invokes qemu-s390x-static when running test binaries.
No extra flags are needed:
cmake -S test -B build-s390x \
-DCMAKE_TOOLCHAIN_FILE=.devcontainer/s390x/toolchain-s390x.cmake \
-DBUILD_TESTS=ON -DNO_STL=OFF -DETL_CXX_STANDARD=17 -G Ninja
cmake --build build-s390x
ctest --test-dir build-s390x
Building and Running Tests
Once inside any container (default, compiler-specific, or s390x) you can build and run the ETL test suite.
Quick CMake workflow
# Configure – build tests with C++17
cmake -S test -B build -DBUILD_TESTS=ON -DETL_CXX_STANDARD=17
# Build
cmake --build build -j $(nproc)
# Run tests
ctest --test-dir build
Change DETL_CXX_STANDARD to 11, 14, 17, 20, or 23 as needed.
Add -DNO_STL=ON to build without the standard library.
Using the run-tests script
The repository also provides a convenience script in test/:
cd test
./run-tests.sh <standard> [optimisation] [threads] [sanitizer] [compiler] [verbose]
| Argument | Values | Default |
|---|---|---|
| C++ standard | 11, 14, 17, 20, 23 |
(required) |
| Optimisation | 0, 1, 2, 3 |
0 |
| Threads | any integer | 4 |
| Sanitizer | s (enable) / n (disable) |
n |
| Compiler | gcc / clang |
all |
| Verbose | v (enable) / n (disable) |
n |
Example – run C++17 tests at -O2 with 8 threads using GCC:
./run-tests.sh 17 2 8 n gcc n
Formatting Inside the Container
The default container ships with clang-format 18 and treefmt. See source-formatting.md for the full formatting guide.
Quick reference:
# Format all tracked C/C++ files with treefmt
treefmt
# Or use clang-format directly via the wrapper
./scripts/clang-format-wrapper -i include/etl/*.h
The wrapper script scripts/clang-format-wrapper resolves the correct
clang-format binary (prefers clang-format-18, falls back to clang-format
after checking the major version).
Customisation
To add extra packages or tools to the default container, edit
.devcontainer/Dockerfile. The image follows a straightforward
apt-get install pattern, so adding a new package is as simple as appending
it to the existing apt-get line.
To create a new compiler variant:
- Create a folder under
.devcontainer/(e.g..devcontainer/gcc16/). - Add a
devcontainer.jsonthat references"../Dockerfile"and setsBASE_IMAGE_NAMEto the desired image (e.g.gcc:16). - Set
DEBIAN_SNAPSHOTto"none"for upstream compiler images.
Example:
{
"name": "Gcc 16",
"build": {
"dockerfile": "../Dockerfile",
"args": {
"BASE_IMAGE_NAME": "gcc:16",
"DEBIAN_SNAPSHOT": "none"
},
"context": "../context"
}
}
Troubleshooting
| Symptom | Cause / Fix |
|---|---|
apt-get fails with "Release file … is not valid yet" |
The Debian snapshot timestamp is in the future relative to the build host clock. Either update DEBIAN_SNAPSHOT in devcontainer.json or set it to "none". |
clang-format reports the wrong version |
The wrapper expects version 18. Make sure the image installs clang-format (or clang-format-18) and that the binary is on PATH. |
| Permission errors on mounted files | The run-docker.sh script runs as user vscode. Ensure your host UID matches, or adjust the --user flag. |
| s390x tests crash immediately | Verify that qemu-user-static is installed and that binfmt-support is active. On some hosts you may need to register binfmt handlers with docker run --privileged --rm tonistiigi/binfmt --install all. |
| Build is very slow the first time | Docker is downloading and building the image from scratch. Subsequent builds use the layer cache and are much faster. |