makefiles/docker: add support for tinybuild and smallbuild
Contribution description
This PR is a first draft to add support for tinybuild and smallbuild in the RIOT build system and automagically selects the right image to use depending on the featureset.
Doing this as a bash-script inside of the make recipe isn't super nice, but I couldn't come up with anything better tbh.
The better solution would be to craft a Dockerfile that distinguishes between the platforms and possibly also gets $(CPU_ARCH) and $(USEMODULE) as parameters. Then it would be easier to keep the platforms in sync, because it's in the riotdocker repository and not here. Something like build-dispatcher.
There is Multi-Stage building in Docker, but I have no experience with that and for the build-dispatcher image, we'd have to pull Alpine Linux again I guess? So there would be a size penalty.
Testing procedure
To test whether the switch-case distinguishes correctly between the variants, I just replaced the docker command with echo:
cbuec@W11nMate:~/RIOTstuff/riot-guides/RIOT$ BUILD_IN_DOCKER=1 DOCKER=echo BOARD=nrf52840dk make -C examples/basic/hello-world/
make: Entering directory '/home/cbuec/RIOTstuff/riot-guides/RIOT/examples/basic/hello-world'
Launching build container using image "docker.io/riot/tinybuild-arm@sha256:08fa7da2c702ac4db7cf57c23fc46c1971f3bffc4a6eff129793f853ec808736".
run --rm --tty --user 1000 --platform linux/amd64 -v /usr/share/zoneinfo/Europe/Berlin:/etc/localtime:ro -v /home/cbuec/RIOTstuff/riot-guides/RIOT:/data/riotbuild/riotbase:delegated -v /home/cbuec/.cargo/registry:/data/riotbuild/.cargo/registry:delegated -v /home/cbuec/.cargo/git:/data/riotbuild/.cargo/git:delegated -e RIOTBASE=/data/riotbuild/riotbase -e CCACHE_BASEDIR=/data/riotbuild/riotbase -e BUILD_DIR=/data/riotbuild/riotbase/build -e BUILD_IN_DOCKER=/data/riotbuild/riotbase/examples/basic/hello-world/1 -e RIOTPROJECT=/data/riotbuild/riotbase -e RIOTCPU=/data/riotbuild/riotbase/cpu -e RIOTBOARD=/data/riotbuild/riotbase/boards -e RIOTMAKE=/data/riotbuild/riotbase/makefiles -e BOARD=nrf52840dk -e DISABLE_MODULE= -e DEFAULT_MODULE= -e FEATURES_REQUIRED= -e FEATURES_BLACKLIST= -e FEATURES_OPTIONAL= -e USEMODULE= -e USEPKG= -w /data/riotbuild/riotbase/examples/basic/hello-world/ docker.io/riot/tinybuild-arm@sha256:08fa7da2c702ac4db7cf57c23fc46c1971f3bffc4a6eff129793f853ec808736 make
make: Leaving directory '/home/cbuec/RIOTstuff/riot-guides/RIOT/examples/basic/hello-world'
cbuec@W11nMate:~/RIOTstuff/riot-guides/RIOT$ BUILD_IN_DOCKER=1 DOCKER=echo BOARD=nrf52840dk make -C examples/lang_support/official/riot_and_cpp/
make: Entering directory '/home/cbuec/RIOTstuff/riot-guides/RIOT/examples/lang_support/official/riot_and_cpp'
Launching build container using image "docker.io/riot/smallbuild-arm@sha256:08fa7da2c702ac4db7cf57c23fc46c1971f3bffc4a6eff129793f853ec808736".
run --rm --tty --user 1000 --platform linux/amd64 -v /usr/share/zoneinfo/Europe/Berlin:/etc/localtime:ro -v /home/cbuec/RIOTstuff/riot-guides/RIOT:/data/riotbuild/riotbase:delegated -v /home/cbuec/.cargo/registry:/data/riotbuild/.cargo/registry:delegated -v /home/cbuec/.cargo/git:/data/riotbuild/.cargo/git:delegated -e RIOTBASE=/data/riotbuild/riotbase -e CCACHE_BASEDIR=/data/riotbuild/riotbase -e BUILD_DIR=/data/riotbuild/riotbase/build -e BUILD_IN_DOCKER=/data/riotbuild/riotbase/examples/lang_support/official/riot_and_cpp/1 -e RIOTPROJECT=/data/riotbuild/riotbase -e RIOTCPU=/data/riotbuild/riotbase/cpu -e RIOTBOARD=/data/riotbuild/riotbase/boards -e RIOTMAKE=/data/riotbuild/riotbase/makefiles -e BOARD=nrf52840dk -e DISABLE_MODULE= -e DEFAULT_MODULE= -e FEATURES_REQUIRED=cpp libstdcpp -e FEATURES_BLACKLIST= -e FEATURES_OPTIONAL= -e USEMODULE= -e USEPKG= -w /data/riotbuild/riotbase/examples/lang_support/official/riot_and_cpp/ docker.io/riot/smallbuild-arm@sha256:08fa7da2c702ac4db7cf57c23fc46c1971f3bffc4a6eff129793f853ec808736 make
make: Leaving directory '/home/cbuec/RIOTstuff/riot-guides/RIOT/examples/lang_support/official/riot_and_cpp'
Select the legacy riotbuild:
cbuec@W11nMate:~/RIOTstuff/riot-guides/RIOT$ BUILD_IN_DOCKER=1 DOCKER=echo DOCKER_IMAGE_VARIANT=riotbuild B
OARD=nrf52840dk make -C examples/basic/hello-world/
make: Entering directory '/home/cbuec/RIOTstuff/riot-guides/RIOT/examples/basic/hello-world'
Launching build container using image "docker.io/riot/riotbuild@sha256:08fa7da2c702ac4db7cf57c23fc46c1971f3bffc4a6eff129793f853ec808736".
run --rm --tty --user 1000 --platform linux/amd64 -v /usr/share/zoneinfo/Europe/Berlin:/etc/localtime:ro -v /home/cbuec/RIOTstuff/riot-guides/RIOT:/data/riotbuild/riotbase:delegated -v /home/cbuec/.cargo/registry:/data/riotbuild/.cargo/registry:delegated -v /home/cbuec/.cargo/git:/data/riotbuild/.cargo/git:delegated -e RIOTBASE=/data/riotbuild/riotbase -e CCACHE_BASEDIR=/data/riotbuild/riotbase -e BUILD_DIR=/data/riotbuild/riotbase/build -e BUILD_IN_DOCKER=/data/riotbuild/riotbase/examples/basic/hello-world/1 -e RIOTPROJECT=/data/riotbuild/riotbase -e RIOTCPU=/data/riotbuild/riotbase/cpu -e RIOTBOARD=/data/riotbuild/riotbase/boards -e RIOTMAKE=/data/riotbuild/riotbase/makefiles -e BOARD=nrf52840dk -e DISABLE_MODULE= -e DEFAULT_MODULE= -e FEATURES_REQUIRED= -e FEATURES_BLACKLIST= -e FEATURES_OPTIONAL= -e USEMODULE= -e USEPKG= -w /data/riotbuild/riotbase/examples/basic/hello-world/ docker.io/riot/riotbuild@sha256:08fa7da2c702ac4db7cf57c23fc46c1971f3bffc4a6eff129793f853ec808736 make
make: Leaving directory '/home/cbuec/RIOTstuff/riot-guides/RIOT/examples/basic/hello-world'
Issues/PRs references
Depends on https://github.com/RIOT-OS/riotdocker/pull/259.
Okay, since Makefiles aren't supposed to check the FEATURES_ variable, I had to move the image variant selection into the recipe where the USEMODULE variable is fully resolved.
It is not incredibly beautiful the way it is, but it would be easy to move it to a dedicated shell script now. The reason I stepped away from the build-dispatcher for now is that we'd have to give it the full USEMODULE variable as argument/environment, the APPLICATION_RUST_MODULE and the CPU_ARCH variable.
Perhaps one could do some magic to conditionally set arguments like uses_cpp or uses_rust when USEMODULE contains cpp or APPLICATION_RUST_MODULE is set. But then you'd have like a third of the decision making back in the recipe and not in the shell script.
I'd like to get some input if this is the right direction or if we should pursue the build-dispatcher idea further.
We could also just drop that check.
To my knowledge the reason for that check has been that once upon a timer there was no FEAUTRES_USED and FEATURES_PROVIDED variables and automatic management of features, but something like:
ifneq (,$(filter periph_i2c,$(FEATURES_REQUIRED))
$(error "Sorry, that feature is not available here")
endif
The check was to ensure that old PRs don't get merged to re-introduce that legacy pattern.
IMO that check has succeeded and could now be dropped.
This is pretty much on hold until the riotdocker PR is merged anyway, but thanks for testing :)