#!/bin/sh #=============================================================== # Filename : scripts/winner # Purpose : Builds Windows-to-Linux cross-compiler toolchains. # Authors : Zach van Rijn # License : MIT # Revision : 20200303 #=============================================================== #--------------------------------------------------------------- # README # # overview # -------- # # This script builds "musl-cross-make" cross-compiler toolchains # that are hosted on Windows and target Linux. For example, your # Windows XP machine can use up-to-date versions of GCC to build # code (C, C++, Fortran) for your MIPS router. The libc used is # called 'musl': https://www.musl-libc.org/faq.html # # Others have tried and failed to deliver what you're able to do # with this tiny script. Additions to this list are welcome: # # * https://gnutoolchains.com/download/ # * (um?) # # What does this look like? Modern GCC that does: # # * Win32 --> ARM, Motorola 68000, MIPS, OpenRISC, PowerPC, # RISC-V, S/390, SuperH, x86-based, more? # # The goal, of course, is to achieve parity with musl.cc's Linux # offerings. A link to pre-built Windows binaries is now public, # and this is the script to reproduce them. https://win.musl.cc/ # # # build platforms # --------------- # # In absolute theory, one can build this toolchain suite using a # "native" toolchain from 'musl.cc' suitable for your platform, # to build a MinGW-w64 cross-compiler (hosted on your platform, # targeting i686- or x86_64- Windows), then use that toolchain # to build the suite. Some may exist here: https://more.musl.cc/ # # In practice, you just need 'i686-w64-mingw32-cross' for 32-bit # or 'x86_64-w64-mingw32-cross' for 64-bit that runs on your own # Linux (or Windows, with Cygwin or MSYS2) system. # # # requirements # ------------ # # Consider running this script inside of an isolated environment # such as a container or virtual machine. While not required, we # do not recommend running any foreign scripts or binaries in an # important environment. You'll need the following packages: # # * cmake # * curl # * git # * make # * patch (GNU) # * rsync # * tar # * xz # * zip # # e.g., apk add cmake curl git make patch rsync tar xz zip # # You'll also need an internet connection (or manually do so) to # obtain corresponding "donor" toolchains from musl.cc; what we # are doing is pulling musl and the Linux kernel headers from an # existing toolchain, rather than fuss with getting them to play # nicely with the "Canadian" cross infrastructure. # # # other notes # ----------- # # * Toolchains cannot be built with kernel headers; these are # copied into the output directory after the initial build. # Kernel version is that of donor toolchain. # # * Toolchains cannot be built with the musl library; this is # copied into the output directory after the initial build. # musl version is that of donor toolchain, but may be flaky. # # * If you do not uncomment the 'nano' line, you will build a # large number of toolchains. This requires an exceptional # amount of disk space and time. This is what I use it for. # # # to-do # ----- # # * Fix underlying issue causing kernel headers and musl to be # not built or installed correctly. # # * Generate Cygwin (and/or MSYS2) packages for distribution. #--------------------------------------------------------------- # Configuration. ## Component Versions # # These options are self explanatory, but *must* correspond to a # supported version within the "musl-cross-make" repository. One # other factor to consider is that kernel headers and musl libc # will be harvested from a "donor" toolchain; these versions do # not necessarily correspond to what is built here (yet, TODO). # GCC_VER=9.3.0 BINUTILS_VER=2.34 MUSL_VER=git-0a005f499cf39822166dd4db3d2d31f0639f1b1b GMP_VER=6.2.0 MPC_VER=1.1.0 MPFR_VER=4.1.0 LINUX_VER=5.4.50 # TODO: proper install, no rsync ## Directories # # By default, all toolchains that can be built, are built. This # requires a significant amount of disk space. Please ensure you # have at least 50GB of free disk space in these directories: # base="/tmp/winner_src" # base source directory huge="/tmp/winner_bld" # base build directory logs="/tmp/winner_log" # suite build log directory zips="/tmp/winner_bin" # completed toolchains go here ## Toolchain Mirror # # If you have access to an x86_64 Linux machine, or one that has # an x86_64 QEMU user-mode emulator registered in 'binfmt_misc', # you will always be using the latest available software. # musl=https://more.musl.cc # more.musl.cc or mirror ## Toolchain Naming Conventions # # The musl.cc toolchains follow a simple naming convention: all # cross compilers are suffixed with '-cross', native '-native'. # If you're using a different mirror or convention, set it here. # csuf=-cross # cross suffix nsuf=-native # native suffix ## Toolchain Tuples # # Values can be found at 'https://more.musl.cc/' where the $user # variable corresponds to your build platform, and $host to your # intended Windows development environment. Note that unless the # website says otherwise, only the 'i686-linux-musl' toolchain # directory is up-to-date. If you can't find what you're looking # for you must build a MinGW-w64 suitable toolchain from source. # user=i686-linux-musl # platform that builds suite host=i686-w64-mingw32 # platform that runs suite ## Build Environment # # This variable is extended during the toolchain download step. # kale="${base}/${host}${csuf}/bin:${base}/${user}${csuf}/bin"; ## Repositories # # The build infrastructure used is called "musl-cross-make" and # is upstream https://github.com/richfelker/musl-cross-make, but # this version is incompatible with the current script. It's out # of date, too, so please leave the default unless you fork it. # name=musl-cross-make repo=https://git.zv.io/toolchains/${name} brch=master # branch name (no assumptions!) ## Suite Targets # # Now that RISC-V patches are (unofficially) merged into musl, a # single text file with target tuples (which comprise the suite) # may now be used. Modify this with e.g. a pastebin link if you # wish to use a different list (this one is self-updating). # list=${repo}/raw/${brch}/scripts/triples.txt filt=tuples.txt # filename of saved tuples list ## Suite Configuration # # To facilitate users' needs in customizing the toolchain suite, # a configuration file is embedded below. These settings *must* # be supported by the repository specified above. # # Note: items that are prefixed/suffixed with double underscores # are automatically populated later. Do not modify them here! # conf=$(cat <<'EOF' STAT = -static --static FLAG = -g0 -O2 -fno-align-functions -fno-align-jumps -fno-align-loops -fno-align-labels ifneq ($(NATIVE),) COMMON_CONFIG += CC="$(HOST)-gcc ${STAT}" CXX="$(HOST)-g++ ${STAT}" FC="$(HOST)-gfortran ${STAT}" else COMMON_CONFIG += CC="gcc ${STAT}" CXX="g++ ${STAT}" FC="gfortran ${STAT}" endif COMMON_CONFIG += CFLAGS="${FLAG}" CXXFLAGS="${FLAG}" FFLAGS="${FLAG}" LDFLAGS="-s ${STAT}" COMMON_CONFIG += --disable-nls --disable-bootstrap --build=__USER__ --host=__HOST__ --target=__TARG__ GCC_VER = __GCC_VER__ BINUTILS_VER = __BINUTILS_VER__ MUSL_VER = __MUSL_VER__ GMP_VER = __GMP_VER__ MPC_VER = __MPC_VER__ MPFR_VER = __MPFR_VER__ LINUX_VER = __LINUX_VER__ EOF ); #--------------------------------------------------------------- # Subroutines. # Download preliminary toolchains. # get_tool () { mkdir -p "${base}"; # host if [ ! -d "${base}/${host}${csuf}" ]; then curl ${musl}/${user}/${host}${csuf}.tgz \ | tar 2>/dev/null -C "${base}" -xzf -; ( cd "${base}/${host}${csuf}/bin"; find . -maxdepth 1 -type f | while read k; do ln -sf ${k} ${k#*-*-*-}; done; ) fi # build if [ ! -d "${base}/${user}${csuf}" ]; then curl ${musl}/${user}/${user}${csuf}.tgz \ | tar 2>/dev/null -C "${base}" -xzf -; fi } # Clone a suitable "musl-cross-make" repository. # get_repo () { [ -d "${base}" ] || exit 1; [ ! -d "${base}/${name}" ] || return; git clone ${repo} "${base}/${name}"; } # Overwrite any existing configuration (config.mak) template. # get_conf () { [ -d "${base}/${name}" ] || exit 1; printf > "${base}/${name}/config.mak" "%s\n" \ "${conf}"; } # Fetch an up-to-date list of possible target tuples. Allow the # user to edit this list, if the line is uncommented, before DL. # get_list () { [ ! -f "${base}/${filt}" ] || return; curl -o "${base}/${filt}" ${list}; sed -i "${base}/${filt}" -e '/mingw/d'; #nano "${base}/${filt}"; } # Download all necessary target toolchains. # get_targ () { # targets (if different from build) cat "${base}/${filt}" | grep -v "#" | while read k; do if [ ! -d "${base}/${k}${csuf}" ]; then curl ${musl}/${user}/${k}${csuf}.tgz \ | tar 2>/dev/null -C "${base}" -xzf -; fi done; } # Build the compiler suite without musl or kernel headers. Note: # the '-ik' in the 'make' command is required to avoid issues in # areas that have not yet been investigated but don't affect the # correctness of the resulting toolchain. # run_make () { mkdir -p "${huge}"; mkdir -p "${logs}"; cat "${base}/${filt}" | grep -v "#" | while read k; do get_conf; sed -i "${base}/${name}/config.mak" \ -e "s@__USER__@${user}@" \ -e "s@__HOST__@${host}@" \ -e "s@__TARG__@${k}@" \ \ -e "s@__GCC_VER__@${GCC_VER}@" \ -e "s@__BINUTILS_VER__@${BINUTILS_VER}@" \ -e "s@__MUSL_VER__@${MUSL_VER}@" \ -e "s@__GMP_VER__@${GMP_VER}@" \ -e "s@__MPC_VER__@${MPC_VER}@" \ -e "s@__MPFR_VER__@${MPFR_VER}@" \ -e "s@__LINUX_VER__@@"; if [ ! -d "${huge}/${k}${csuf}" ]; then PATH="${kale}:${base}/${k}${csuf}/bin:${PATH}" \ \ CC="${host}-gcc" \ CXX="${host}-g++" \ RANLIB="${host}-ranlib" \ \ CC_FOR_BUILD="${user}-gcc" \ CXX_FOR_BUILD="${user}-g++" \ RANLIB_FOR_BUILD="${user}-ranlib" \ \ CC_FOR_TARGET="${k}-gcc" \ CXX_FOR_TARGET="${k}-g++" \ RANLIB_FOR_TARGET="${k}-ranlib" \ \ make -ik -C "${base}/${name}" -O install \ TARGET=${k} OUTPUT="${huge}/${k}${csuf}" \ 2>&1 | tee "${logs}/${k}${csuf}.log"; fi done; } # Synchronize a donor toolchain's libraries and headers (for the # sole purposes of musl and kernel headers) with the newly-built # Windows-hosted toolchain. # run_sync () { cat "${base}/${filt}" | grep -v "#" | while read k; do sync=$(cat <