Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ValveSoftware/Proton.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Eikum <aeikum@codeweavers.com>2019-11-26 17:40:12 +0300
committerAndrew Eikum <aeikum@codeweavers.com>2019-11-26 20:03:32 +0300
commit3454fff8d35d22840820013fe4579fd758de7618 (patch)
tree2819bbea08f647cf52b3bb73c3bb1d4683879db2
parent2ba034409cf29845df162500729376e785a80f7d (diff)
build-mingw-w64.sh: Document my findingsproton-4.11-9
-rwxr-xr-xbuild-mingw-w64.sh121
1 files changed, 119 insertions, 2 deletions
diff --git a/build-mingw-w64.sh b/build-mingw-w64.sh
index 30076aa5..4d6d32f0 100755
--- a/build-mingw-w64.sh
+++ b/build-mingw-w64.sh
@@ -2,10 +2,127 @@
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:
+#
+# 64-bit cross-compiler:
+# Build (where the compiler is built): 64-bit linux (our VM)
+# Host (where the compiler is run): 64-bit linux (64-bit Steam runtime)
+# Target (what the compiler outputs): 64-bit win32 (PE files to be run)
+#
+# 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)
+# 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."
echo ""
- echo "Note: Requires a system mingw-w64 to be present already, for us to bootstrap with."
+ echo "Note: Requires a system mingw-w64 compiler to be present already on your build machine, for us to bootstrap with."
echo ""
echo "usage:"
echo -e "\t$0 <installation path e.g. \$HOME/.local>"
@@ -175,7 +292,7 @@ function build_arch {
pushd gcc/
#next step requires libgcc in default library location, but
- #"canadian" build doesn't handle that, so install it explicitly
+ #"canadian" build doesn't handle that(?), so install it explicitly
PATH=$NEWPATH make configure-target-libgcc
PATH=$NEWPATH make -C $WIN32_TARGET_ARCH/libgcc $JOBS
PATH=$NEWPATH make -C $WIN32_TARGET_ARCH/libgcc $JOBS install