123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 |
- #!/bin/bash
- #
- # Copyright (C) 2024 Kyle Schwarz <zeranoe@gmail.com>
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- #
- ROOT_PATH="/opt/mingw"
- MINGW_W64_BRANCH="master"
- BINUTILS_BRANCH="binutils-2_42-branch"
- GCC_BRANCH="releases/gcc-12"
- ENABLE_THREADS="--enable-threads=posix"
- JOB_COUNT=$(($(getconf _NPROCESSORS_ONLN) + 2))
- LINKED_RUNTIME="msvcrt"
- show_help()
- {
- cat <<EOF
- Usage:
- $0 [options] <arch>...
- Archs:
- i586 Windows 32-bit for old CPUs (Intel Pentium (MMX), AMD K5, K6, K6-2, K6-III)
- i686 Windows 32-bit (Intel P6 [Pentium Pro], AMD K7 and newer)
- x86_64 Windows 64-bit
- Options:
- -h, --help show help
- -j <count>, --jobs <count> override make job count (default: $JOB_COUNT)
- -p <path>, --prefix <path> install location (default: $ROOT_PATH/<arch>)
- -r <path>, --root <path> location for sources, build artifacts and the resulting compiler (default: $ROOT_PATH)
- --keep-artifacts don't remove source and build files after a successful build
- --disable-threads disable pthreads and STL <thread>
- --cached-sources use existing sources instead of downloading new ones
- --binutils-branch <branch> set Binutils branch (default: $BINUTILS_BRANCH)
- --gcc-branch <branch> set GCC branch (default: $GCC_BRANCH)
- --mingw-w64-branch <branch> set MinGW-w64 branch (default: $MINGW_W64_BRANCH)
- --linked-runtime <runtime> set MinGW Linked Runtime (default: $LINKED_RUNTIME)
- EOF
- }
- error_exit()
- {
- local error_msg="$1"
- shift 1
- if [ "$error_msg" ]; then
- printf "%s\n" "$error_msg" >&2
- else
- printf "an error occured\n" >&2
- fi
- exit 1
- }
- arg_error()
- {
- local error_msg="$1"
- shift 1
- error_exit "$error_msg, see --help for options" "$error_msg"
- }
- execute()
- {
- local info_msg="$1"
- local error_msg="$2"
- shift 2
- if [ ! "$error_msg" ]; then
- error_msg="error"
- fi
- if [ "$info_msg" ]; then
- printf "(%d/%d): %s\n" "$CURRENT_STEP" "$TOTAL_STEPS" "$info_msg"
- CURRENT_STEP=$((CURRENT_STEP + 1))
- fi
- "$@" >>"$LOG_FILE" 2>&1 || error_exit "$error_msg, check $LOG_FILE for details"
- }
- create_dir()
- {
- local path="$1"
- shift 1
- execute "" "unable to create directory '$path'" \
- mkdir -p "$path"
- }
- remove_path()
- {
- local path="$1"
- shift 1
- execute "" "unable to remove path '$path'" \
- rm -fr "$path"
- }
- change_dir()
- {
- local path="$1"
- shift 1
- execute "" "unable to cd to directory '$path'" \
- cd "$path"
- }
- download_sources()
- {
- remove_path "$SRC_PATH"
- create_dir "$SRC_PATH"
- change_dir "$SRC_PATH"
- execute "downloading MinGW-w64 source" "" \
- git clone --depth 1 -b "$MINGW_W64_BRANCH" \
- https://git.code.sf.net/p/mingw-w64/mingw-w64 mingw-w64
- execute "downloading Binutils source" "" \
- git clone --depth 1 -b "$BINUTILS_BRANCH" \
- https://sourceware.org/git/binutils-gdb.git binutils
- execute "downloading GCC source" "" \
- git clone --depth 1 -b "$GCC_BRANCH" \
- https://gcc.gnu.org/git/gcc.git gcc
- execute "downloading config.guess" "" \
- curl -o config.guess \
- "https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD"
- }
- build()
- {
- local arch="$1"
- local prefix="$2"
- shift 2
- local bld_path="$BLD_PATH/$arch"
- local host="$arch-w64-mingw32"
- export PATH="$prefix/bin:$PATH"
- remove_path "$bld_path"
- # don't remove a user defined prefix (could be /usr/local)
- if [ ! "$PREFIX" ]; then
- remove_path "$prefix"
- fi
- if [ "$arch" = "i586" ] || [ "$arch" = "i686" ]; then
- local x86_dwarf2="--disable-sjlj-exceptions --with-dwarf2"
- local crt_lib="--enable-lib32 --disable-lib64"
- else
- local x86_dwarf2=""
- local crt_lib="--enable-lib64 --disable-lib32"
- fi
- create_dir "$bld_path/binutils"
- change_dir "$bld_path/binutils"
- execute "($arch): configuring Binutils" "" \
- "$SRC_PATH/binutils/configure" --prefix="$prefix" --disable-shared \
- --enable-static --with-sysroot="$prefix" --target="$host" \
- --disable-multilib --disable-nls --enable-lto --disable-gdb
- execute "($arch): building Binutils" "" \
- make -j $JOB_COUNT
- execute "($arch): installing Binutils" "" \
- make install
- create_dir "$bld_path/mingw-w64-headers"
- change_dir "$bld_path/mingw-w64-headers"
- execute "($arch): configuring MinGW-w64 headers" "" \
- "$SRC_PATH/mingw-w64/mingw-w64-headers/configure" --build="$BUILD" \
- --host="$host" --prefix="$prefix/$host" \
- --with-default-msvcrt=$LINKED_RUNTIME
- execute "($arch): installing MinGW-w64 headers" "" \
- make install
- create_dir "$bld_path/gcc"
- change_dir "$bld_path/gcc"
- execute "($arch): configuring GCC" "" \
- "$SRC_PATH/gcc/configure" --target="$host" --disable-shared \
- --enable-static --disable-multilib --prefix="$prefix" \
- --enable-languages=c,c++ --disable-nls $ENABLE_THREADS \
- $x86_dwarf2
- execute "($arch): building GCC (all-gcc)" "" \
- make -j $JOB_COUNT all-gcc
- execute "($arch): installing GCC (install-gcc)" "" \
- make install-gcc
- create_dir "$bld_path/mingw-w64-crt"
- change_dir "$bld_path/mingw-w64-crt"
- execute "($arch): configuring MinGW-w64 CRT" "" \
- "$SRC_PATH/mingw-w64/mingw-w64-crt/configure" --build="$BUILD" \
- --host="$host" --prefix="$prefix/$host" \
- --with-default-msvcrt=$LINKED_RUNTIME \
- --with-sysroot="$prefix/$host" $crt_lib
- execute "($arch): building MinGW-w64 CRT" "" \
- make -j $JOB_COUNT
- execute "($arch): installing MinGW-w64 CRT" "" \
- make install
- if [ "$ENABLE_THREADS" ]; then
- create_dir "$bld_path/mingw-w64-winpthreads"
- change_dir "$bld_path/mingw-w64-winpthreads"
- execute "($arch): configuring winpthreads" "" \
- "$SRC_PATH/mingw-w64/mingw-w64-libraries/winpthreads/configure" \
- --build="$BUILD" --host="$host" --disable-shared \
- --enable-static --prefix="$prefix/$host"
- execute "($arch): building winpthreads" "" \
- make -j $JOB_COUNT
- execute "($arch): installing winpthreads" "" \
- make install
- fi
- change_dir "$bld_path/gcc"
- execute "($arch): building GCC" "" \
- make -j $JOB_COUNT
- execute "($arch): installing GCC" "" \
- make install
- }
- while :; do
- case $1 in
- -h|--help)
- show_help
- exit 0
- ;;
- -j|--jobs)
- if [ "$2" ]; then
- JOB_COUNT=$2
- shift
- else
- arg_error "'--jobs' requires a non-empty option argument"
- fi
- ;;
- -p|--prefix)
- if [ "$2" ]; then
- PREFIX="$2"
- shift
- else
- arg_error "'--prefix' requires a non-empty option argument"
- fi
- ;;
- --prefix=?*)
- PREFIX=${1#*=}
- ;;
- --prefix=)
- arg_error "'--prefix' requires a non-empty option argument"
- ;;
- -r|--root)
- if [ "$2" ]; then
- ROOT_PATH_ARG="$2"
- shift
- else
- arg_error "'--root' requires a non-empty option argument"
- fi
- ;;
- --root=?*)
- ROOT_PATH_ARG="${1#*=}"
- ;;
- --root=)
- arg_error "'--root' requires a non-empty option argument"
- ;;
- --keep-artifacts)
- KEEP_ARTIFACTS=1
- ;;
- --disable-threads)
- ENABLE_THREADS=""
- ;;
- --cached-sources)
- CACHED_SOURCES=1
- ;;
- --binutils-branch)
- if [ "$2" ]; then
- BINUTILS_BRANCH="$2"
- shift
- else
- arg_error "'--binutils-branch' requires a non-empty option argument"
- fi
- ;;
- --binutils-branch=?*)
- BINUTILS_BRANCH=${1#*=}
- ;;
- --binutils-branch=)
- arg_error "'--binutils-branch' requires a non-empty option argument"
- ;;
- --gcc-branch)
- if [ "$2" ]; then
- GCC_BRANCH="$2"
- shift
- else
- arg_error "'--gcc-branch' requires a non-empty option argument"
- fi
- ;;
- --gcc-branch=?*)
- GCC_BRANCH=${1#*=}
- ;;
- --gcc-branch=)
- arg_error "'--gcc-branch' requires a non-empty option argument"
- ;;
- --linked-runtime)
- if [ "$2" ]; then
- LINKED_RUNTIME="$2"
- shift
- else
- arg_error "'--linked-runtime' requires a non-empty option argument"
- fi
- ;;
- --linked-runtime=?*)
- LINKED_RUNTIME=${1#*=}
- ;;
- --linked-runtime=)
- arg_error "'--linked-runtime' requires a non-empty option argument"
- ;;
- --mingw-w64-branch)
- if [ "$2" ]; then
- MINGW_W64_BRANCH="$2"
- shift
- else
- arg_error "'--mingw-w64-branch' requires a non-empty option argument"
- fi
- ;;
- --mingw-w64-branch=?*)
- MINGW_W64_BRANCH=${1#*=}
- ;;
- --mingw-w64-branch=)
- arg_error "'--mingw-w64-branch' requires a non-empty option argument"
- ;;
- i586)
- BUILD_I586=1
- ;;
- i686)
- BUILD_I686=1
- ;;
- x86_64)
- BUILD_X86_64=1
- ;;
- --)
- shift
- break
- ;;
- -?*)
- arg_error "unknown option '$1'"
- ;;
- ?*)
- arg_error "unknown arch '$1'"
- ;;
- *)
- break
- esac
- shift
- done
- NUM_BUILDS=$((BUILD_I586 + BUILD_I686 + BUILD_X86_64))
- if [ "$NUM_BUILDS" -eq 0 ]; then
- arg_error "no ARCH was specified"
- fi
- MISSING_EXECS=""
- for exec in g++ flex bison git makeinfo m4 bzip2 curl make diff; do
- if ! command -v "$exec" >/dev/null; then
- MISSING_EXECS="$MISSING_EXECS $exec"
- fi
- done
- if [ "$MISSING_EXECS" ]; then
- error_exit "missing required executable(s):$MISSING_EXECS"
- fi
- TOTAL_STEPS=0
- if [ ! "$CACHED_SOURCES" ]; then
- TOTAL_STEPS=$((TOTAL_STEPS + 4))
- fi
- if [ "$ENABLE_THREADS" ]; then
- THREADS_STEPS=3
- else
- THREADS_STEPS=0
- fi
- THREADS_STEPS=$((THREADS_STEPS * NUM_BUILDS))
- BUILD_STEPS=$((13 * NUM_BUILDS))
- TOTAL_STEPS=$((TOTAL_STEPS + THREADS_STEPS + BUILD_STEPS))
- if [ "$ROOT_PATH_ARG" ]; then
- ROOT_PATH=$(mkdir -p "$ROOT_PATH_ARG" && cd "$ROOT_PATH_ARG" && pwd)
- fi
- SRC_PATH="$ROOT_PATH/src"
- BLD_PATH="$ROOT_PATH/bld"
- LOG_FILE="$ROOT_PATH/build.log"
- if [ "$PREFIX" ]; then
- I586_PREFIX="$PREFIX"
- I686_PREFIX="$PREFIX"
- X86_64_PREFIX="$PREFIX"
- else
- I586_PREFIX="$ROOT_PATH/i586"
- I686_PREFIX="$ROOT_PATH/i686"
- X86_64_PREFIX="$ROOT_PATH/x86_64"
- fi
- CURRENT_STEP=1
- # clean log file for execute()
- mkdir -p "$ROOT_PATH"
- rm -f "$LOG_FILE"
- touch "$LOG_FILE"
- if [ ! "$CACHED_SOURCES" ]; then
- download_sources
- else
- if [ ! -f "$SRC_PATH/config.guess" ]; then
- arg_error "no sources found, run with --keep-artifacts first"
- fi
- fi
- BUILD=$(sh "$SRC_PATH/config.guess")
- change_dir "$SRC_PATH/gcc"
- execute "" "failed to download GCC dependencies" \
- ./contrib/download_prerequisites
- for i in mpc isl mpfr gmp; do
- ln -s "$SRC_PATH/gcc/$i" "$SRC_PATH/binutils/$i"
- done
- export CFLAGS="-O2"
- export CXXFLAGS="-O2"
- export LDFLAGS="-Wl,-O1,--sort-common,--as-needed"
- ADD_TO_PATH=()
- if [ "$BUILD_I586" ]; then
- build i586 "$I586_PREFIX"
- ADD_TO_PATH+=("'$I586_PREFIX/bin'")
- fi
- if [ "$BUILD_I686" ]; then
- build i686 "$I686_PREFIX"
- ADD_TO_PATH+=("'$I686_PREFIX/bin'")
- fi
- if [ "$BUILD_X86_64" ]; then
- build x86_64 "$X86_64_PREFIX"
- ADD_TO_PATH+=("'$X86_64_PREFIX/bin'")
- fi
- if [ ! "$KEEP_ARTIFACTS" ]; then
- remove_path "$SRC_PATH"
- remove_path "$BLD_PATH"
- remove_path "$LOG_FILE"
- fi
- echo "complete, to use MinGW-w64 everywhere add these to your \$PATH:"
- for add_to_path in "${ADD_TO_PATH[@]}"; do
- printf "\t%s\n" "$add_to_path"
- done
- exit 0
|