diff --git a/build-mingw-w64.sh b/build-mingw-w64.sh index f8c8a74c..fa42418d 100755 --- a/build-mingw-w64.sh +++ b/build-mingw-w64.sh @@ -2,11 +2,7 @@ set -e -# The Story So Far -# -# We need two cross-compilers to build Proton. These each have to run in the -# Steam runtimes, each of which only supports 32- or 64-bit programs. Our build -# VM is a 64-bit Linux machine. So our platform configurations are: +# We need two cross-compilers to build Proton: # # 64-bit cross-compiler: # Build (where the compiler is built): 64-bit linux (our VM) @@ -15,109 +11,8 @@ set -e # # 32-bit cross-compiler: # Build (where the compiler is built): 64-bit linux (our VM) -# Host (where the compiler is run): 32-bit linux (32-bit Steam runtime) +# Host (where the compiler is run): 64-bit linux (64-bit Steam runtime) # Target (what the compiler outputs): 32-bit win32 (PE files to be run) -# -# The former is a pretty standard cross-compiler setup. -# -# gcc calls the latter, where all of the platforms are different, a "Canadian" -# build. See "The GNU configure and build system" by Ian Lance Taylor, section -# "Canadian Cross", available here: -# https://www.airs.com/ian/configure/configure_6.html -# -# This turned out to be quite difficult, possibly due to the added complexity of -# mingw-w64. I'm documenting the problems I had and how I solved/worked around -# them here, to hopefully save myself or someone else some heartburn in the -# future. If you are a compiler expert and find yourself shaking your head at -# this poor fool, I welcome your assistance improving this. -# -# Canadian builds require the build machine to already have a cross-compiler for -# the Target platform available on the Build machine. Without this, the gcc build -# will fail with: -# -# i686-w64-mingw32-gcc -dumpspecs > tmp-specs -# /bin/bash: i686-w64-mingw32-gcc: command not found -# -# We are building both C and C++ lang support, so we need both gcc and g++ -# cross-compilers available. With the Build->Target cross-compilers installed, -# we can now build gcc, and use that to build mingw-w64. After that, we need to -# build gcc's libraries, like libgcc and libstdc++v3, against those mingw-w64 -# libraries. However, the libatomic and/or libgomp builds will fail with: -# -# checking for suffix of object files... -# configure: error: in `/home/vagrant/mingw/build-i686-w64-mingw32/gcc/i686-w64-mingw32/libatomic': -# configure: error: C compiler cannot create executables -# See `config.log' for more details -# -# checking for suffix of object files... -# configure: error: in `/home/vagrant/mingw/build-i686-w64-mingw32/gcc/i686-w64-mingw32/libgomp': -# configure: error: C compiler cannot create executables -# See `config.log' for more details -# -# Digging into config.log shows it can't find libgcc: -# -# configure:3722: checking whether the C compiler works -# configure:3744: i686-w64-mingw32-gcc -L/home/vagrant/mingw/output/i686-w64-mingw32/lib -L/home/vagrant/mingw/output/mingw/lib -isystem /home/vagrant/mingw/output/i686-w64-mingw32/include -isystem /home/vagrant/mingw/output/mingw/include -g -O2 conftest.c >&5 -# /home/vagrant/mingw/output/lib/gcc/i686-w64-mingw32/9.2.0/../../../../i686-w64-mingw32/bin/ld: cannot find -lgcc -# /home/vagrant/mingw/output/lib/gcc/i686-w64-mingw32/9.2.0/../../../../i686-w64-mingw32/bin/ld: cannot find -lgcc_eh -# /home/vagrant/mingw/output/lib/gcc/i686-w64-mingw32/9.2.0/../../../../i686-w64-mingw32/bin/ld: cannot find -lgcc -# /home/vagrant/mingw/output/lib/gcc/i686-w64-mingw32/9.2.0/../../../../i686-w64-mingw32/bin/ld: cannot find -lgcc_eh -# collect2: error: ld returned 1 exit status -# -# I don't know what causes this (maybe Canadian builds don't like being split up -# like this?). However, installing libgcc explicitly first will work around it. -# After installing libgcc explicitly, we can then build the rest of gcc's -# libraries. That was all the easy (ha!) stuff. At this point, you will have a -# cross-compiler that will build Proton. -# -# However, there's a sneaky problem. For some reason the libstdc++v3 build system -# requires libstdc++ to be available to detect C-lang functions(?!?). It will -# still build without those C functions, but it may have far worse performance -# (see Proton github issue #3198). You can detect this situation by examining the -# config.log output for libstdc++v3 after your build completes: -# -# configure:16811: checking for gettimeofday -# configure:16827: checking sys/time.h usability -# configure:16827: i686-w64-mingw32-c++ -L/home/vagrant/mingw/output/i686-w64-mingw32/lib -L/home/vagrant/mingw/output/mingw/lib -isystem /home/vagrant/mingw/output/i686-w64-mingw32/include -isystem /home/vagrant/mingw/output/mingw/include -c -g -O2 -fno-exceptions conftest.cpp >&5 -# configure:16827: $? = 0 -# configure:16827: result: yes -# configure:16827: checking sys/time.h presence -# configure:16827: i686-w64-mingw32-c++ -L/home/vagrant/mingw/output/i686-w64-mingw32/lib -L/home/vagrant/mingw/output/mingw/lib -isystem /home/vagrant/mingw/output/i686-w64-mingw32/include -isystem /home/vagrant/mingw/output/mingw/include -E conftest.cpp -# configure:16827: $? = 0 -# configure:16827: result: yes -# configure:16827: checking for sys/time.h -# configure:16827: result: yes -# configure:16840: checking for gettimeofday -# configure:16875: i686-w64-mingw32-c++ -L/home/vagrant/mingw/output/i686-w64-mingw32/lib -L/home/vagrant/mingw/output/mingw/lib -isystem /home/vagrant/mingw/output/i686-w64-mingw32/include -isystem /home/vagrant/mingw/output/mingw/include -o conftest.exe -g -O2 -fno-exceptions conftest.cpp >&5 -# /home/vagrant/mingw/output/lib/gcc/i686-w64-mingw32/9.2.0/../../../../i686-w64-mingw32/bin/ld: cannot find -lstdc++ -# collect2: error: ld returned 1 exit status -# -# But that error doesn't kill configure, and it happily continues with this in -# config.h: -# -# /* #undef _GLIBCXX_USE_GETTIMEOFDAY */ -# -# This triggers the bad codepath in libstdc++v3 that caused the performance -# problem mentioned above, and is clearly wrong anyway, as gettimeofday is -# definitely available. Yes, this was a huge pain to puzzle out. I "solved" this -# by letting the libstdc++v3 build continue, then re-running the build after -# installing it, so now it will find libstdc++ and so correctly detect the C-lang -# function that has nothing at all to do with libstdc++. Argh. -# -# After all that, we finally have a functioning set of cross-compilers. Most of -# the configuration parameters used here are taken from the Arch Linux mingw-w64 -# PKGBUILDs, as those were written by someone with more knowledge than me, and -# have had a lot of testing. We make one tweak to the gcc configuration, which is -# to disable SJLJ exceptions and enable DWARF2 debug symbols. The former -# apparently helps with performance on 32-bit, and the latter puts debug symbols -# in a format that more Linux tooling can read. -# -# Side note, the Arch Linux PKGBUILDs work very differently from how this script -# works. While working on this, I tried to adapt the PKGBUILDs' process here -# (e.g. build a bootstrap C-lang compiler, use that to build mingw-w64, then -# rebuild gcc against the mingw-w64 CRT with C++-lang support), but I ran into a -# ton of problems, possibly caused by the Canadian-ness of the build, and -# eventually ran out of ideas for working around them. if [ -z "$1" ]; then echo "Makes a local build of mingw-w64 in this directory and installs it to the given path." @@ -315,7 +210,7 @@ setup_src mkdir -p $DST_DIR -MINGW_W64_CRT_EXTRA_CONFIGURE="--disable-lib64 --enable-lib32" build_arch i686-linux-gnu i686-w64-mingw32 +MINGW_W64_CRT_EXTRA_CONFIGURE="--disable-lib64 --enable-lib32" build_arch x86_64-linux-gnu i686-w64-mingw32 MINGW_W64_CRT_EXTRA_CONFIGURE="--disable-lib32 --enable-lib64" build_arch x86_64-linux-gnu x86_64-w64-mingw32