#!/bin/sh #=============================================================== # Filename : scripts/sinner # Purpose : Builds Linux-to-Windows cross-compiler toolchains. # Authors : Zach van Rijn # License : MIT # Revision : 20190531 #=============================================================== #--------------------------------------------------------------- # README # # overview # -------- # # This script builds "musl-cross-make" cross-compiler toolchains # that are hosted on Linux and target Windows. For example, your # MIPS router can use up-to-date versions of GCC to build code # (C, C++, Fortran) for your Windows XP machine. 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: # # What does this look like? Modern GCC that does: # # * Linux on ARM, Motorola 68000, MIPS, OpenRISC, PowerPC, # RISC-V, S/390, SuperH, x86-based, more? # # --> Windows XP to 10, and possibly older. # # The goal, of course, is to achieve parity with musl.cc's Linux # offerings. This is the script to build the binaries located at # https://more.musl.cc/YOUR-HOST-ARCHITECTURE/*-w64-mingw32.zip # # # build platforms # --------------- # # You need Linux to build these, and an architecture that runs a # toolchain from musl.cc. # # # 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) # * tar # * xz # * zip # # e.g., apk add cmake curl git make patch rsync tar xz zip # # # other notes # ----------- # # * A prior version of this script ('prepare') relies on Linux # 'binfmt_misc' and QEMU to emulate certain build byproducts # and requires root privileges to install (but not use) that # setup. This version cross-compiles the toolchains purely. # # * This script uses the 'mingw-cross-make' flavor maintained # at https://git.zv.io/toolchains/mingw-cross-make to build # MinGW toolchains. Issues should be addressed there. # # # usage # ----- # # $ ./scripts/sinner [TRIPLE ...] # # $ ./scripts/sinner i686-w64-mingw32 x86_64-w64-mingw32 #--------------------------------------------------------------- # 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.1.0 BINUTILS_VER=2.32 MUSL_VER=git-a60b9e06861e56c0810bae0249b421e1758d281a GMP_VER=6.1.2 MPC_VER=1.1.0 MPFR_VER=4.0.2 MINGW_VER=git-3e6c10aeba81c589a7b2ed1e7daee4d4d75b646e ## 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="${HOME}/sinner_src" # base source directory huge="${HOME}/sinner_bld" # base build directory logs="${HOME}/sinner_log" # suite build log directory zips="${HOME}/sinner_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 Linux development environment. Note that unless the # website says otherwise, only the 'x86_64-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=x86_64-linux-musl # platform that builds suite ## Build Environment # # This variable is extended during the toolchain download step. # kale="${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=musl-git # branch name (no assumptions!) sinn=mingw-cross-make sinr=https://git.zv.io/toolchains/${sinn} sinb=mingw ## 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 COMMON_CONFIG += CC="$(HOST)-gcc ${STAT}" CXX="$(HOST)-g++ ${STAT}" FC="$(HOST)-gfortran -${STAT}" COMMON_CONFIG += CFLAGS="${FLAG}" CXXFLAGS="${FLAG}" FFLAGS="${FLAG}" LDFLAGS="-s ${STAT}" COMMON_CONFIG += --disable-nls --disable-bootstrap --build=__USER__ --host=__HOST__ --target=__TARG__ GCC_CONFIG += --enable-threads=__THREADS__ OVERRIDE = --enable-libquadmath --enable-libquadmath-support GCC_VER = __GCC_VER__ BINUTILS_VER = __BINUTILS_VER__ MUSL_VER = __MUSL_VER__ GMP_VER = __GMP_VER__ MPC_VER = __MPC_VER__ MPFR_VER = __MPFR_VER__ MINGW_VER = __MINGW_VER__ LINUX_VER = EOF ); ## Thread Configuration # # By popular demand, both Win32 and POSIX thread models will are # supported. Edit this variable if you don't wish to build both. # tmod="posix" # default: "win32 posix" #--------------------------------------------------------------- # Subroutines. # Download preliminary toolchains. # get_tool () { mkdir -p "${base}"; # 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}/${sinn}" ] || return; git clone ${sinr} "${base}/${sinn}"; } # Overwrite any existing configuration (config.mak) template. # get_conf () { [ -d "${base}/${sinn}" ] || exit 1; printf > "${base}/${sinn}/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. Note: the '-ik' in 'make' is used to # ignore an error: # # The directory that should contain system headers does not # exist: //mingw/include # # We use 'make clean' to ensure that the updated configuration # takes full effect (relevant to thread model settings). # run_make () { cat "${base}/${filt}" | grep -v "#" | while read k; do for tget in ${@}; do # command-line argument list for t in ${tmod}; do # thread model list mkdir -p "${huge}/${k}"; mkdir -p "${logs}/${k}"; get_conf; sed -i "${base}/${sinn}/config.mak" \ -e "s@__USER__@${user}@" \ -e "s@__HOST__@${k}@" \ -e "s@__TARG__@${tget}@" \ \ -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@__MINGW_VER__@${MINGW_VER}@" \ \ -e "s@__THREADS__@${t}@"; if [ ! -d "${huge}/${k}/${tget}${csuf}-${t}" ]; then PATH="${kale}:${base}/${k}${csuf}/bin:${base}/${tget}${csuf}/bin:${PATH}" \ \ CC="${k}-gcc" \ CXX="${k}-g++" \ RANLIB="${k}-ranlib" \ \ CC_FOR_BUILD="${user}-gcc" \ CXX_FOR_BUILD="${user}-g++" \ RANLIB_FOR_BUILD="${user}-ranlib" \ \ make -ik -C "${base}/${sinn}" -O clean install \ HOST=${k} \ TARGET=${tget} \ OUTPUT="${huge}/${k}/${tget}${csuf}-${t}" \ 2>&1 | tee \ "${logs}/${k}/${tget}${csuf}-${t}.log"; fi done; # thread model list done; # command-line argument list done; # source list (hosts) } # Pack the toolchains into tgz files. They're ready for distro. # run_pack () { cat "${base}/${filt}" | grep -v "#" | while read k; do for tget in ${@}; do # command-line argument list for t in ${tmod}; do # thread model list mkdir -p "${zips}/${k}"; if [ ! -e "${zips}/${k}/${tget}${csuf}-${t}.tgz" ]; then ( cd "${huge}/${k}"; tar -pczf "${zips}/${k}/${tget}${csuf}-${t}.tgz" \ ${tget}${csuf}-${t}; ) fi done; # thread model list done; # command-line argument list done; # source list (hosts) } #--------------------------------------------------------------- # Driver. get_tool; # Download initial toolchains. get_repo; # Clone "musl-cross-make" repo. get_conf; # Write toolchain configuration. get_list; # Generate list of targets. get_targ; # Fetch "donor" toolchains. run_make ${@}; # Build specified toolchains. run_pack ${@}; # Pack output for distribution.