From f689a8df49a3636bfc49286ac393b79d526be70f Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Mon, 3 Feb 2025 10:47:53 -0800 Subject: [PATCH] Support building on an arm64 host too This adds a `.host-arch` symlink to build output; this doesn't get committed (for hopefully obvious reasons), but allows for things like `CMD` and `update.sh` to have a known-effective target for testing the output further in some way. This was a mapping we already had thanks to `ARCH_TEST`, so I've also reordered our builds such that they're grouped by "host" architecture and sorted by "preference"/compatibility (with the goal that we get a more "correct" `.host-arch` symlink). --- .dockerignore | 1 + .gitignore | 1 + Dockerfile.build | 54 ++++++++++++++++++++++++++---------------------- Makefile | 3 +++ update.sh | 4 ++-- 5 files changed, 36 insertions(+), 27 deletions(-) create mode 100644 .gitignore diff --git a/.dockerignore b/.dockerignore index 5edb8bf..0982361 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,5 +4,6 @@ *.sh .dockerignore .git* +.host-arch Dockerfile* LICENSE diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4956936 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.host-arch diff --git a/Dockerfile.build b/Dockerfile.build index 90510df..d22307f 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -3,6 +3,7 @@ FROM debian:bookworm-slim RUN set -eux; \ apt-get update; \ + dpkgArch="$(dpkg --print-architecture)"; \ apt-get install -y --no-install-recommends \ ca-certificates \ gnupg \ @@ -12,6 +13,8 @@ RUN set -eux; \ libc6-dev \ make \ \ +# these are all "arch:all" so we can just install all of them + libc6-dev-amd64-cross \ libc6-dev-arm64-cross \ libc6-dev-armel-cross \ libc6-dev-armhf-cross \ @@ -21,7 +24,9 @@ RUN set -eux; \ libc6-dev-riscv64-cross \ libc6-dev-s390x-cross \ \ - gcc-aarch64-linux-gnu \ +# the cross-compilers are particular about which architectures they build for, so for now we'll only support a host architecture of amd64 or arm64 + $([ "$dpkgArch" = 'amd64' ] || echo 'gcc-x86-64-linux-gnu') \ + $([ "$dpkgArch" = 'arm64' ] || echo 'gcc-aarch64-linux-gnu') \ gcc-arm-linux-gnueabi \ gcc-arm-linux-gnueabihf \ gcc-i686-linux-gnu \ @@ -54,32 +59,18 @@ RUN set -eux; \ WORKDIR /usr/src/hello COPY . . +# the following steps are grouped into "architecture families" and roughly ordered in a descending compatibility way such that we end up with the most accurate ".host-arch" symlink we can reasonably get + RUN set -ex; \ make clean all test \ TARGET_ARCH='amd64' \ CROSS_COMPILE='x86_64-linux-gnu-' \ ARCH_TEST='amd64' - RUN set -ex; \ make clean all test \ - TARGET_ARCH='arm32v5' \ - CROSS_COMPILE='arm-linux-gnueabi-' \ -# EXTRA_CFLAGS='-march=armv5te' \ - ARCH_TEST='armel' - -RUN set -ex; \ - make clean all test \ - TARGET_ARCH='arm32v6' \ - CROSS_COMPILE='arm-linux-gnueabi-' \ - EXTRA_CFLAGS='-march=armv6+fp' \ - ARCH_TEST='armhf' - -RUN set -ex; \ - make clean all test \ - TARGET_ARCH='arm32v7' \ - CROSS_COMPILE='arm-linux-gnueabihf-' \ -# EXTRA_CFLAGS='-march=armv7-a+fp' \ - ARCH_TEST='armhf' + TARGET_ARCH='i386' \ + CROSS_COMPILE='i686-linux-gnu-' \ + ARCH_TEST='i386' RUN set -ex; \ make clean all test \ @@ -89,9 +80,22 @@ RUN set -ex; \ RUN set -ex; \ make clean all test \ - TARGET_ARCH='i386' \ - CROSS_COMPILE='i686-linux-gnu-' \ - ARCH_TEST='i386' + TARGET_ARCH='arm32v7' \ + CROSS_COMPILE='arm-linux-gnueabihf-' \ +# EXTRA_CFLAGS='-march=armv7-a+fp' \ + ARCH_TEST='armhf' +RUN set -ex; \ + make clean all test \ + TARGET_ARCH='arm32v6' \ + CROSS_COMPILE='arm-linux-gnueabi-' \ + EXTRA_CFLAGS='-march=armv6+fp' \ + ARCH_TEST='armhf' +RUN set -ex; \ + make clean all test \ + TARGET_ARCH='arm32v5' \ + CROSS_COMPILE='arm-linux-gnueabi-' \ +# EXTRA_CFLAGS='-march=armv5te' \ + ARCH_TEST='armel' RUN set -ex; \ make clean all test \ @@ -118,6 +122,6 @@ RUN set -ex; \ CROSS_COMPILE='s390x-linux-gnu-' \ ARCH_TEST='s390x' -RUN find \( -name 'hello' -or -name 'hello.txt' \) -exec file '{}' + -exec ls -lh '{}' + +RUN find \( -name 'hello' -or -name 'hello.txt' -or -name '.host-arch' \) -exec file '{}' + -exec ls -lh '{}' + -CMD ["./amd64/hello-world/hello"] +CMD [".host-arch/hello-world/hello"] diff --git a/Makefile b/Makefile index 9e7a3eb..9b88341 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,9 @@ test: $(C_TARGETS) if [ -n "$$ARCH_TEST" ] && command -v arch-test > /dev/null && arch-test "$$ARCH_TEST" > /dev/null; then \ ( set -x && "./$$b" ); \ ( set -x && "./$$b" | grep -q '"'"$$(basename "$$(dirname "$$b")")"'"' ); \ + if [ ! -e .host-arch ] && arch-test -n "$$ARCH_TEST" > /dev/null; then \ + ln -svfT "$${b%%/*}" .host-arch; \ + fi; \ else \ echo >&2 "warning: $$TARGET_ARCH ($$ARCH_TEST) not supported; skipping test"; \ fi; \ diff --git a/update.sh b/update.sh index d0c1462..34d4ec4 100755 --- a/update.sh +++ b/update.sh @@ -8,7 +8,7 @@ set -x docker build -f Dockerfile.build -t hello-world:build . find */ \( -name hello -or -name hello.txt \) -delete -docker run --rm hello-world:build sh -c 'find \( -name hello -or -name hello.txt \) -print0 | xargs -0 tar --create' | tar --extract --verbose +docker run --rm hello-world:build sh -c 'find \( -name hello -or -name hello.txt -or -name .host-arch \) -print0 | xargs -0 tar --create' | tar --extract --verbose find -name hello -type f -exec dirname '{}' ';' | xargs -n1 -i'{}' cp Dockerfile-linux.template '{}/Dockerfile' find -name hello.txt -type f -exec dirname '{}' ';' | xargs -n1 -i'{}' cp Dockerfile-windows.template '{}/Dockerfile' @@ -20,7 +20,7 @@ for h in */*/nanoserver-*/Dockerfile; do sed -i 's!FROM .*!FROM mcr.microsoft.com/windows/nanoserver:'"$nano"'!' "$h" done -for h in amd64/*/hello; do +for h in .host-arch/*/hello; do d="$(dirname "$h")" b="$(basename "$d")" "$h" > /dev/null