From 2aec1f35d28be69ac6b7014411a80744afe53f3e Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Sun, 9 Aug 2026 16:05:29 -0500 Subject: [PATCH 01/11] Add x86 multilib toolchain support Keep x86_64 as the default output while enabling the GCC and mingw-w64 32-bit multilib under lib32. Build 32-bit support archives, CRT libraries, and winpthreads for both the bootstrap and final sysroots so each compiler stage has a complete i686 runtime. Use pentium4 as the 32-bit architecture baseline. Add a GCC specs rule that defaults _WIN32_WINNT to 0x0501 only under -m32 and only when the caller has not supplied a value, preserving the existing x64 default and explicit overrides. Retain the x86_64-w64-mingw32-prefixed tools and add a separate build step for an i686-w64-mingw32 interface. Compiler drivers inject -m32. Target-sensitive binutils select their 32-bit modes explicitly: as uses --32, ld uses -m i386pe, dlltool uses -m i386 with --as-flags=--32, and windres uses --target=pe-i386. Input-driven inspection and archive tools forward without a target override. These forwarding executables provide both prefixed interfaces without duplicating a second binutils installation. They deliberately remain selectors for the underlying x86_64-configured multilib compiler rather than spoofing its configured target identity. Direct, Autoconf, CMake, and Libtool probes using the i686-prefixed interface all produced PE-i386 output. --- Dockerfile | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index caaf9fd..4604f71 100644 --- a/Dockerfile +++ b/Dockerfile @@ -253,6 +253,8 @@ RUN cat $PREFIX/src/gcc-*.patch | patch -d/dl/gcc -p1 \ && /dl/gcc/configure \ --prefix=/bootstrap \ --with-sysroot=/bootstrap \ + --with-arch-32=pentium4 \ + "--with-specs=%{m32:%{!D_WIN32_WINNT*:-D_WIN32_WINNT=0x0501}}" \ --target=$ARCH \ --enable-static \ --disable-shared \ @@ -266,7 +268,6 @@ RUN cat $PREFIX/src/gcc-*.patch | patch -d/dl/gcc -p1 \ --disable-dependency-tracking \ --disable-nls \ --disable-lto \ - --disable-multilib \ CFLAGS_FOR_TARGET="-O2" \ CXXFLAGS_FOR_TARGET="-O2" \ LDFLAGS_FOR_TARGET="-s" \ @@ -279,13 +280,19 @@ RUN cat $PREFIX/src/gcc-*.patch | patch -d/dl/gcc -p1 \ ENV PATH="/bootstrap/bin:${PATH}" COPY src/libmemory.c src/libchkstk.S $PREFIX/src/ -RUN mkdir -p $PREFIX/lib \ +RUN mkdir -p $PREFIX/lib $PREFIX/lib32 /bootstrap/lib32 \ && CC=$ARCH-gcc AR=$ARCH-ar DESTDIR=$PREFIX/lib/ \ sh $PREFIX/src/libmemory.c \ && ln $PREFIX/lib/libmemory.a /bootstrap/lib/ \ && CC=$ARCH-gcc AR=$ARCH-ar DESTDIR=$PREFIX/lib/ \ sh $PREFIX/src/libchkstk.S \ - && ln $PREFIX/lib/libchkstk.a /bootstrap/lib/ + && ln $PREFIX/lib/libchkstk.a /bootstrap/lib/ \ + && CC="$ARCH-gcc -m32" AR=$ARCH-ar DESTDIR=$PREFIX/lib32/ \ + sh $PREFIX/src/libmemory.c \ + && ln $PREFIX/lib32/libmemory.a /bootstrap/lib32/ \ + && CC="$ARCH-gcc -m32" AR=$ARCH-ar DESTDIR=$PREFIX/lib32/ \ + sh $PREFIX/src/libchkstk.S \ + && ln $PREFIX/lib32/libchkstk.a /bootstrap/lib32/ WORKDIR /x-mingw-crt RUN /dl/mingw/mingw-w64-crt/configure \ @@ -294,7 +301,7 @@ RUN /dl/mingw/mingw-w64-crt/configure \ --host=$ARCH \ --with-default-msvcrt=msvcrt-os \ --disable-dependency-tracking \ - --disable-lib32 \ + --enable-lib32 \ --enable-lib64 \ CFLAGS="-O2" \ LDFLAGS="-s" \ @@ -313,6 +320,20 @@ RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ && make -j$(nproc) \ && make install +WORKDIR /x-winpthreads32 +RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ + --prefix=/bootstrap \ + --libdir=/bootstrap/lib32 \ + --with-sysroot=/bootstrap \ + --host=$ARCH \ + --enable-static \ + --disable-shared \ + CC="$ARCH-gcc -m32" \ + CFLAGS="-O2" \ + LDFLAGS="-s" \ + && make -j$(nproc) \ + && make install + WORKDIR /x-gcc RUN make -j$(nproc) \ && make install @@ -398,7 +419,7 @@ RUN /dl/mingw/mingw-w64-crt/configure \ --host=$ARCH \ --with-default-msvcrt=msvcrt-os \ --disable-dependency-tracking \ - --disable-lib32 \ + --enable-lib32 \ --enable-lib64 \ CFLAGS="-O2" \ LDFLAGS="-s" \ @@ -409,7 +430,11 @@ COPY src/threads.c $PREFIX/src/ COPY src/threads.h $PREFIX/include/ RUN $ARCH-gcc -c -Oz -I$PREFIX/include/ \ -ffunction-sections -Wa,--no-pad-sections $PREFIX/src/threads.c \ - && $ARCH-ar r $PREFIX/lib/libmingwex.a threads.o + && $ARCH-ar r $PREFIX/lib/libmingwex.a threads.o \ + && $ARCH-gcc -m32 -c -Oz -I$PREFIX/include/ \ + -ffunction-sections -Wa,--no-pad-sections \ + -o threads32.o $PREFIX/src/threads.c \ + && $ARCH-ar r $PREFIX/lib32/libmingwex.a threads32.o WORKDIR /winpthreads RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ @@ -423,6 +448,20 @@ RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ && make -j$(nproc) \ && make install +WORKDIR /winpthreads32 +RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ + --prefix=$PREFIX \ + --libdir=$PREFIX/lib32 \ + --with-sysroot=$PREFIX \ + --host=$ARCH \ + --enable-static \ + --disable-shared \ + CC="$ARCH-gcc -m32" \ + CFLAGS="-O2" \ + LDFLAGS="-s" \ + && make -j$(nproc) \ + && make install + WORKDIR /gcc COPY src/crossgcc-*.patch $PREFIX/src/ RUN cat $PREFIX/src/crossgcc-*.patch | patch -d/dl/gcc -p1 \ @@ -430,6 +469,8 @@ RUN cat $PREFIX/src/crossgcc-*.patch | patch -d/dl/gcc -p1 \ --prefix=$PREFIX \ --with-sysroot=$PREFIX \ --with-native-system-header-dir=/include \ + --with-arch-32=pentium4 \ + "--with-specs=%{m32:%{!D_WIN32_WINNT*:-D_WIN32_WINNT=0x0501}}" \ --target=$ARCH \ --host=$ARCH \ --enable-static \ @@ -446,7 +487,6 @@ RUN cat $PREFIX/src/crossgcc-*.patch | patch -d/dl/gcc -p1 \ --disable-libstdcxx-verbose \ --disable-dependency-tracking \ --disable-lto \ - --disable-multilib \ --disable-nls \ --disable-win32-registry \ --enable-mingw-wildcard \ @@ -485,6 +525,46 @@ RUN $ARCH-gcc -DEXE=gcc.exe -DCMD=cc \ -Wl,--gc-sections -s -nostdlib \ -o $PREFIX/bin/$ARCH-{}.exe $PREFIX/src/alias.c -lkernel32 +# Create i686 tool aliases +RUN printf '%s\n' addr2line ar c++filt gcc-ar gcc-nm gcc-ranlib gcov \ + gcov-dump gcov-tool gendef nm objcopy objdump ranlib size strings \ + strip uuidgen widl windmc \ + | xargs -I{} -P$(nproc) \ + $ARCH-gcc -DEXE={}.exe -DCMD=i686-w64-mingw32-{} \ + -Oz -fno-asynchronous-unwind-tables \ + -Wl,--gc-sections -s -nostdlib \ + -o $PREFIX/bin/i686-w64-mingw32-{}.exe \ + $PREFIX/src/alias.c -lkernel32 \ + && printf '%s\n' cpp gcc g++ gfortran \ + | xargs -I{} -P$(nproc) \ + $ARCH-gcc -DEXE={}.exe -DCMD="i686-w64-mingw32-{} -m32" \ + -Oz -fno-asynchronous-unwind-tables \ + -Wl,--gc-sections -s -nostdlib \ + -o $PREFIX/bin/i686-w64-mingw32-{}.exe \ + $PREFIX/src/alias.c -lkernel32 \ + && $ARCH-gcc -DEXE=g++.exe -DCMD="i686-w64-mingw32-c++ -m32" \ + -Oz -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ + -o $PREFIX/bin/i686-w64-mingw32-c++.exe \ + $PREFIX/src/alias.c -lkernel32 \ + && $ARCH-gcc -DEXE=as.exe -DCMD="i686-w64-mingw32-as --32" \ + -Oz -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ + -o $PREFIX/bin/i686-w64-mingw32-as.exe \ + $PREFIX/src/alias.c -lkernel32 \ + && $ARCH-gcc -DEXE=ld.exe -DCMD="i686-w64-mingw32-ld -m i386pe" \ + -Oz -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ + -o $PREFIX/bin/i686-w64-mingw32-ld.exe \ + $PREFIX/src/alias.c -lkernel32 \ + && $ARCH-gcc -DEXE=dlltool.exe \ + -DCMD="i686-w64-mingw32-dlltool -m i386 --as-flags=--32" \ + -Oz -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ + -o $PREFIX/bin/i686-w64-mingw32-dlltool.exe \ + $PREFIX/src/alias.c -lkernel32 \ + && $ARCH-gcc -DEXE=windres.exe \ + -DCMD="i686-w64-mingw32-windres --target=pe-i386" \ + -Oz -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ + -o $PREFIX/bin/i686-w64-mingw32-windres.exe \ + $PREFIX/src/alias.c -lkernel32 + # Build some extra development tools FROM cross AS build-gendef From d9666fbbb3a7089725bad024ab17e2565b3ebcac Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Sun, 9 Aug 2026 18:56:42 -0500 Subject: [PATCH 02/11] Default x86 Windows target version in headers --- Dockerfile | 2 -- src/mingw-default-win32-winnt.patch | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 src/mingw-default-win32-winnt.patch diff --git a/Dockerfile b/Dockerfile index 4604f71..e9cbc9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -254,7 +254,6 @@ RUN cat $PREFIX/src/gcc-*.patch | patch -d/dl/gcc -p1 \ --prefix=/bootstrap \ --with-sysroot=/bootstrap \ --with-arch-32=pentium4 \ - "--with-specs=%{m32:%{!D_WIN32_WINNT*:-D_WIN32_WINNT=0x0501}}" \ --target=$ARCH \ --enable-static \ --disable-shared \ @@ -470,7 +469,6 @@ RUN cat $PREFIX/src/crossgcc-*.patch | patch -d/dl/gcc -p1 \ --with-sysroot=$PREFIX \ --with-native-system-header-dir=/include \ --with-arch-32=pentium4 \ - "--with-specs=%{m32:%{!D_WIN32_WINNT*:-D_WIN32_WINNT=0x0501}}" \ --target=$ARCH \ --host=$ARCH \ --enable-static \ diff --git a/src/mingw-default-win32-winnt.patch b/src/mingw-default-win32-winnt.patch new file mode 100644 index 0000000..eb75943 --- /dev/null +++ b/src/mingw-default-win32-winnt.patch @@ -0,0 +1,19 @@ +headers: default 32-bit x86 to Windows XP + +The x86_64 multilib toolchain shares one header tree between its 64-bit +and 32-bit targets. Keep the configured mingw-w64 default for x86_64 and +other architectures, but preserve w64devkit's Windows XP default when +the compiler targets i686. An explicit user definition still takes +precedence through the existing outer guard. + +--- a/mingw-w64-headers/crt/_mingw.h.in ++++ b/mingw-w64-headers/crt/_mingw.h.in +@@ -255,3 +255,7 @@ + #ifndef _WIN32_WINNT +-#define _WIN32_WINNT @DEFAULT_WIN32_WINNT@ ++# if defined(__i386__) ++# define _WIN32_WINNT 0x0501 ++# else ++# define _WIN32_WINNT @DEFAULT_WIN32_WINNT@ ++# endif + #endif From 5a4fe4964935c13b93497ea5fe9939c220b2f2e8 Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Sat, 29 Aug 2026 01:02:33 -0500 Subject: [PATCH 03/11] Fix i686 multilib tool aliases --- Dockerfile | 7 ++++++- src/crossgcc-i686-dumpmachine.patch | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/crossgcc-i686-dumpmachine.patch diff --git a/Dockerfile b/Dockerfile index e9cbc9a..cb18a17 100644 --- a/Dockerfile +++ b/Dockerfile @@ -526,7 +526,7 @@ RUN $ARCH-gcc -DEXE=gcc.exe -DCMD=cc \ # Create i686 tool aliases RUN printf '%s\n' addr2line ar c++filt gcc-ar gcc-nm gcc-ranlib gcov \ gcov-dump gcov-tool gendef nm objcopy objdump ranlib size strings \ - strip uuidgen widl windmc \ + strip uuidgen windmc \ | xargs -I{} -P$(nproc) \ $ARCH-gcc -DEXE={}.exe -DCMD=i686-w64-mingw32-{} \ -Oz -fno-asynchronous-unwind-tables \ @@ -557,6 +557,11 @@ RUN printf '%s\n' addr2line ar c++filt gcc-ar gcc-nm gcc-ranlib gcov \ -Oz -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ -o $PREFIX/bin/i686-w64-mingw32-dlltool.exe \ $PREFIX/src/alias.c -lkernel32 \ + && $ARCH-gcc -DEXE=widl.exe \ + -DCMD="i686-w64-mingw32-widl --win32" \ + -Oz -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ + -o $PREFIX/bin/i686-w64-mingw32-widl.exe \ + $PREFIX/src/alias.c -lkernel32 \ && $ARCH-gcc -DEXE=windres.exe \ -DCMD="i686-w64-mingw32-windres --target=pe-i386" \ -Oz -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ diff --git a/src/crossgcc-i686-dumpmachine.patch b/src/crossgcc-i686-dumpmachine.patch new file mode 100644 index 0000000..3669a7e --- /dev/null +++ b/src/crossgcc-i686-dumpmachine.patch @@ -0,0 +1,23 @@ +Report the emulated i686 target from i686 driver aliases + +The multilib compiler is configured for x86_64, so -m32 does not change +-dumpmachine. The i686 aliases present themselves as target-prefixed +compilers, and target-detecting build systems expect that prefix and +-dumpmachine to agree. Preserve normal multilib behavior for every other +invocation name. +--- a/gcc/gcc.cc ++++ b/gcc/gcc.cc +@@ -4249,6 +4249,13 @@ driver_handle_option (struct gcc_options *opts, + exit (0); + + case OPT_dumpmachine: ++#ifdef __MINGW32__ ++ if (startswith (progname, "i686-w64-mingw32-")) ++ { ++ printf ("i686-w64-mingw32\n"); ++ exit (0); ++ } ++#endif + printf ("%s\n", spec_machine); + exit (0); + From b4e8b659c594896c8610d79b84a0884a8f780149 Mon Sep 17 00:00:00 2001 From: Christopher Wellons Date: Sat, 29 Aug 2026 12:57:07 -0400 Subject: [PATCH 04/11] Remove dllwrap from the distribution It's been deprecated for 6 years and unmaintained for 20 years. --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index cb18a17..4676c02 100644 --- a/Dockerfile +++ b/Dockerfile @@ -351,7 +351,7 @@ RUN /dl/binutils/configure \ LDFLAGS="-s" \ && make MAKEINFO=true tooldir=$PREFIX -j$(nproc) \ && make MAKEINFO=true tooldir=$PREFIX install \ - && rm $PREFIX/bin/elfedit.exe $PREFIX/bin/readelf.exe + && rm $PREFIX/bin/dllwrap.exe $PREFIX/bin/elfedit.exe $PREFIX/bin/readelf.exe WORKDIR /gmp RUN /dl/gmp/configure \ @@ -513,7 +513,7 @@ RUN $ARCH-gcc -DEXE=gcc.exe -DCMD=cc \ && $ARCH-gcc -DEXE=gcc.exe -DCMD="cc -ansi" \ -Oz -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ -o $PREFIX/bin/c89.exe $PREFIX/src/alias.c -lkernel32 \ - && printf '%s\n' addr2line ar as c++filt cpp dlltool dllwrap g++ \ + && printf '%s\n' addr2line ar as c++filt cpp dlltool g++ \ gcc gcc-ar gcc-nm gcc-ranlib gcov gcov-dump gcov-tool gendef gfortran \ ld nm objcopy objdump ranlib size strings strip uuidgen widl \ windmc windres \ From 54a49eee4aeb516ee8c5781fa0cc7948eed7d6a1 Mon Sep 17 00:00:00 2001 From: Christopher Wellons Date: Sat, 29 Aug 2026 13:00:24 -0400 Subject: [PATCH 05/11] fixup! Add x86 multilib toolchain support --- Dockerfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4676c02..1170796 100644 --- a/Dockerfile +++ b/Dockerfile @@ -540,10 +540,6 @@ RUN printf '%s\n' addr2line ar c++filt gcc-ar gcc-nm gcc-ranlib gcov \ -Wl,--gc-sections -s -nostdlib \ -o $PREFIX/bin/i686-w64-mingw32-{}.exe \ $PREFIX/src/alias.c -lkernel32 \ - && $ARCH-gcc -DEXE=g++.exe -DCMD="i686-w64-mingw32-c++ -m32" \ - -Oz -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ - -o $PREFIX/bin/i686-w64-mingw32-c++.exe \ - $PREFIX/src/alias.c -lkernel32 \ && $ARCH-gcc -DEXE=as.exe -DCMD="i686-w64-mingw32-as --32" \ -Oz -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ -o $PREFIX/bin/i686-w64-mingw32-as.exe \ From e8056722e1122439a46ad61457eaedc93dbc2b2b Mon Sep 17 00:00:00 2001 From: Christopher Wellons Date: Sat, 29 Aug 2026 14:10:55 -0400 Subject: [PATCH 06/11] Replace the variant patch with Dockerfile build args Hoist every variant-sensitive value into an ARG at the top of the cross stage, with defaults producing the x64 kit, and gate the multilib-only sidecar builds on MULTILIB. The x86 variant becomes a set of NAME=value overrides in src/variant-x86.args, which multibuild.sh turns into --build-arg options. A plain "docker build" continues to work untouched, downloads stay shared between variants, and the patch mechanism remains available as a fallback for a future variant needing structural changes. One hazard of this approach: ARGs leak into the environment of every subsequent RUN in the stage, and configure scripts read arbitrary environment variables. mingw-w64-crt decides whether to build the Win64 runtime by testing whether a shell variable named LIB64 is merely set, so an ARG of that name forced lib64 on past an explicit --disable-lib64. Hence CRT_LIB64. Keep ARG names clear of names configure might consult. Co-Authored-By: Claude Fable 5 --- Dockerfile | 133 +++++++++++++++++++++++++++--------------- multibuild.sh | 6 +- src/variant-x86.args | 10 ++++ src/variant-x86.patch | 61 ------------------- 4 files changed, 102 insertions(+), 108 deletions(-) create mode 100644 src/variant-x86.args delete mode 100644 src/variant-x86.patch diff --git a/Dockerfile b/Dockerfile index 1170796..6a743ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -208,8 +208,29 @@ RUN mkdir nsis \ # Build cross-compiler FROM dl-cross AS cross + +# Variant configuration. The defaults produce the x64 kit, and a variant +# is a coherent set of overrides (see src/variant-x86.args). Stages +# before this point are shared between variants. ARG ARCH=x86_64-w64-mingw32 -ENV ARCH=$ARCH +ARG MULTILIB=--enable-multilib +ARG ARCH_FLAGS=--with-arch-32=pentium4 +# Not named "LIB64": mingw-w64-crt's configure tests whether a shell +# variable LIB64 (or LIB32) is set, and ARGs leak into the environment +# of every RUN, which would force the Win64 runtime on regardless of +# the --{enable,disable}-lib64 flag. +ARG CRT_LIB64=--enable-lib64 +ARG WINNT_FLAGS= +ARG MANIFEST_FLAGS= +ARG BUSYBOX_CONFIG=mingw64u_defconfig +ARG ZSTD_FLAGS= +ARG CMAKE_WINNT= +ARG NSIS_ARCH=amd64 +ENV ARCH=$ARCH \ + BUSYBOX_CONFIG=$BUSYBOX_CONFIG \ + ZSTD_FLAGS=$ZSTD_FLAGS \ + CMAKE_WINNT=$CMAKE_WINNT \ + NSIS_ARCH=$NSIS_ARCH WORKDIR /dl/binutils COPY src/binutils-*.patch $PREFIX/src/ @@ -241,6 +262,7 @@ RUN printf '#include \n#if __has_include_next()\n#include_n --prefix=/bootstrap \ --host=$ARCH \ --with-default-msvcrt=msvcrt-os \ + $WINNT_FLAGS \ && make -j$(nproc) \ && make install @@ -253,7 +275,8 @@ RUN cat $PREFIX/src/gcc-*.patch | patch -d/dl/gcc -p1 \ && /dl/gcc/configure \ --prefix=/bootstrap \ --with-sysroot=/bootstrap \ - --with-arch-32=pentium4 \ + $ARCH_FLAGS \ + $MULTILIB \ --target=$ARCH \ --enable-static \ --disable-shared \ @@ -279,19 +302,22 @@ RUN cat $PREFIX/src/gcc-*.patch | patch -d/dl/gcc -p1 \ ENV PATH="/bootstrap/bin:${PATH}" COPY src/libmemory.c src/libchkstk.S $PREFIX/src/ -RUN mkdir -p $PREFIX/lib $PREFIX/lib32 /bootstrap/lib32 \ +RUN mkdir -p $PREFIX/lib \ && CC=$ARCH-gcc AR=$ARCH-ar DESTDIR=$PREFIX/lib/ \ sh $PREFIX/src/libmemory.c \ && ln $PREFIX/lib/libmemory.a /bootstrap/lib/ \ && CC=$ARCH-gcc AR=$ARCH-ar DESTDIR=$PREFIX/lib/ \ sh $PREFIX/src/libchkstk.S \ && ln $PREFIX/lib/libchkstk.a /bootstrap/lib/ \ - && CC="$ARCH-gcc -m32" AR=$ARCH-ar DESTDIR=$PREFIX/lib32/ \ - sh $PREFIX/src/libmemory.c \ - && ln $PREFIX/lib32/libmemory.a /bootstrap/lib32/ \ - && CC="$ARCH-gcc -m32" AR=$ARCH-ar DESTDIR=$PREFIX/lib32/ \ - sh $PREFIX/src/libchkstk.S \ - && ln $PREFIX/lib32/libchkstk.a /bootstrap/lib32/ + && if [ "$MULTILIB" = --enable-multilib ]; then \ + mkdir -p $PREFIX/lib32 /bootstrap/lib32 \ + && CC="$ARCH-gcc -m32" AR=$ARCH-ar DESTDIR=$PREFIX/lib32/ \ + sh $PREFIX/src/libmemory.c \ + && ln $PREFIX/lib32/libmemory.a /bootstrap/lib32/ \ + && CC="$ARCH-gcc -m32" AR=$ARCH-ar DESTDIR=$PREFIX/lib32/ \ + sh $PREFIX/src/libchkstk.S \ + && ln $PREFIX/lib32/libchkstk.a /bootstrap/lib32/ ; \ + fi WORKDIR /x-mingw-crt RUN /dl/mingw/mingw-w64-crt/configure \ @@ -301,7 +327,7 @@ RUN /dl/mingw/mingw-w64-crt/configure \ --with-default-msvcrt=msvcrt-os \ --disable-dependency-tracking \ --enable-lib32 \ - --enable-lib64 \ + $CRT_LIB64 \ CFLAGS="-O2" \ LDFLAGS="-s" \ && make -j$(nproc) \ @@ -320,18 +346,20 @@ RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ && make install WORKDIR /x-winpthreads32 -RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ - --prefix=/bootstrap \ - --libdir=/bootstrap/lib32 \ - --with-sysroot=/bootstrap \ - --host=$ARCH \ - --enable-static \ - --disable-shared \ - CC="$ARCH-gcc -m32" \ - CFLAGS="-O2" \ - LDFLAGS="-s" \ - && make -j$(nproc) \ - && make install +RUN if [ "$MULTILIB" = --enable-multilib ]; then \ + /dl/mingw/mingw-w64-libraries/winpthreads/configure \ + --prefix=/bootstrap \ + --libdir=/bootstrap/lib32 \ + --with-sysroot=/bootstrap \ + --host=$ARCH \ + --enable-static \ + --disable-shared \ + CC="$ARCH-gcc -m32" \ + CFLAGS="-O2" \ + LDFLAGS="-s" \ + && make -j$(nproc) \ + && make install ; \ + fi WORKDIR /x-gcc RUN make -j$(nproc) \ @@ -408,6 +436,7 @@ RUN /dl/mingw/mingw-w64-headers/configure \ --host=$ARCH \ --enable-idl \ --with-default-msvcrt=msvcrt-os \ + $WINNT_FLAGS \ && make -j$(nproc) \ && make install @@ -419,7 +448,7 @@ RUN /dl/mingw/mingw-w64-crt/configure \ --with-default-msvcrt=msvcrt-os \ --disable-dependency-tracking \ --enable-lib32 \ - --enable-lib64 \ + $CRT_LIB64 \ CFLAGS="-O2" \ LDFLAGS="-s" \ && make -j$(nproc) \ @@ -430,10 +459,12 @@ COPY src/threads.h $PREFIX/include/ RUN $ARCH-gcc -c -Oz -I$PREFIX/include/ \ -ffunction-sections -Wa,--no-pad-sections $PREFIX/src/threads.c \ && $ARCH-ar r $PREFIX/lib/libmingwex.a threads.o \ - && $ARCH-gcc -m32 -c -Oz -I$PREFIX/include/ \ - -ffunction-sections -Wa,--no-pad-sections \ - -o threads32.o $PREFIX/src/threads.c \ - && $ARCH-ar r $PREFIX/lib32/libmingwex.a threads32.o + && if [ "$MULTILIB" = --enable-multilib ]; then \ + $ARCH-gcc -m32 -c -Oz -I$PREFIX/include/ \ + -ffunction-sections -Wa,--no-pad-sections \ + -o threads32.o $PREFIX/src/threads.c \ + && $ARCH-ar r $PREFIX/lib32/libmingwex.a threads32.o ; \ + fi WORKDIR /winpthreads RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ @@ -448,18 +479,20 @@ RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ && make install WORKDIR /winpthreads32 -RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ - --prefix=$PREFIX \ - --libdir=$PREFIX/lib32 \ - --with-sysroot=$PREFIX \ - --host=$ARCH \ - --enable-static \ - --disable-shared \ - CC="$ARCH-gcc -m32" \ - CFLAGS="-O2" \ - LDFLAGS="-s" \ - && make -j$(nproc) \ - && make install +RUN if [ "$MULTILIB" = --enable-multilib ]; then \ + /dl/mingw/mingw-w64-libraries/winpthreads/configure \ + --prefix=$PREFIX \ + --libdir=$PREFIX/lib32 \ + --with-sysroot=$PREFIX \ + --host=$ARCH \ + --enable-static \ + --disable-shared \ + CC="$ARCH-gcc -m32" \ + CFLAGS="-O2" \ + LDFLAGS="-s" \ + && make -j$(nproc) \ + && make install ; \ + fi WORKDIR /gcc COPY src/crossgcc-*.patch $PREFIX/src/ @@ -468,7 +501,8 @@ RUN cat $PREFIX/src/crossgcc-*.patch | patch -d/dl/gcc -p1 \ --prefix=$PREFIX \ --with-sysroot=$PREFIX \ --with-native-system-header-dir=/include \ - --with-arch-32=pentium4 \ + $ARCH_FLAGS \ + $MULTILIB \ --target=$ARCH \ --host=$ARCH \ --enable-static \ @@ -487,6 +521,7 @@ RUN cat $PREFIX/src/crossgcc-*.patch | patch -d/dl/gcc -p1 \ --disable-lto \ --disable-nls \ --disable-win32-registry \ + $MANIFEST_FLAGS \ --enable-mingw-wildcard \ CFLAGS_FOR_TARGET="-O2" \ CXXFLAGS_FOR_TARGET="-O2" \ @@ -524,7 +559,8 @@ RUN $ARCH-gcc -DEXE=gcc.exe -DCMD=cc \ -o $PREFIX/bin/$ARCH-{}.exe $PREFIX/src/alias.c -lkernel32 # Create i686 tool aliases -RUN printf '%s\n' addr2line ar c++filt gcc-ar gcc-nm gcc-ranlib gcov \ +RUN if [ "$MULTILIB" = --enable-multilib ]; then \ + printf '%s\n' addr2line ar c++filt gcc-ar gcc-nm gcc-ranlib gcov \ gcov-dump gcov-tool gendef nm objcopy objdump ranlib size strings \ strip uuidgen windmc \ | xargs -I{} -P$(nproc) \ @@ -562,7 +598,8 @@ RUN printf '%s\n' addr2line ar c++filt gcc-ar gcc-nm gcc-ranlib gcov \ -DCMD="i686-w64-mingw32-windres --target=pe-i386" \ -Oz -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ -o $PREFIX/bin/i686-w64-mingw32-windres.exe \ - $PREFIX/src/alias.c -lkernel32 + $PREFIX/src/alias.c -lkernel32 ; \ + fi # Build some extra development tools @@ -677,7 +714,7 @@ COPY --from=dl-busybox /dl/ /dl/ WORKDIR /dl/busybox COPY src/busybox-* $PREFIX/src/ RUN cat $PREFIX/src/busybox-*.patch | patch -p1 \ - && make mingw64u_defconfig \ + && make $BUSYBOX_CONFIG \ && sed -ri 's/^(CONFIG_AR)=y/\1=n/' .config \ && sed -ri 's/^(CONFIG_ASCII)=y/\1=n/' .config \ && sed -ri -e 's/^(CONFIG_BASH_IS_ASH)=y/\1=n/' \ @@ -772,7 +809,7 @@ RUN make -j$(nproc) CC=$ARCH-gcc AR=$ARCH-ar CFLAGS="-O2" libzstd.a \ WORKDIR /dl/zstd RUN make -j$(nproc) -C programs zstd \ - CC=$ARCH-gcc CFLAGS="-O2" LDFLAGS="-s" EXT=.exe \ + CC=$ARCH-gcc CFLAGS="-O2" LDFLAGS="-s" EXT=.exe $ZSTD_FLAGS \ && mkdir -p /out/bin \ && cp programs/zstd.exe /out/bin/ \ && $ARCH-gcc -DEXE=zstd.exe -DCMD=unzstd \ @@ -867,7 +904,11 @@ COPY --from=build-pdcurses /deps/include/curses.h /deps/include/ WORKDIR /cmake COPY src/cmake-*.patch $PREFIX/src/ RUN cat $PREFIX/src/cmake-*.patch | patch -d/dl/cmake -p1 \ - && cmake -DCMAKE_BUILD_TYPE=Release \ + && if [ -n "$CMAKE_WINNT" ]; then \ + set -- -DCMAKE_C_FLAGS="-O2 -D_WIN32_WINNT=$CMAKE_WINNT" \ + -DCMAKE_CXX_FLAGS="-O2 -D_WIN32_WINNT=$CMAKE_WINNT" ; \ + fi \ + && cmake "$@" -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_SYSTEM_NAME=Windows \ -DCMAKE_C_COMPILER=$ARCH-gcc \ -DCMAKE_CXX_COMPILER=$ARCH-g++ \ @@ -932,7 +973,7 @@ RUN sed -i 's/\r$//' Source/build.cpp \ && cat $PREFIX/src/nsis-*.patch | patch -p1 \ && scons -j$(nproc) \ XGCC_W32_PREFIX=$ARCH- \ - TARGET_ARCH=amd64 \ + TARGET_ARCH=$NSIS_ARCH \ PREFIX=$PREFIX \ PREFIX_BIN=$PREFIX/share/nsis/bin \ PREFIX_DATA=$PREFIX/share/nsis \ diff --git a/multibuild.sh b/multibuild.sh index 92ab732..8232859 100755 --- a/multibuild.sh +++ b/multibuild.sh @@ -53,7 +53,11 @@ cleanup() { trap cleanup EXIT for variant in $arch; do - if [ -e "src/variant-$variant.patch" ]; then + if [ -e "src/variant-$variant.args" ]; then + $dryrun docker build \ + $(sed 's/^/--build-arg /' "src/variant-$variant.args") \ + -t $target . + elif [ -e "src/variant-$variant.patch" ]; then tmp=$(mktemp -d) $dryrun cp Dockerfile "$tmp/" $dryrun patch "$tmp/Dockerfile" "src/variant-$variant.patch" diff --git a/src/variant-x86.args b/src/variant-x86.args new file mode 100644 index 0000000..06ad08c --- /dev/null +++ b/src/variant-x86.args @@ -0,0 +1,10 @@ +ARCH=i686-w64-mingw32 +MULTILIB=--disable-multilib +ARCH_FLAGS=--with-arch=pentium4 +CRT_LIB64=--disable-lib64 +WINNT_FLAGS=--with-default-win32-winnt=0x0501 +MANIFEST_FLAGS=--disable-win32-utf8-manifest +BUSYBOX_CONFIG=mingw32w_defconfig +ZSTD_FLAGS=HAVE_THREAD=0 +CMAKE_WINNT=0x0601 +NSIS_ARCH=x86 diff --git a/src/variant-x86.patch b/src/variant-x86.patch deleted file mode 100644 index 1621c7f..0000000 --- a/src/variant-x86.patch +++ /dev/null @@ -1,61 +0,0 @@ ---- a/Dockerfile -+++ b/Dockerfile -@@ -229,3 +229,3 @@ - FROM dl-cross AS cross --ARG ARCH=x86_64-w64-mingw32 -+ARG ARCH=i686-w64-mingw32 - ENV ARCH=$ARCH -@@ -260,2 +260,3 @@ - --with-default-msvcrt=msvcrt-os \ -+ --with-default-win32-winnt=0x0501 \ - && make -j$(nproc) \ -@@ -272,2 +273,3 @@ - --with-sysroot=/bootstrap \ -+ --with-arch=pentium4 \ - --target=$ARCH \ -@@ -313,4 +315,4 @@ - --disable-dependency-tracking \ -- --disable-lib32 \ -- --enable-lib64 \ -+ --enable-lib32 \ -+ --disable-lib64 \ - CFLAGS="-O2" \ -@@ -399,2 +401,3 @@ - --with-default-msvcrt=msvcrt-os \ -+ --with-default-win32-winnt=0x0501 \ - && make -j$(nproc) \ -@@ -409,4 +412,4 @@ - --disable-dependency-tracking \ -- --disable-lib32 \ -- --enable-lib64 \ -+ --enable-lib32 \ -+ --disable-lib64 \ - CFLAGS="-O2" \ -@@ -437,2 +440,3 @@ - --with-native-system-header-dir=/include \ -+ --with-arch=pentium4 \ - --target=$ARCH \ -@@ -456,2 +460,3 @@ - --disable-win32-registry \ -+ --disable-win32-utf8-manifest \ - --enable-mingw-wildcard \ -@@ -605,3 +610,3 @@ - RUN cat $PREFIX/src/busybox-*.patch | patch -p1 \ -- && make mingw64u_defconfig \ -+ && make mingw32w_defconfig \ - && sed -ri 's/^(CONFIG_AR)=y/\1=n/' .config \ -@@ -699,3 +704,3 @@ - RUN make -j$(nproc) -C programs zstd \ -- CC=$ARCH-gcc CFLAGS="-O2" LDFLAGS="-s" EXT=.exe \ -+ CC=$ARCH-gcc CFLAGS="-O2" LDFLAGS="-s" EXT=.exe HAVE_THREAD=0 \ - && mkdir -p /out/bin \ -@@ -798,2 +803,4 @@ - -DCMAKE_EXE_LINKER_FLAGS="-s" \ -+ -DCMAKE_C_FLAGS="-O2 -D_WIN32_WINNT=0x0601" \ -+ -DCMAKE_CXX_FLAGS="-O2 -D_WIN32_WINNT=0x0601" \ - -DCMAKE_INSTALL_PREFIX=$PREFIX \ -@@ -840,3 +847,3 @@ - XGCC_W32_PREFIX=$ARCH- \ -- TARGET_ARCH=amd64 \ -+ TARGET_ARCH=x86 \ - PREFIX=$PREFIX \ From 7a2cb7cbb258f598e5f5c3764235545d5c85bd5f Mon Sep 17 00:00:00 2001 From: Christopher Wellons Date: Sat, 29 Aug 2026 14:17:11 -0400 Subject: [PATCH 07/11] Use x86 build args instead of the patch in CI The variant patch no longer exists, so both x86 builds read src/variant-x86.args into a step output, which build-push-action accepts verbatim as its newline-delimited build-args input. The args file remains the single definition of the variant. Co-Authored-By: Claude Fable 5 --- .github/workflows/build.yml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3235c94..b51f990 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -97,8 +97,14 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 - - name: Apply x86 patch - run: patch -p1 -i src/variant-x86.patch + - name: Load x86 build args + id: variant + run: | + { + echo 'args<> "$GITHUB_OUTPUT" - name: Generate archive name and version string id: filename @@ -112,6 +118,7 @@ jobs: uses: docker/build-push-action@v7 with: context: . + build-args: ${{ steps.variant.outputs.args }} tags: w64devkit:${{ env.ARCH }} load: true cache-from: type=gha,scope=w64devkit-${{ env.ARCH }} @@ -175,13 +182,20 @@ jobs: > w64devkit-x64-${{ steps.filename.outputs.version }}.7z.exe ls -lh w64devkit-x64-${{ steps.filename.outputs.version }}.7z.exe - - name: Apply x86 patch - run: patch -p1 -i src/variant-x86.patch + - name: Load x86 build args + id: variant + run: | + { + echo 'args<> "$GITHUB_OUTPUT" - name: Build signed image (x86) uses: docker/build-push-action@v7 with: context: . + build-args: ${{ steps.variant.outputs.args }} target: signed tags: w64devkit:x86-signed load: true From 4d229a3b256e49eea59a83fda84159a9e55db302 Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Sat, 29 Aug 2026 18:10:31 -0500 Subject: [PATCH 08/11] Replace variant arguments with build profiles Replace the loosely coordinated collection of x86 build arguments with a single VARIANT selector. Define x64, x86, and multilib configuration stages, then select the requested stage as the common cross-compiler base. This keeps each supported configuration closed and prevents callers from combining incompatible architecture settings. Make x64 the default standalone profile. It targets x86_64-w64-mingw32, disables GCC multilib support, builds only the 64-bit CRT, and omits the secondary 32-bit libraries and aliases. Keep the standalone x86 behavior in its own profile. It targets i686-w64-mingw32, retains the Pentium 4 default, enables only the 32-bit CRT, preserves the Windows XP header default and manifest behavior, selects the 32-bit BusyBox and NSIS configurations, disables zstd threading, and raises _WIN32_WINNT only while building CMake. CMake and its bundled curl require at least Windows Vista APIs, so the C and C++ flags continue to target Windows 7 without changing the XP-oriented default of the installed toolchain. Define multilib as an x86_64 compiler with GCC multilib enabled, both CRT library sets installed, and the existing i686 forwarding aliases. Use a dedicated EXTRA_32 setting for the secondary lib32 libraries, winpthreads builds, thread support object, and aliases instead of inferring that work from the spelling of a GCC configure option. Expose independent CRT_LIB32 and CRT_LIB64 settings so each profile selects exactly the runtime libraries it needs. Pass the profile's CMake C and C++ flags directly rather than building an optional argument list through shell positional parameters. Keep all other profile-specific values next to the selected base stage, including GCC architecture and manifest flags, BusyBox configuration, zstd options, and NSIS target architecture. Simplify multibuild.sh to pass only VARIANT to Docker. Add -m for the multilib flavor, make -a build all three profiles, and remove the old argument-file and Dockerfile-patch fallback paths. Update unsigned and signed CI builds to select x64 or x86 directly, remove the obsolete variant-x86.args bundle, and document the new build interface. Verify all three profiles with docker build --check and complete cross toolchain builds. Smoke-test x64 and x86 compilation, plus both the 64-bit compiler and i686 alias in the multilib profile. Also build the x64 and x86 CMake targets to exercise both the empty and Windows 7 CMake flag configurations. --- .github/workflows/build.yml | 24 ++-------- Dockerfile | 93 +++++++++++++++++++++++-------------- README.md | 8 ++++ multibuild.sh | 36 +++++--------- src/variant-x86.args | 10 ---- 5 files changed, 81 insertions(+), 90 deletions(-) delete mode 100644 src/variant-x86.args diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b51f990..6cddf41 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,6 +40,7 @@ jobs: uses: docker/build-push-action@v7 with: context: . + build-args: VARIANT=x64 tags: w64devkit:${{ env.ARCH }} load: true cache-from: type=gha,scope=w64devkit-${{ env.ARCH }} @@ -97,15 +98,6 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 - - name: Load x86 build args - id: variant - run: | - { - echo 'args<> "$GITHUB_OUTPUT" - - name: Generate archive name and version string id: filename run: | @@ -118,7 +110,7 @@ jobs: uses: docker/build-push-action@v7 with: context: . - build-args: ${{ steps.variant.outputs.args }} + build-args: VARIANT=x86 tags: w64devkit:${{ env.ARCH }} load: true cache-from: type=gha,scope=w64devkit-${{ env.ARCH }} @@ -166,6 +158,7 @@ jobs: uses: docker/build-push-action@v7 with: context: . + build-args: VARIANT=x64 target: signed tags: w64devkit:x64-signed load: true @@ -182,20 +175,11 @@ jobs: > w64devkit-x64-${{ steps.filename.outputs.version }}.7z.exe ls -lh w64devkit-x64-${{ steps.filename.outputs.version }}.7z.exe - - name: Load x86 build args - id: variant - run: | - { - echo 'args<> "$GITHUB_OUTPUT" - - name: Build signed image (x86) uses: docker/build-push-action@v7 with: context: . - build-args: ${{ steps.variant.outputs.args }} + build-args: VARIANT=x86 target: signed tags: w64devkit:x86-signed load: true diff --git a/Dockerfile b/Dockerfile index 6a743ca..61af5e9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,6 @@ ARG VERSION=2.9.1 \ PREFIX=/w64devkit +ARG VARIANT=x64 FROM debian:trixie-slim AS base ARG PREFIX @@ -207,30 +208,52 @@ RUN mkdir nsis \ # Build cross-compiler -FROM dl-cross AS cross - -# Variant configuration. The defaults produce the x64 kit, and a variant -# is a coherent set of overrides (see src/variant-x86.args). Stages -# before this point are shared between variants. -ARG ARCH=x86_64-w64-mingw32 -ARG MULTILIB=--enable-multilib -ARG ARCH_FLAGS=--with-arch-32=pentium4 -# Not named "LIB64": mingw-w64-crt's configure tests whether a shell -# variable LIB64 (or LIB32) is set, and ARGs leak into the environment -# of every RUN, which would force the Win64 runtime on regardless of -# the --{enable,disable}-lib64 flag. -ARG CRT_LIB64=--enable-lib64 -ARG WINNT_FLAGS= -ARG MANIFEST_FLAGS= -ARG BUSYBOX_CONFIG=mingw64u_defconfig -ARG ZSTD_FLAGS= -ARG CMAKE_WINNT= -ARG NSIS_ARCH=amd64 -ENV ARCH=$ARCH \ - BUSYBOX_CONFIG=$BUSYBOX_CONFIG \ - ZSTD_FLAGS=$ZSTD_FLAGS \ - CMAKE_WINNT=$CMAKE_WINNT \ - NSIS_ARCH=$NSIS_ARCH +FROM dl-cross AS variant-x64 +ENV ARCH=x86_64-w64-mingw32 \ + ARCH_FLAGS="" \ + MULTILIB=--disable-multilib \ + CRT_LIB32=--disable-lib32 \ + CRT_LIB64=--enable-lib64 \ + WINNT_FLAGS="" \ + MANIFEST_FLAGS="" \ + EXTRA_32=0 \ + BUSYBOX_CONFIG=mingw64u_defconfig \ + ZSTD_FLAGS="" \ + CMAKE_C_FLAGS="" \ + CMAKE_CXX_FLAGS="" \ + NSIS_ARCH=amd64 + +FROM dl-cross AS variant-x86 +ENV ARCH=i686-w64-mingw32 \ + ARCH_FLAGS=--with-arch=pentium4 \ + MULTILIB=--disable-multilib \ + CRT_LIB32=--enable-lib32 \ + CRT_LIB64=--disable-lib64 \ + WINNT_FLAGS=--with-default-win32-winnt=0x0501 \ + MANIFEST_FLAGS=--disable-win32-utf8-manifest \ + EXTRA_32=0 \ + BUSYBOX_CONFIG=mingw32w_defconfig \ + ZSTD_FLAGS=HAVE_THREAD=0 \ + CMAKE_C_FLAGS="-O2 -D_WIN32_WINNT=0x0601" \ + CMAKE_CXX_FLAGS="-O2 -D_WIN32_WINNT=0x0601" \ + NSIS_ARCH=x86 + +FROM dl-cross AS variant-multilib +ENV ARCH=x86_64-w64-mingw32 \ + ARCH_FLAGS=--with-arch-32=pentium4 \ + MULTILIB=--enable-multilib \ + CRT_LIB32=--enable-lib32 \ + CRT_LIB64=--enable-lib64 \ + WINNT_FLAGS="" \ + MANIFEST_FLAGS="" \ + EXTRA_32=1 \ + BUSYBOX_CONFIG=mingw64u_defconfig \ + ZSTD_FLAGS="" \ + CMAKE_C_FLAGS="" \ + CMAKE_CXX_FLAGS="" \ + NSIS_ARCH=amd64 + +FROM variant-${VARIANT} AS cross WORKDIR /dl/binutils COPY src/binutils-*.patch $PREFIX/src/ @@ -309,7 +332,7 @@ RUN mkdir -p $PREFIX/lib \ && CC=$ARCH-gcc AR=$ARCH-ar DESTDIR=$PREFIX/lib/ \ sh $PREFIX/src/libchkstk.S \ && ln $PREFIX/lib/libchkstk.a /bootstrap/lib/ \ - && if [ "$MULTILIB" = --enable-multilib ]; then \ + && if [ "$EXTRA_32" = 1 ]; then \ mkdir -p $PREFIX/lib32 /bootstrap/lib32 \ && CC="$ARCH-gcc -m32" AR=$ARCH-ar DESTDIR=$PREFIX/lib32/ \ sh $PREFIX/src/libmemory.c \ @@ -326,7 +349,7 @@ RUN /dl/mingw/mingw-w64-crt/configure \ --host=$ARCH \ --with-default-msvcrt=msvcrt-os \ --disable-dependency-tracking \ - --enable-lib32 \ + $CRT_LIB32 \ $CRT_LIB64 \ CFLAGS="-O2" \ LDFLAGS="-s" \ @@ -346,7 +369,7 @@ RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ && make install WORKDIR /x-winpthreads32 -RUN if [ "$MULTILIB" = --enable-multilib ]; then \ +RUN if [ "$EXTRA_32" = 1 ]; then \ /dl/mingw/mingw-w64-libraries/winpthreads/configure \ --prefix=/bootstrap \ --libdir=/bootstrap/lib32 \ @@ -447,7 +470,7 @@ RUN /dl/mingw/mingw-w64-crt/configure \ --host=$ARCH \ --with-default-msvcrt=msvcrt-os \ --disable-dependency-tracking \ - --enable-lib32 \ + $CRT_LIB32 \ $CRT_LIB64 \ CFLAGS="-O2" \ LDFLAGS="-s" \ @@ -459,7 +482,7 @@ COPY src/threads.h $PREFIX/include/ RUN $ARCH-gcc -c -Oz -I$PREFIX/include/ \ -ffunction-sections -Wa,--no-pad-sections $PREFIX/src/threads.c \ && $ARCH-ar r $PREFIX/lib/libmingwex.a threads.o \ - && if [ "$MULTILIB" = --enable-multilib ]; then \ + && if [ "$EXTRA_32" = 1 ]; then \ $ARCH-gcc -m32 -c -Oz -I$PREFIX/include/ \ -ffunction-sections -Wa,--no-pad-sections \ -o threads32.o $PREFIX/src/threads.c \ @@ -479,7 +502,7 @@ RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ && make install WORKDIR /winpthreads32 -RUN if [ "$MULTILIB" = --enable-multilib ]; then \ +RUN if [ "$EXTRA_32" = 1 ]; then \ /dl/mingw/mingw-w64-libraries/winpthreads/configure \ --prefix=$PREFIX \ --libdir=$PREFIX/lib32 \ @@ -559,7 +582,7 @@ RUN $ARCH-gcc -DEXE=gcc.exe -DCMD=cc \ -o $PREFIX/bin/$ARCH-{}.exe $PREFIX/src/alias.c -lkernel32 # Create i686 tool aliases -RUN if [ "$MULTILIB" = --enable-multilib ]; then \ +RUN if [ "$EXTRA_32" = 1 ]; then \ printf '%s\n' addr2line ar c++filt gcc-ar gcc-nm gcc-ranlib gcov \ gcov-dump gcov-tool gendef nm objcopy objdump ranlib size strings \ strip uuidgen windmc \ @@ -904,11 +927,9 @@ COPY --from=build-pdcurses /deps/include/curses.h /deps/include/ WORKDIR /cmake COPY src/cmake-*.patch $PREFIX/src/ RUN cat $PREFIX/src/cmake-*.patch | patch -d/dl/cmake -p1 \ - && if [ -n "$CMAKE_WINNT" ]; then \ - set -- -DCMAKE_C_FLAGS="-O2 -D_WIN32_WINNT=$CMAKE_WINNT" \ - -DCMAKE_CXX_FLAGS="-O2 -D_WIN32_WINNT=$CMAKE_WINNT" ; \ - fi \ - && cmake "$@" -DCMAKE_BUILD_TYPE=Release \ + && cmake -DCMAKE_C_FLAGS="$CMAKE_C_FLAGS" \ + -DCMAKE_CXX_FLAGS="$CMAKE_CXX_FLAGS" \ + -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_SYSTEM_NAME=Windows \ -DCMAKE_C_COMPILER=$ARCH-gcc \ -DCMAKE_CXX_COMPILER=$ARCH-g++ \ diff --git a/README.md b/README.md index 00b2f22..8ab8265 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,14 @@ Build the image, then run it to produce a self-extracting 7z archive: docker build -t w64devkit . docker run --rm w64devkit >w64devkit-x64.exe +The default variant is `x64`. Select a standalone x86 or combined multilib +toolchain with a build argument: + + docker build --build-arg VARIANT=x86 -t w64devkit . + docker build --build-arg VARIANT=multilib -t w64devkit . + +`multibuild.sh -a` builds all three variants. + This takes about 15 minutes on modern systems. You will need an internet connection during the first few minutes of the build. **Note:** Do not use PowerShell because it lacks file redirection. diff --git a/multibuild.sh b/multibuild.sh index 8232859..953dab9 100755 --- a/multibuild.sh +++ b/multibuild.sh @@ -8,27 +8,29 @@ # $ ./multibuild.sh -as "$(git describe | tr v -)" set -e -arch= +variants= dryrun= suffix="$(git describe --exact-match 2>/dev/null | tr v - || true)" usage() { cat </dev/null || true } trap cleanup EXIT -for variant in $arch; do - if [ -e "src/variant-$variant.args" ]; then - $dryrun docker build \ - $(sed 's/^/--build-arg /' "src/variant-$variant.args") \ - -t $target . - elif [ -e "src/variant-$variant.patch" ]; then - tmp=$(mktemp -d) - $dryrun cp Dockerfile "$tmp/" - $dryrun patch "$tmp/Dockerfile" "src/variant-$variant.patch" - $dryrun docker build -f "$tmp/Dockerfile" -t $target . - rm -rf -- "$tmp" - else - $dryrun docker build -t $target . - fi +for variant in $variants; do + $dryrun docker build --build-arg VARIANT=$variant -t $target . out="w64devkit-$variant$suffix.7z.exe" if [ -n "$dryrun" ]; then $dryrun docker run --rm $target ">$out" diff --git a/src/variant-x86.args b/src/variant-x86.args deleted file mode 100644 index 06ad08c..0000000 --- a/src/variant-x86.args +++ /dev/null @@ -1,10 +0,0 @@ -ARCH=i686-w64-mingw32 -MULTILIB=--disable-multilib -ARCH_FLAGS=--with-arch=pentium4 -CRT_LIB64=--disable-lib64 -WINNT_FLAGS=--with-default-win32-winnt=0x0501 -MANIFEST_FLAGS=--disable-win32-utf8-manifest -BUSYBOX_CONFIG=mingw32w_defconfig -ZSTD_FLAGS=HAVE_THREAD=0 -CMAKE_WINNT=0x0601 -NSIS_ARCH=x86 From d9804ea14b032017eef097a4140ea1904e43588c Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Sat, 29 Aug 2026 18:13:58 -0500 Subject: [PATCH 09/11] Build multilib artifacts in CI Treat the multilib profile as a first-class CI and release artifact alongside the standalone x64 and x86 profiles. Add a build-multilib job that selects VARIANT=multilib, uses an independent GitHub Actions cache scope, extracts the generated self-extracting archive, and uploads it with a multilib-specific name. Run it after the x64 job so the workflow retains the existing ordering while allowing the x86 and multilib builds to proceed independently. Make tagged releases wait for the multilib build as well. Build the signed target with VARIANT=multilib, pass the same trusted-signing credentials used by the other profiles, and pack the result as w64devkit-multilib-.7z.exe. The existing release glob then publishes the signed multilib archive with the x64, x86, and source artifacts. --- .github/workflows/build.yml | 67 ++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6cddf41..3b3e258 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -129,8 +129,52 @@ jobs: path: ${{ steps.filename.outputs.archive }}.7z.exe archive: false + build-multilib: + runs-on: ubuntu-latest + needs: build-x64 + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + env: + ARCH: multilib + + steps: + - uses: actions/checkout@v6 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Generate archive name and version string + id: filename + run: | + GIT_VERSION="$(git describe --tags --always)" + VERSION="${GIT_VERSION#v}" + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "archive=w64devkit-$ARCH-$VERSION" >> $GITHUB_OUTPUT + + - name: Build image + uses: docker/build-push-action@v7 + with: + context: . + build-args: VARIANT=multilib + tags: w64devkit:${{ env.ARCH }} + load: true + cache-from: type=gha,scope=w64devkit-${{ env.ARCH }} + cache-to: type=gha,scope=w64devkit-${{ env.ARCH }},mode=max,ignore-error=true + + - name: Extract artifact + run: | + docker run --rm w64devkit:${{ env.ARCH }} > w64devkit.exe + mv w64devkit.exe ${{ steps.filename.outputs.archive }}.7z.exe + ls -lh ${{ steps.filename.outputs.archive }}.7z.exe + + - name: Upload artifact + uses: actions/upload-artifact@v7 + with: + name: ${{ steps.filename.outputs.archive }}.7z.exe + path: ${{ steps.filename.outputs.archive }}.7z.exe + archive: false + release: - needs: [build-x64, build-x86] + needs: [build-x64, build-x86, build-multilib] if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest environment: release @@ -196,6 +240,27 @@ jobs: > w64devkit-x86-${{ steps.filename.outputs.version }}.7z.exe ls -lh w64devkit-x86-${{ steps.filename.outputs.version }}.7z.exe + - name: Build signed image (multilib) + uses: docker/build-push-action@v7 + with: + context: . + build-args: VARIANT=multilib + target: signed + tags: w64devkit:multilib-signed + load: true + cache-from: type=gha,scope=w64devkit-multilib + cache-to: type=gha,scope=w64devkit-multilib,mode=max,ignore-error=true + + - name: Sign and pack (multilib) + run: | + docker run --rm \ + -e AZURE_CLIENT_ID -e AZURE_TENANT_ID \ + -e AAS_SIGN_ENDPOINT -e AAS_SIGN_ACCOUNT -e AAS_SIGN_PROFILE \ + -e ACTIONS_ID_TOKEN_REQUEST_URL -e ACTIONS_ID_TOKEN_REQUEST_TOKEN \ + w64devkit:multilib-signed \ + > w64devkit-multilib-${{ steps.filename.outputs.version }}.7z.exe + ls -lh w64devkit-multilib-${{ steps.filename.outputs.version }}.7z.exe + - name: Download source tarball uses: actions/download-artifact@v8 with: From 219117849b20e639b2544ff2808f287d3a262157 Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Sat, 29 Aug 2026 18:56:39 -0500 Subject: [PATCH 10/11] Simplify variant profile controls Use the selected VARIANT directly for multilib-only control flow rather than maintaining a separate EXTRA_32 boolean. Redeclare the global build argument in the selected cross stage so each conditional can state the actual profile requirement explicitly. Represent GCC multilib and mingw-w64 CRT selections as enable or disable state instead of storing complete configure options. Form the GCC and CRT arguments at their call sites, which keeps punctuation out of the profile data and makes the three configurations easier to compare. Remove the standalone x86 WINNT_FLAGS override. The mingw-default-win32-winnt patch already substitutes Windows XP for every __i386__ compilation, so passing the same header default through configure was redundant. Keep the separate Windows 7 CMake flags because CMake and its bundled curl cannot build against the XP target. Rename the remaining values that intentionally contain complete command arguments to GCC_ARCH_FLAG, GCC_MANIFEST_FLAG, and ZSTD_THREAD_FLAG. The component scope and representation are now visible in each name. Verify the resulting x64, x86, and multilib Dockerfiles with build checks and complete cross-toolchain builds. Confirm that only the multilib profile executes the secondary 32-bit runtime and alias blocks and that each GCC and CRT configure command receives the expected enable or disable options. --- Dockerfile | 75 +++++++++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/Dockerfile b/Dockerfile index 61af5e9..f669d14 100644 --- a/Dockerfile +++ b/Dockerfile @@ -210,50 +210,45 @@ RUN mkdir nsis \ FROM dl-cross AS variant-x64 ENV ARCH=x86_64-w64-mingw32 \ - ARCH_FLAGS="" \ - MULTILIB=--disable-multilib \ - CRT_LIB32=--disable-lib32 \ - CRT_LIB64=--enable-lib64 \ - WINNT_FLAGS="" \ - MANIFEST_FLAGS="" \ - EXTRA_32=0 \ + GCC_ARCH_FLAG="" \ + GCC_MULTILIB=disable \ + CRT_LIB32=disable \ + CRT_LIB64=enable \ + GCC_MANIFEST_FLAG="" \ BUSYBOX_CONFIG=mingw64u_defconfig \ - ZSTD_FLAGS="" \ + ZSTD_THREAD_FLAG="" \ CMAKE_C_FLAGS="" \ CMAKE_CXX_FLAGS="" \ NSIS_ARCH=amd64 FROM dl-cross AS variant-x86 ENV ARCH=i686-w64-mingw32 \ - ARCH_FLAGS=--with-arch=pentium4 \ - MULTILIB=--disable-multilib \ - CRT_LIB32=--enable-lib32 \ - CRT_LIB64=--disable-lib64 \ - WINNT_FLAGS=--with-default-win32-winnt=0x0501 \ - MANIFEST_FLAGS=--disable-win32-utf8-manifest \ - EXTRA_32=0 \ + GCC_ARCH_FLAG=--with-arch=pentium4 \ + GCC_MULTILIB=disable \ + CRT_LIB32=enable \ + CRT_LIB64=disable \ + GCC_MANIFEST_FLAG=--disable-win32-utf8-manifest \ BUSYBOX_CONFIG=mingw32w_defconfig \ - ZSTD_FLAGS=HAVE_THREAD=0 \ + ZSTD_THREAD_FLAG=HAVE_THREAD=0 \ CMAKE_C_FLAGS="-O2 -D_WIN32_WINNT=0x0601" \ CMAKE_CXX_FLAGS="-O2 -D_WIN32_WINNT=0x0601" \ NSIS_ARCH=x86 FROM dl-cross AS variant-multilib ENV ARCH=x86_64-w64-mingw32 \ - ARCH_FLAGS=--with-arch-32=pentium4 \ - MULTILIB=--enable-multilib \ - CRT_LIB32=--enable-lib32 \ - CRT_LIB64=--enable-lib64 \ - WINNT_FLAGS="" \ - MANIFEST_FLAGS="" \ - EXTRA_32=1 \ + GCC_ARCH_FLAG=--with-arch-32=pentium4 \ + GCC_MULTILIB=enable \ + CRT_LIB32=enable \ + CRT_LIB64=enable \ + GCC_MANIFEST_FLAG="" \ BUSYBOX_CONFIG=mingw64u_defconfig \ - ZSTD_FLAGS="" \ + ZSTD_THREAD_FLAG="" \ CMAKE_C_FLAGS="" \ CMAKE_CXX_FLAGS="" \ NSIS_ARCH=amd64 FROM variant-${VARIANT} AS cross +ARG VARIANT WORKDIR /dl/binutils COPY src/binutils-*.patch $PREFIX/src/ @@ -285,7 +280,6 @@ RUN printf '#include \n#if __has_include_next()\n#include_n --prefix=/bootstrap \ --host=$ARCH \ --with-default-msvcrt=msvcrt-os \ - $WINNT_FLAGS \ && make -j$(nproc) \ && make install @@ -298,8 +292,8 @@ RUN cat $PREFIX/src/gcc-*.patch | patch -d/dl/gcc -p1 \ && /dl/gcc/configure \ --prefix=/bootstrap \ --with-sysroot=/bootstrap \ - $ARCH_FLAGS \ - $MULTILIB \ + $GCC_ARCH_FLAG \ + --${GCC_MULTILIB}-multilib \ --target=$ARCH \ --enable-static \ --disable-shared \ @@ -332,7 +326,7 @@ RUN mkdir -p $PREFIX/lib \ && CC=$ARCH-gcc AR=$ARCH-ar DESTDIR=$PREFIX/lib/ \ sh $PREFIX/src/libchkstk.S \ && ln $PREFIX/lib/libchkstk.a /bootstrap/lib/ \ - && if [ "$EXTRA_32" = 1 ]; then \ + && if [ "$VARIANT" = multilib ]; then \ mkdir -p $PREFIX/lib32 /bootstrap/lib32 \ && CC="$ARCH-gcc -m32" AR=$ARCH-ar DESTDIR=$PREFIX/lib32/ \ sh $PREFIX/src/libmemory.c \ @@ -349,8 +343,8 @@ RUN /dl/mingw/mingw-w64-crt/configure \ --host=$ARCH \ --with-default-msvcrt=msvcrt-os \ --disable-dependency-tracking \ - $CRT_LIB32 \ - $CRT_LIB64 \ + --${CRT_LIB32}-lib32 \ + --${CRT_LIB64}-lib64 \ CFLAGS="-O2" \ LDFLAGS="-s" \ && make -j$(nproc) \ @@ -369,7 +363,7 @@ RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ && make install WORKDIR /x-winpthreads32 -RUN if [ "$EXTRA_32" = 1 ]; then \ +RUN if [ "$VARIANT" = multilib ]; then \ /dl/mingw/mingw-w64-libraries/winpthreads/configure \ --prefix=/bootstrap \ --libdir=/bootstrap/lib32 \ @@ -459,7 +453,6 @@ RUN /dl/mingw/mingw-w64-headers/configure \ --host=$ARCH \ --enable-idl \ --with-default-msvcrt=msvcrt-os \ - $WINNT_FLAGS \ && make -j$(nproc) \ && make install @@ -470,8 +463,8 @@ RUN /dl/mingw/mingw-w64-crt/configure \ --host=$ARCH \ --with-default-msvcrt=msvcrt-os \ --disable-dependency-tracking \ - $CRT_LIB32 \ - $CRT_LIB64 \ + --${CRT_LIB32}-lib32 \ + --${CRT_LIB64}-lib64 \ CFLAGS="-O2" \ LDFLAGS="-s" \ && make -j$(nproc) \ @@ -482,7 +475,7 @@ COPY src/threads.h $PREFIX/include/ RUN $ARCH-gcc -c -Oz -I$PREFIX/include/ \ -ffunction-sections -Wa,--no-pad-sections $PREFIX/src/threads.c \ && $ARCH-ar r $PREFIX/lib/libmingwex.a threads.o \ - && if [ "$EXTRA_32" = 1 ]; then \ + && if [ "$VARIANT" = multilib ]; then \ $ARCH-gcc -m32 -c -Oz -I$PREFIX/include/ \ -ffunction-sections -Wa,--no-pad-sections \ -o threads32.o $PREFIX/src/threads.c \ @@ -502,7 +495,7 @@ RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ && make install WORKDIR /winpthreads32 -RUN if [ "$EXTRA_32" = 1 ]; then \ +RUN if [ "$VARIANT" = multilib ]; then \ /dl/mingw/mingw-w64-libraries/winpthreads/configure \ --prefix=$PREFIX \ --libdir=$PREFIX/lib32 \ @@ -524,8 +517,8 @@ RUN cat $PREFIX/src/crossgcc-*.patch | patch -d/dl/gcc -p1 \ --prefix=$PREFIX \ --with-sysroot=$PREFIX \ --with-native-system-header-dir=/include \ - $ARCH_FLAGS \ - $MULTILIB \ + $GCC_ARCH_FLAG \ + --${GCC_MULTILIB}-multilib \ --target=$ARCH \ --host=$ARCH \ --enable-static \ @@ -544,7 +537,7 @@ RUN cat $PREFIX/src/crossgcc-*.patch | patch -d/dl/gcc -p1 \ --disable-lto \ --disable-nls \ --disable-win32-registry \ - $MANIFEST_FLAGS \ + $GCC_MANIFEST_FLAG \ --enable-mingw-wildcard \ CFLAGS_FOR_TARGET="-O2" \ CXXFLAGS_FOR_TARGET="-O2" \ @@ -582,7 +575,7 @@ RUN $ARCH-gcc -DEXE=gcc.exe -DCMD=cc \ -o $PREFIX/bin/$ARCH-{}.exe $PREFIX/src/alias.c -lkernel32 # Create i686 tool aliases -RUN if [ "$EXTRA_32" = 1 ]; then \ +RUN if [ "$VARIANT" = multilib ]; then \ printf '%s\n' addr2line ar c++filt gcc-ar gcc-nm gcc-ranlib gcov \ gcov-dump gcov-tool gendef nm objcopy objdump ranlib size strings \ strip uuidgen windmc \ @@ -832,7 +825,7 @@ RUN make -j$(nproc) CC=$ARCH-gcc AR=$ARCH-ar CFLAGS="-O2" libzstd.a \ WORKDIR /dl/zstd RUN make -j$(nproc) -C programs zstd \ - CC=$ARCH-gcc CFLAGS="-O2" LDFLAGS="-s" EXT=.exe $ZSTD_FLAGS \ + CC=$ARCH-gcc CFLAGS="-O2" LDFLAGS="-s" EXT=.exe $ZSTD_THREAD_FLAG \ && mkdir -p /out/bin \ && cp programs/zstd.exe /out/bin/ \ && $ARCH-gcc -DEXE=zstd.exe -DCMD=unzstd \ From 8628abc958a7147bbb7ddfe853becd6626ba5038 Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Sat, 29 Aug 2026 21:22:05 -0500 Subject: [PATCH 11/11] Merge multilib support into x64 variant --- .github/workflows/build.yml | 67 +------------------------------------ Dockerfile | 30 +++++------------ README.md | 7 ++-- multibuild.sh | 8 ++--- 4 files changed, 15 insertions(+), 97 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3b3e258..6cddf41 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -129,52 +129,8 @@ jobs: path: ${{ steps.filename.outputs.archive }}.7z.exe archive: false - build-multilib: - runs-on: ubuntu-latest - needs: build-x64 - if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository - env: - ARCH: multilib - - steps: - - uses: actions/checkout@v6 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 - - - name: Generate archive name and version string - id: filename - run: | - GIT_VERSION="$(git describe --tags --always)" - VERSION="${GIT_VERSION#v}" - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "archive=w64devkit-$ARCH-$VERSION" >> $GITHUB_OUTPUT - - - name: Build image - uses: docker/build-push-action@v7 - with: - context: . - build-args: VARIANT=multilib - tags: w64devkit:${{ env.ARCH }} - load: true - cache-from: type=gha,scope=w64devkit-${{ env.ARCH }} - cache-to: type=gha,scope=w64devkit-${{ env.ARCH }},mode=max,ignore-error=true - - - name: Extract artifact - run: | - docker run --rm w64devkit:${{ env.ARCH }} > w64devkit.exe - mv w64devkit.exe ${{ steps.filename.outputs.archive }}.7z.exe - ls -lh ${{ steps.filename.outputs.archive }}.7z.exe - - - name: Upload artifact - uses: actions/upload-artifact@v7 - with: - name: ${{ steps.filename.outputs.archive }}.7z.exe - path: ${{ steps.filename.outputs.archive }}.7z.exe - archive: false - release: - needs: [build-x64, build-x86, build-multilib] + needs: [build-x64, build-x86] if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest environment: release @@ -240,27 +196,6 @@ jobs: > w64devkit-x86-${{ steps.filename.outputs.version }}.7z.exe ls -lh w64devkit-x86-${{ steps.filename.outputs.version }}.7z.exe - - name: Build signed image (multilib) - uses: docker/build-push-action@v7 - with: - context: . - build-args: VARIANT=multilib - target: signed - tags: w64devkit:multilib-signed - load: true - cache-from: type=gha,scope=w64devkit-multilib - cache-to: type=gha,scope=w64devkit-multilib,mode=max,ignore-error=true - - - name: Sign and pack (multilib) - run: | - docker run --rm \ - -e AZURE_CLIENT_ID -e AZURE_TENANT_ID \ - -e AAS_SIGN_ENDPOINT -e AAS_SIGN_ACCOUNT -e AAS_SIGN_PROFILE \ - -e ACTIONS_ID_TOKEN_REQUEST_URL -e ACTIONS_ID_TOKEN_REQUEST_TOKEN \ - w64devkit:multilib-signed \ - > w64devkit-multilib-${{ steps.filename.outputs.version }}.7z.exe - ls -lh w64devkit-multilib-${{ steps.filename.outputs.version }}.7z.exe - - name: Download source tarball uses: actions/download-artifact@v8 with: diff --git a/Dockerfile b/Dockerfile index f669d14..6006568 100644 --- a/Dockerfile +++ b/Dockerfile @@ -210,9 +210,9 @@ RUN mkdir nsis \ FROM dl-cross AS variant-x64 ENV ARCH=x86_64-w64-mingw32 \ - GCC_ARCH_FLAG="" \ - GCC_MULTILIB=disable \ - CRT_LIB32=disable \ + GCC_ARCH_FLAG=--with-arch-32=pentium4 \ + GCC_MULTILIB=enable \ + CRT_LIB32=enable \ CRT_LIB64=enable \ GCC_MANIFEST_FLAG="" \ BUSYBOX_CONFIG=mingw64u_defconfig \ @@ -234,21 +234,7 @@ ENV ARCH=i686-w64-mingw32 \ CMAKE_CXX_FLAGS="-O2 -D_WIN32_WINNT=0x0601" \ NSIS_ARCH=x86 -FROM dl-cross AS variant-multilib -ENV ARCH=x86_64-w64-mingw32 \ - GCC_ARCH_FLAG=--with-arch-32=pentium4 \ - GCC_MULTILIB=enable \ - CRT_LIB32=enable \ - CRT_LIB64=enable \ - GCC_MANIFEST_FLAG="" \ - BUSYBOX_CONFIG=mingw64u_defconfig \ - ZSTD_THREAD_FLAG="" \ - CMAKE_C_FLAGS="" \ - CMAKE_CXX_FLAGS="" \ - NSIS_ARCH=amd64 - FROM variant-${VARIANT} AS cross -ARG VARIANT WORKDIR /dl/binutils COPY src/binutils-*.patch $PREFIX/src/ @@ -326,7 +312,7 @@ RUN mkdir -p $PREFIX/lib \ && CC=$ARCH-gcc AR=$ARCH-ar DESTDIR=$PREFIX/lib/ \ sh $PREFIX/src/libchkstk.S \ && ln $PREFIX/lib/libchkstk.a /bootstrap/lib/ \ - && if [ "$VARIANT" = multilib ]; then \ + && if [ "$GCC_MULTILIB" = enable ]; then \ mkdir -p $PREFIX/lib32 /bootstrap/lib32 \ && CC="$ARCH-gcc -m32" AR=$ARCH-ar DESTDIR=$PREFIX/lib32/ \ sh $PREFIX/src/libmemory.c \ @@ -363,7 +349,7 @@ RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ && make install WORKDIR /x-winpthreads32 -RUN if [ "$VARIANT" = multilib ]; then \ +RUN if [ "$GCC_MULTILIB" = enable ]; then \ /dl/mingw/mingw-w64-libraries/winpthreads/configure \ --prefix=/bootstrap \ --libdir=/bootstrap/lib32 \ @@ -475,7 +461,7 @@ COPY src/threads.h $PREFIX/include/ RUN $ARCH-gcc -c -Oz -I$PREFIX/include/ \ -ffunction-sections -Wa,--no-pad-sections $PREFIX/src/threads.c \ && $ARCH-ar r $PREFIX/lib/libmingwex.a threads.o \ - && if [ "$VARIANT" = multilib ]; then \ + && if [ "$GCC_MULTILIB" = enable ]; then \ $ARCH-gcc -m32 -c -Oz -I$PREFIX/include/ \ -ffunction-sections -Wa,--no-pad-sections \ -o threads32.o $PREFIX/src/threads.c \ @@ -495,7 +481,7 @@ RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \ && make install WORKDIR /winpthreads32 -RUN if [ "$VARIANT" = multilib ]; then \ +RUN if [ "$GCC_MULTILIB" = enable ]; then \ /dl/mingw/mingw-w64-libraries/winpthreads/configure \ --prefix=$PREFIX \ --libdir=$PREFIX/lib32 \ @@ -575,7 +561,7 @@ RUN $ARCH-gcc -DEXE=gcc.exe -DCMD=cc \ -o $PREFIX/bin/$ARCH-{}.exe $PREFIX/src/alias.c -lkernel32 # Create i686 tool aliases -RUN if [ "$VARIANT" = multilib ]; then \ +RUN if [ "$GCC_MULTILIB" = enable ]; then \ printf '%s\n' addr2line ar c++filt gcc-ar gcc-nm gcc-ranlib gcov \ gcov-dump gcov-tool gendef nm objcopy objdump ranlib size strings \ strip uuidgen windmc \ diff --git a/README.md b/README.md index 8ab8265..6a02597 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,12 @@ Build the image, then run it to produce a self-extracting 7z archive: docker build -t w64devkit . docker run --rm w64devkit >w64devkit-x64.exe -The default variant is `x64`. Select a standalone x86 or combined multilib -toolchain with a build argument: +The default `x64` variant is a combined x64/x86 multilib toolchain. Select a +standalone x86 toolchain with a build argument: docker build --build-arg VARIANT=x86 -t w64devkit . - docker build --build-arg VARIANT=multilib -t w64devkit . -`multibuild.sh -a` builds all three variants. +`multibuild.sh -a` builds both variants. This takes about 15 minutes on modern systems. You will need an internet connection during the first few minutes of the build. **Note:** Do not use diff --git a/multibuild.sh b/multibuild.sh index 953dab9..b6c2de8 100755 --- a/multibuild.sh +++ b/multibuild.sh @@ -14,23 +14,21 @@ suffix="$(git describe --exact-match 2>/dev/null | tr v - || true)" usage() { cat <