Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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<<EOF'
cat src/variant-x86.args
echo 'EOF'
} >> "$GITHUB_OUTPUT"

- name: Generate archive name and version string
id: filename
Expand All @@ -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 }}
Expand Down Expand Up @@ -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<<EOF'
cat src/variant-x86.args
echo 'EOF'
} >> "$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
Expand Down
150 changes: 135 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down Expand Up @@ -241,6 +262,7 @@ RUN printf '#include <crtdefs.h>\n#if __has_include_next(<stddef.h>)\n#include_n
--prefix=/bootstrap \
--host=$ARCH \
--with-default-msvcrt=msvcrt-os \
$WINNT_FLAGS \
&& make -j$(nproc) \
&& make install

Expand All @@ -253,6 +275,8 @@ RUN cat $PREFIX/src/gcc-*.patch | patch -d/dl/gcc -p1 \
&& /dl/gcc/configure \
--prefix=/bootstrap \
--with-sysroot=/bootstrap \
$ARCH_FLAGS \
$MULTILIB \
--target=$ARCH \
--enable-static \
--disable-shared \
Expand All @@ -266,7 +290,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" \
Expand All @@ -285,7 +308,16 @@ RUN mkdir -p $PREFIX/lib \
&& 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/ \
&& 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 \
Expand All @@ -294,8 +326,8 @@ RUN /dl/mingw/mingw-w64-crt/configure \
--host=$ARCH \
--with-default-msvcrt=msvcrt-os \
--disable-dependency-tracking \
--disable-lib32 \
--enable-lib64 \
--enable-lib32 \
$CRT_LIB64 \
CFLAGS="-O2" \
LDFLAGS="-s" \
&& make -j$(nproc) \
Expand All @@ -313,6 +345,22 @@ RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \
&& make -j$(nproc) \
&& make install

WORKDIR /x-winpthreads32
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) \
&& make install
Expand All @@ -331,7 +379,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 \
Expand Down Expand Up @@ -388,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

Expand All @@ -398,8 +447,8 @@ RUN /dl/mingw/mingw-w64-crt/configure \
--host=$ARCH \
--with-default-msvcrt=msvcrt-os \
--disable-dependency-tracking \
--disable-lib32 \
--enable-lib64 \
--enable-lib32 \
$CRT_LIB64 \
CFLAGS="-O2" \
LDFLAGS="-s" \
&& make -j$(nproc) \
Expand All @@ -409,7 +458,13 @@ 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 \
&& 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 \
Expand All @@ -423,13 +478,31 @@ RUN /dl/mingw/mingw-w64-libraries/winpthreads/configure \
&& make -j$(nproc) \
&& make install

WORKDIR /winpthreads32
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/
RUN cat $PREFIX/src/crossgcc-*.patch | patch -d/dl/gcc -p1 \
&& /dl/gcc/configure \
--prefix=$PREFIX \
--with-sysroot=$PREFIX \
--with-native-system-header-dir=/include \
$ARCH_FLAGS \
$MULTILIB \
--target=$ARCH \
--host=$ARCH \
--enable-static \
Expand All @@ -446,9 +519,9 @@ 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 \
$MANIFEST_FLAGS \
--enable-mingw-wildcard \
CFLAGS_FOR_TARGET="-O2" \
CXXFLAGS_FOR_TARGET="-O2" \
Expand All @@ -475,7 +548,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 \
Expand All @@ -485,6 +558,49 @@ 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 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) \
$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=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=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 \
-o $PREFIX/bin/i686-w64-mingw32-windres.exe \
$PREFIX/src/alias.c -lkernel32 ; \
fi

# Build some extra development tools

FROM cross AS build-gendef
Expand Down Expand Up @@ -598,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/' \
Expand Down Expand Up @@ -693,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 \
Expand Down Expand Up @@ -788,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" \
Comment thread
Peter0x44 marked this conversation as resolved.
-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++ \
Expand Down Expand Up @@ -853,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 \

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder, does nsis need to be able to make "multilib" 32-or-64 bit installers?
I'm not going to use it, just curious. I've actually made windows installers myself at my job it's a surprisingly tricky problem.

PREFIX=$PREFIX \
PREFIX_BIN=$PREFIX/share/nsis/bin \
PREFIX_DATA=$PREFIX/share/nsis \
Expand Down
6 changes: 5 additions & 1 deletion multibuild.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
23 changes: 23 additions & 0 deletions src/crossgcc-i686-dumpmachine.patch
Original file line number Diff line number Diff line change
@@ -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);

19 changes: 19 additions & 0 deletions src/mingw-default-win32-winnt.patch
Original file line number Diff line number Diff line change
@@ -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
Loading