diff --git a/Dockerfile b/Dockerfile index fd4c372..ecb0b23 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,7 +44,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # Pinned commits for each component. ARG BINUTILS_COMMIT=686c3b0673c89fae3d03ee22a9d9ac9ce29bfa75 ARG GCC_COMMIT=d6995f34118ad2a5ed2f0408a3a8af44568bf2ee -ARG NEWLIB_COMMIT=e12d84a6789c07f938db4f6440ea0b427914c735 +# Pinned to the merge commit of nanvix/newlib#TBD ("[libc] F: Weaken +# _do_start so libnvx_crt0.a can override it cleanly"). Update this +# SHA to the upstream merge commit before merging the present PR. +ARG NEWLIB_COMMIT=881840f880350e6fd929629cef9a5a3d1708bbf4 ARG NEWLIB_BRANCH=dev ENV PREFIX=/opt/nanvix @@ -61,9 +64,14 @@ RUN git clone https://github.com/nanvix/binutils /build/binutils && \ RUN git clone https://github.com/nanvix/gcc /build/gcc && \ cd /build/gcc && git checkout ${GCC_COMMIT} -# Clone Newlib. -RUN git clone --branch ${NEWLIB_BRANCH} --single-branch --depth=1 \ - https://github.com/nanvix/newlib /build/newlib +# Clone Newlib and pin to ${NEWLIB_COMMIT} (prior versions of this +# Dockerfile cloned with --depth=1 only and silently used the tip of +# ${NEWLIB_BRANCH} regardless of the declared pin, which made the +# build non-reproducible). Fetching with sufficient depth and then +# checking out ${NEWLIB_COMMIT} restores the pin. +RUN git clone --branch ${NEWLIB_BRANCH} \ + https://github.com/nanvix/newlib /build/newlib && \ + cd /build/newlib && git checkout ${NEWLIB_COMMIT} # Build Binutils. RUN cd /build/binutils && \ diff --git a/Dockerfile.localpatch-do_start b/Dockerfile.localpatch-do_start new file mode 100644 index 0000000..ef68bb6 --- /dev/null +++ b/Dockerfile.localpatch-do_start @@ -0,0 +1,56 @@ +# Local-only Dockerfile to validate the nanvix/newlib `_do_start` weakening +# fix WITHOUT a full toolchain rebuild. Starts from the official base image +# and surgically rebuilds the `crt0.S` source from a patched newlib tree, +# then overlays the resulting `crt0.o` onto the toolchain sysroot. +# +# After this patch: +# * `/opt/nanvix/i686-nanvix/lib/crt0.o` defines `_do_start` as a WEAK +# (`W`) symbol instead of STRONG (`T`). +# * `libnvx_crt0.a`'s strong `_do_start` override now wins at link time +# without `-Wl,--allow-multiple-definition`. +# +# Usage (run from `D:\src\toolchain-gcc-dev`): +# docker build --build-context newlib=D:\src\newlib-dev ` +# -f Dockerfile.localpatch-do_start ` +# -t local-nanvix/toolchain-gcc:do_start-weak . +# +# Verification: +# docker run --rm local-nanvix/toolchain-gcc:do_start-weak ` +# i686-nanvix-nm /opt/nanvix/i686-nanvix/lib/crt0.o +# Expected: `00000000 W _do_start` (weak, not strong T). + +FROM ghcr.io/nanvix/toolchain-gcc:sha-34a3641 + +# DO NOT set `ENV TARGET=` or `ENV PREFIX=` here. The published +# toolchain-gcc runtime image deliberately drops those build-time +# variables; setting them again leaks into autotools-based downstream +# builds. In particular, libffi's `AX_ENABLE_BUILDDIR` macro +# (m4/ax_enable_builddir.m4) computes its build subdir from `$TARGET` +# if the variable is set, defeating config.sub's canonicalization of +# `i686-nanvix` -> `i686-pc-nanvix`. The result is that the build +# lands in `./i686-nanvix/` while `Makefile.nanvix` and `z.py` look +# in `./i686-pc-nanvix/`, breaking the link step. +# +# The `PATH` extension is the only inherited env override that is +# safe and necessary. + +# Copy just the patched crt0.S source. +COPY --from=newlib newlib/libc/sys/nanvix/crt0.S /build/patch/crt0.S + +# Normalize line endings — Windows checkouts may carry CRLF. +RUN sed -i 's/\r$//' /build/patch/crt0.S + +# Reassemble crt0.S into crt0.o. +RUN /opt/nanvix/bin/i686-nanvix-as \ + /build/patch/crt0.S \ + -o /build/patch/crt0.o + +# Replace the toolchain sysroot's crt0.o. +RUN cp /build/patch/crt0.o /opt/nanvix/i686-nanvix/lib/crt0.o + +# Verify: _do_start must now be WEAK, not STRONG. +RUN result=$(/opt/nanvix/bin/i686-nanvix-nm /opt/nanvix/i686-nanvix/lib/crt0.o); \ + echo "$result"; \ + echo "$result" | grep -qE '^[0-9a-f]+ W _do_start$' \ + || (echo "VERIFY FAILED: _do_start is not WEAK in patched crt0.o" && exit 1) \ + && echo "VERIFY OK: _do_start is now WEAK in crt0.o"