Conversation
mmmorks
force-pushed
the
pr/01-build-tooling
branch
from
September 8, 2026 04:11
bb47913 to
41a35c8
Compare
build-docker.sh builds linux_repeater for arm64 inside a Debian container,
so the firmware can be built from a non-Linux host. BASE_IMAGE selects the
container's libgpiod major (bookworm = 1.x, trixie = 2.x); each base gets
its own build directory and package-cache volume, because PlatformIO does
not track system headers and would otherwise relink objects compiled
against the other version's gpiod.h. The build runs without a TTY, and
FIRMWARE_VERSION reaches the compiler through PLATFORMIO_BUILD_FLAGS the
same way build.sh does it for the MCU targets, so `meshcored -V` reports
the version the script was asked for instead of the #ifndef default in
MyMesh.h. The artifacts left under the bind-mounted .pio are handed back
to the invoking user, scoped to this run's own paths so a read-only file
from another env's libdeps cannot fail the script after a successful
build; the three .pio parent directories get a separate non-recursive
chown, because on a Linux host the container is what creates them on a
fresh checkout, and the invoking user could otherwise no longer run
`pio test -e native`.
Build fixes found along the way:
* linux_base force-includes /usr/include/string.h when that path exists:
ArduinoCore-API and the ardulinux core use str*/mem* without including
it, which newer GCC/libstdc++ no longer provide transitively. The
existence test keeps the build usable where there is no /usr/include
-- unlike -I, an -include of a missing absolute path is fatal in every
translation unit.
* ConfigSerializer.cpp includes <stdlib.h> for atoi/atol/atof. MCU builds
reach these through Arduino.h; the host `native` test build does not,
and fails to compile on macOS without it.
* Drop [env:linux] from variants/linux/platformio.ini: it defines neither
RADIO_CLASS nor WRAPPER_CLASS (which target.cpp requires) and builds no
application, and nothing references it. Drop SKIP_CONFIG_OVERWRITE from
linux_repeater, which nothing reads.
* The unit file's own comment named /var/lib/systemd/system, a directory
systemd never reads; units install to /etc/systemd/system.
mmmorks
force-pushed
the
pr/01-build-tooling
branch
from
September 12, 2026 21:21
41a35c8 to
37a7709
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two scripts for building and shipping the Linux firmware, plus the small build fixes found while getting them to work on a fresh machine.
What changed
build-docker.shbuildslinux_repeaterfor arm64 inside a Debian container, so the firmware can be built from macOS or any host without the ardulinux toolchain.BASE_IMAGEpicks the libgpiod major the binary links against (debian:bookworm= 1.x, default;debian:trixie= 2.x). Each base gets its own build directory and PlatformIO cache volume, because PlatformIO does not track system headers and would otherwise relink objects compiled against the othergpiod.h. It runs without a TTY (so it works from CI and| tee), and hands the artifacts under the bind-mounted.pioback to the invoking user, scoped to this run's own paths so a read-only file left by another env cannot fail the script after a successful build.platformio.ini:linux_baseforce-includes/usr/include/string.h. ArduinoCore-API and the ardulinux core usestr*/mem*without including it, which newer GCC/libstdc++ no longer provide transitively. The absolute path matters (a bare-include string.hresolves to the Arduino shim), andstdlib.h/stdio.hmust not be added the same way (theirselect()collides with the static one inlib/ed25519/ge.c).src/helpers/ConfigSerializer.cppincludes<stdlib.h>foratoi/atol/atof. MCU builds reach these throughArduino.h; the hostnativetest build does not, and fails to compile on macOS without it (the wholepio test -e nativesuite errors on the currentlinuxbranch there).variants/linux/platformio.ini: drops[env:linux], which defines neitherRADIO_CLASSnorWRAPPER_CLASS(required bytarget.cpp) and builds no application, and theSKIP_CONFIG_OVERWRITEflag, which nothing reads.meshcored.service: the header comment named/var/lib/systemd/system, a directory systemd never reads.How it was tested
build-docker.shis how every Linux binary in this series was produced (bookworm and trixie bases, on Apple Silicon). The ownership fix-up was reproduced before and after the change with a planted read-only file under another env'slibdeps(build succeeded, chown failed, script exited 1 before; build and scoped chown succeeded after).pio test -e nativepasses on macOS (44 tests). Without theConfigSerializer.cppinclude the suite does not compile there.Dependencies
Independent. The other PRs in this series are based on it only so that their native tests compile on macOS.
Shared code touched
platformio.ini(linux_baseonly)src/helpers/ConfigSerializer.cpp(one include; also a candidate for meshcore-dev)