Source
FROM scratch AS build
ARG GCC_VERSION
ARG GMP_VERSION
ARG MPFR_VERSION
ARG MPC_VERSION
ARG ISL_VERSION
ARG BINUTILS_VERSION
ARG GLIBC_VERSION
ENV ARCH=x86_64
ENV BUILD=${ARCH}-linux-musl
ENV HOST=${ARCH}-linux-musl
ENV TARGET=${ARCH}-linux-gnu
ENV TZ=UTC
ENV LANG=C.UTF-8
ENV SOURCE_DATE_EPOCH=1
ENV KCONFIG_NOTIMESTAMP=1
ENV OUTPUT=/opt/cross
ENV PATH=/opt/cross/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
WORKDIR /
COPY --from=stagex/core-busybox . /
COPY --from=stagex/core-musl . /
COPY --from=stagex/core-gcc . /
COPY --from=stagex/core-binutils . /
COPY --from=stagex/core-make . /
COPY --from=stagex/core-gawk . /
COPY --from=stagex/core-linux-headers /usr/include/. ${OUTPUT}/${TARGET}/include/
COPY --from=stagex/core-bison . /
COPY --from=stagex/core-m4 . /
COPY --from=stagex/core-perl . /
COPY --from=stagex/core-python . /
COPY --from=stagex/core-grep . /
ADD fetch/binutils-${BINUTILS_VERSION}.tar.xz .
ADD fetch/gcc-${GCC_VERSION}.tar.xz .
ADD fetch/glibc-${GLIBC_VERSION}.tar.gz .
ADD fetch/gmp-${GMP_VERSION}.tar.bz2 .
ADD fetch/mpfr-${MPFR_VERSION}.tar.bz2 .
ADD fetch/mpc-${MPC_VERSION}.tar.gz .
ADD fetch/isl-${ISL_VERSION}.tar.bz2 .
WORKDIR /gcc-${GCC_VERSION}
RUN --network=none <<-EOF
set -eux
mv ../gmp-${GMP_VERSION} gmp
mv ../mpfr-${MPFR_VERSION} mpfr
mv ../mpc-${MPC_VERSION} mpc
mv ../isl-${ISL_VERSION} isl
EOF
# HACK: libgcc.a embeds .o files with timestamps ignoring SOURCE_DATE_EPOCH
COPY --from=stagex/core-libfaketime . /
ENV LD_PRELOAD=/usr/local/lib/faketime/libfaketime.so.1
ENV FAKETIME="1970-01-01 00:00:00 GMT"
# Phase 1: Build cross binutils
WORKDIR /build-binutils
RUN --network=none <<-EOF
set -eux
../binutils-${BINUTILS_VERSION}/configure \
--target=${TARGET} \
--prefix=${OUTPUT} \
--disable-multilib
make all -j "$(nproc)"
make install
EOF
# Phase 2: Build and install cross gcc, without libgcc
WORKDIR /build-gcc
RUN --network=none <<-EOF
set -eux
../gcc-${GCC_VERSION}/configure \
--target=${TARGET} \
--prefix=${OUTPUT} \
--enable-languages=c,c++ \
--disable-multilib \
--disable-libssp \
--disable-libsanitizer \
--enable-deterministic-archives
make all-gcc
make install-gcc
EOF
# Phase 4: Build and Install glibc headers for use by libgcc
WORKDIR /build-glibc
RUN --network=none <<-EOF
set -eux
sed -i 's/--yacc //' \
../glibc-${GLIBC_VERSION}/intl/Makefile
../glibc-${GLIBC_VERSION}/configure \
--prefix=${OUTPUT}/${TARGET} \
--build=${BUILD} \
--host=${TARGET} \
--target=${TARGET} \
--with-headers=${OUTPUT}/${TARGET}/include \
--disable-multilib \
--disable-werror \
libc_cv_forced_unwind=yes
make \
install-bootstrap-headers=yes \
install-headers
make -j "$(nproc)" csu/subdir_lib
mkdir -p ${OUTPUT}/${TARGET}/lib ${OUTPUT}/${TARGET}/include/gnu
install csu/crt1.o csu/crti.o csu/crtn.o -t ${OUTPUT}/${TARGET}/lib
${TARGET}-gcc \
-nostdlib \
-nostartfiles \
-shared \
-x c /dev/null \
-o ${OUTPUT}/${TARGET}/lib/libc.so
touch ${OUTPUT}/${TARGET}/include/gnu/stubs.h
EOF
# Phase 5: Build and install libgcc
WORKDIR /build-gcc
RUN --network=none <<-EOF
set -eux
make -j "$(nproc)" all-target-libgcc
make install-target-libgcc
EOF
# Phase 6: Build and install glibc
WORKDIR /build-glibc
RUN --network=none <<-EOF
set -eux
make -j "$(nproc)"
make install
EOF
# Phase 7: Build and install remaining gcc targets (C++)
WORKDIR /build-gcc
RUN --network=none <<-EOF
set -eux
make -j "$(nproc)"
make install
EOF
RUN --network=none <<-EOF
mkdir -p /rootfs/opt /rootfs/usr/bin
mv /opt/cross /rootfs/opt/cross
for bin_path in $(find /rootfs/opt/cross/bin -name ${TARGET}-*); do
bin_name=$(basename "$bin_path")
ln -s /opt/cross/bin/${bin_name} /rootfs/usr/bin/${bin_name}
done
EOF
FROM stagex/core-filesystem AS package
COPY --from=build /rootfs/ /