building mingw toolchain with pthreads, gendef, widl

Questions that occur when trying to compile FFmpeg.
Post Reply
hydra3333
Posts: 123
Joined: Sun Apr 28, 2013 1:03 pm
Contact:

building mingw toolchain with pthreads, gendef, widl

Post by hydra3333 » Sat Jul 08, 2017 5:58 am

Non-linux-aware-user alert: seeking a bit of advice.

Zeranoe has a lovely new v4.0.0 mingw build script. From other places (eg deadsix27 https://github.com/DeadSix27/python_cro ... threads.sh) when using a variation of the prior mingw build script, one can build with pthreads.
Attempting to modify zeranoe's script a bit like the one attached below, fails when I change from this

Code: Select all

"$src/gcc-$v_gcc/configure" --target="$host" --disable-shared --enable-static --disable-multilib --prefix="$prefix" --enable-languages=c,c++ --disable-nls || error_exit
to this

Code: Select all

"$src/gcc-$v_gcc/configure" --target="$host" --disable-shared --enable-static --disable-multilib --prefix="$prefix" --enable-languages=c,c++ --disable-nls --with-sysroot="$prefix" --build="$build" --enable-fully-dynamic-string --enable-lto --enable-threads=posix || error_exit
The "--enable-threads=posix" causes the script to crash further down in the "building gcc compiler support library" area and the build log isn't all that informative to me (the last thing shown is a "note:" rather than an error).

Code: Select all

/home/u/Desktop/ffmpeg-windows-build-helpers-withOpenCL-master/sandbox/cross_compilers/bld/gcc/x86_64-w64-mingw32/libstdc++-v3/include/thread:284:3: note: candidate: bool std::operator<(std::thread::id, std::thread::id)
   operator<(thread::id __x, thread::id __y) noexcept
   ^~~~~~~~
/home/u/Desktop/ffmpeg-windows-build-helpers-withOpenCL-master/sandbox/cross_compilers/bld/gcc/x86_64-w64-mingw32/libstdc++-v3/include/thread:284:3: note:   no known conversion for argument 1 from 'std::thread::native_handle_type {aka ptw32_handle_t}' to 'std::thread::id'
Makefile:1736: recipe for target 'x86_64-w64-mingw32/bits/stdc++.h.gch/O2ggnu++0x.gch' failed
make[4]: *** [x86_64-w64-mingw32/bits/stdc++.h.gch/O2ggnu++0x.gch] Error 1
make[4]: *** Waiting for unfinished jobs....
Advice on what I'm doing wrong would be very much welcomed.

I suppose I could post an issue on github https://github.com/Zeranoe/mingw-w64-build but it seems better to ask here.

Updated script:

Code: Select all

#!/bin/bash
#
# Copyright (C) 2017 Kyle Schwarz
#
# 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/>.
#

v_script="4.0.0-hydra3333"
v_binutils="2.28"
v_gcc="7.1.0"
v_gmp="6.1.2"
v_mpfr="3.1.5"
v_mpc="1.0.3"
v_isl="0.18"
v_pthreads="2-9-1"

show_help()
{
  cat <<HELP
usage: mingw-w64-build [OPTION]... ARCH...
Build the MinGW-w64 toolchain for ARCH(s) (i686 or x86_64). 

  -h, --help     display this help and exit
  --version      output version information and exit

Creates directories 'src' and 'bld' in the current directory and
  removes them when complete.

examples:
  mingw-w64-build i686
  mingw-w64-build x86_64
  mingw-w64-build i686 x86_64
HELP
}

show_version()
{
  cat <<VERSION
mingw-w64-build $v_script
Copyright (C) 2017 Kyle Schwarz
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
VERSION
}

error_exit()
{
  local error_text="$1"
  shift

  if [[ -z "$error_text" ]]; then
    error_text="See 'build.log' for further details."
  fi

  echo "mingw-w64-build: error: $error_text" >&3

  exit 1
}

clean_build()
{
  local build_dir="$1"

  rm -fvr "$build_dir"
  mkdir -pv "$build_dir"
  cd "$build_dir" || error_exit  
}

download_sources()
{
  cd "$src" || error_exit

  echo "downloading mingw-w64-git" >&3
  git clone git://git.code.sf.net/p/mingw-w64/mingw-w64 "mingw-w64-git" || error_exit

  
  local urls=(
    "http://ftp.gnu.org/gnu/binutils/binutils-$v_binutils.tar.bz2"
    "http://ftp.gnu.org/gnu/gcc/gcc-$v_gcc/gcc-$v_gcc.tar.bz2"
    "http://ftp.gnu.org/gnu/gmp/gmp-$v_gmp.tar.xz"
    "http://ftp.gnu.org/gnu/mpfr/mpfr-$v_mpfr.tar.xz"
    "http://ftp.gnu.org/gnu/mpc/mpc-$v_mpc.tar.gz"
    "http://isl.gforge.inria.fr/isl-$v_isl.tar.xz"
    "http://mirrors.kernel.org/sourceware/pthreads-win32/pthreads-w32-$v_pthreads-release.tar.gz"
  )

  for url in "${urls[@]}"; do
    local archive="${url##*/}"
    local c
    echo "downloading $archive" >&3
    wget -nv "$url" || error_exit
    echo "extracting $archive" >&3
    case "${archive##*.}" in
      gz) c=z ;;
      bz2) c=j ;;
      xz) c=J ;;
    esac
    tar -x${c}f "$archive" || error_exit
  done

  cd "$src/gcc-$v_gcc" || error_exit

  ln -fsv "../gmp-$v_gmp" "gmp"
  ln -fsv "../mpfr-$v_mpfr" "mpfr"
  ln -fsv "../mpc-$v_mpc" "mpc"
  ln -fsv "../isl-$v_isl" "isl"

  patch -p 1 <<PATCH
diff -uprN a/libstdc++-v3/config/os/mingw32-w64/os_defines.h b/libstdc++-v3/config/os/mingw32-w64/os_defines.h
--- a/libstdc++-v3/config/os/mingw32-w64/os_defines.h   2017-01-01 04:07:43.000000000 -0800
+++ b/libstdc++-v3/config/os/mingw32-w64/os_defines.h   2017-05-25 18:47:52.161016148 -0700
@@ -76,6 +76,7 @@

 #ifdef __x86_64__
 #define _GLIBCXX_LLP64 1
+#define _GLIBCXX_USE_WEAK_REF 0
 #endif

 // Enable use of GetModuleHandleEx (requires Windows XP/2003) in
PATCH
}

build_toolchain()
{
  local p_arch="$1"
  local host="$1-w64-mingw32"
  local prefix="$wd/$host"
  export PATH="$prefix/bin:$PATH"
  
  #local p_arch="$1"
  #local host="$1-w64-mingw32"
  #local compatibility_host="mingw-w64-$1" # change back to the pre v4 folder structure so as to not break build scripts
  #local prefix="$wd/$compatibility_host"
  #export PATH="$prefix/bin:$PATH"

  rm -frv "$prefix"

  clean_build "$bld/binutils"
  echo "configuring binutils" >&3
  # new zeranoe:
  #"$src/binutils-$v_binutils/configure" --prefix="$prefix" --disable-shared --enable-static --with-sysroot="$prefix" --target="$host" --disable-multilib --disable-nls || error_exit
  # old zeranoe-ish:
    "$src/binutils-$v_binutils/configure" --prefix="$prefix" --disable-shared --enable-static --with-sysroot="$prefix" --target="$host" --disable-multilib  --disable-nls --build="$build" || error_exit

  echo "building binutils" >&3
  make -j $cpus || error_exit
  echo "installing binutils" >&3
  make install || error_exit

  clean_build "$bld/mingw-w64"
  echo "configuring mingw-w64-headers" >&3
  # new zeranoe:
  #"$src/mingw-w64-git/mingw-w64-headers/configure" --build="$build" --host="$host" --prefix="$prefix/$host" --enable-secure-api || error_exit
  # old zeranoe-ish:
  "$src/mingw-w64-git/mingw-w64-headers/configure" --build="$build" --host="$host" --prefix="$prefix/$host" --enable-secure-api --enable-sdk=all || error_exit
  echo "installing mingw-w64-headers" >&3
  make install || error_exit
  cd "$prefix" || error_exit
  ln -fsv "./$host" "./mingw" || error_exit
  #---------- per old zeranoe 3.6.9
  # 2017.07.05  is it missing this library re-linking ??
  if [[ ! -d "./$host/include" ]]; then
    cd "./$host" || error_exit
    ln -fsv '../include' './include' || error_exit
    cd ".." || error_exit
  fi
  #---------- per old zeranoe 3.6.9
  
  # GCC all-gcc
  clean_build "$bld/gcc"
  echo "configuring gcc all-gcc" >&3
  # new zeranoe:
  #"$src/gcc-$v_gcc/configure" --target="$host" --disable-shared --enable-static --disable-multilib --prefix="$prefix" --enable-languages=c,c++ --disable-nls || error_exit
  # old zeranoe-ish:
  "$src/gcc-$v_gcc/configure" --target="$host" --disable-shared --enable-static --disable-multilib --prefix="$prefix" --enable-languages=c,c++ --disable-nls --enable-fully-dynamic-string --enable-lto  || error_exit
  #"$src/gcc-$v_gcc/configure" --target="$host" --disable-shared --enable-static --disable-multilib --prefix="$prefix" --enable-languages=c,c++ --disable-nls --with-sysroot="$prefix" --build="$build" --enable-fully-dynamic-string --enable-lto --enable-threads=posix || error_exit
  echo "running 'make all-gcc' for gcc" >&3
  make -j $cpus all-gcc || error_exit
  echo "running 'install-gcc' for gcc" >&3
  make install-gcc || error_exit

  # CRT
  clean_build "$bld/mingw-w64" # could specify this folder if you liked "$bld/mingw-w64-crt"
  echo "configuring mingw-w64-crt" >&3
  # new zeranoe:
  "$src/mingw-w64-git/mingw-w64-crt/configure" --build="$build" --host="$host" --prefix="$prefix/$host" --with-sysroot="$prefix/$host"
  # old zeranoe-ish:
  #"$src/mingw-w64-git/mingw-w64-crt/configure" --build="$build" --host="$host" --prefix="$prefix/$host" --with-sysroot="$prefix/$host" || error_exit
  echo "building mingw-w64-crt" >&3
  make -j $cpus || error_exit
  echo "installing mingw-w64-crt" >&3
  make install || error_exit

  #---------- per old zeranoe 3.6.9
  pwd
  cd "$prefix" || print_error
  mv -vf "./$host/lib/"* './lib/'  # this commandline must be EXACTLY like this
  mv -vf "./$host/lib/*" './lib/'  # this commandline must be EXACTLY like this
  rm -frv "./$host/lib"
  cd "./$host"
  ln -fsv '../lib' './lib'  
  pwd
  #---------- per old zeranoe 3.6.9
    
 #---------- start of pthreads per old deadsix27 ----------------------------------------------------------
  echo "#---- start building pthreads (static only) " >&3
  cd "$src/pthreads-w32-$v_pthreads-release" || error_exit
  make realclean || error_exit
  make CROSS="${host}-" realclean GC-static ARCH="${p_arch} --always-make" -d || error_exit
  cp -fv 'libpthreadGC2.a' "$prefix/lib/" || error_exit
  cp -fv 'pthread.h' 'sched.h' 'semaphore.h' "$prefix/include/" || error_exit
  cp -fv 'pthread.h' 'sched.h' 'semaphore.h' "$prefix/$host/include/" || error_exit # added just to see
  ls  "$prefix/include/"
  ls  "$prefix/$host/include/"  # added just to see
  cd "$prefix/lib" || error_exit
  ln -fsv "./libpthreadGC2.a" "./libpthread.a"  || error_exit
  #
  cd "../include/" || error_exit
  file="pthread.h"
  rm -fv "$file".orig
  sed -i.orig 's/ __declspec (dllexport)//g;s/ __declspec (dllimport)//g' "$file"  || error_exit
  file="sched.h"
  rm -fv "$file".orig
  sed -i.orig 's/ __declspec (dllexport)//g;s/ __declspec (dllimport)//g' "$file"  || error_exit
  file="semaphore.h"
  rm -fv "$file".orig
  sed -i.orig 's/ __declspec (dllexport)//g;s/ __declspec (dllimport)//g' "$file"  || error_exit
  # added just to see
  cd "$prefix/$host/include/" || error_exit
  file="pthread.h"
  rm -fv "$file".orig
  sed -i.orig 's/ __declspec (dllexport)//g;s/ __declspec (dllimport)//g' "$file"  || error_exit
  file="sched.h"
  rm -fv "$file".orig
  sed -i.orig 's/ __declspec (dllexport)//g;s/ __declspec (dllimport)//g' "$file"  || error_exit
  file="semaphore.h"
  rm -fv "$file".orig
  sed -i.orig 's/ __declspec (dllexport)//g;s/ __declspec (dllimport)//g' "$file"  || error_exit
  echo "#---- finished building  pthreads (static only) " >&3
  #read -p "Press Enter to continue or control-C if not happy"
 #---------- end of pthreads per old deadsix27 ----------------------------------------------------------
  
  # GCC compiler support library
  cd "$bld/gcc" || error_exit
  echo "building gcc compiler support library" >&3
  make -j $cpus || error_exit
  echo "installing gcc compiler support library" >&3
  make install || error_exit

  #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  # 2017.06.14 gendef here like old zeranoe-ish:
    echo "#---- configuring gendef" >&3
  clean_build "$bld/gendef" || error_exit
  "$src/mingw-w64-git/mingw-w64-tools/gendef/configure" --prefix="$prefix" --target="$host" --build="$build"  || error_exit
  #"$src/mingw-w64-git/mingw-w64-tools/gendef/configure" --prefix="$prefix/$host" --target="$host" --build="$build"  || error_exit
  echo "#---- making gendef" >&3
  make -j $cpus || error_exit
  make install || error_exit
  echo "#---- END making gendef" >&3
  #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  # 2017.06.14 widl here like old zeranoe-ish:
  echo "#---- configuring widl" >&3
  clean_build "$bld/widl" || error_exit
  "$src/mingw-w64-git/mingw-w64-tools/widl/configure" --prefix="$prefix" --target="$host" --build="$build"  || error_exit
  #"$src/mingw-w64-git/mingw-w64-tools/widl/configure" --prefix="$prefix/$host" --target="$host" --build="$build"  || error_exit
  echo "#---- making widl" >&3
  make -j $cpus || error_exit
  make install || error_exit
  echo "#---- END making widl" >&3
  #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
  echo "#---- Finished build_toolchain"
  echo "#---- Finished build_toolchain" >&3  

  echo "#---- Start checking for cmath in the inlcude folder(s)"
  echo "#---- Start checking for cmath in the inlcude folder(s)" >&3  
  echo "find ../../../../ | grep 'cmath'" 
  find ../../../../ | grep 'cmath'  
  find ../../../../ | grep 'cmath' >&3
  echo "#---- End checking for cmath in the inlcude folder(s)"
  echo "#---- End checking for cmath in the inlcude folder(s)" >&3  

  return 0
}

while :; do
  case $1 in
    -h|--help)
      show_help
      exit
      ;;
    --version)
      show_version
      exit
      ;;
    -?*)
      echo "mingw-w64-build: error: unknown option: '$1'" >&2
      exit
      ;;
    *)
      break
  esac

  shift
done

if [[ "$PWD" = *" "* ]]; then
  echo "mingw-w64-build: error: working path contains spaces" >&2
  exit 1
fi

if [[ -z "[email protected]" ]]; then
  echo "mingw-w64-build: error: missing ARCH option" >&2
  echo "See 'mingw-w64-build --help' for build options." >&2
  exit 1
fi

for arch in [email protected]; do
  if [[ "$arch" != "i686" ]] && [[ "$arch" != "x86_64" ]]; then
    echo "mingw-w64-build: error: invalid ARCH: '$arch'" >&2
    exit 1
  fi
done

progs=(
  "wget"
  "gzip"
  "bzip2"
  "xz"
  "git"
  "make"
  "patch"
  "g++"
  "tr"
  "tar"
)
missing_progs=""
for prog in "${progs[@]}"; do
  if ! command -v $prog >/dev/null; then
    missing_progs="$prog $missing_progs"
  fi
done
if [[ -n "$missing_progs" ]]; then
  echo "mingw-w64-build: missing required program(s): $missing_progs" >&2
  exit 1
fi

cpus=$(grep -c processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu | tr -d "\n" 2>/dev/null)
build=$(wget -qO - "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD" | sh)
wd="$PWD"
src="$wd/src"
bld="$wd/bld"
log="$wd/bld/build.log"

# for the time being, keep the src and bld folders 
#rm -frv "$log" "$src" "$bld"
rm -frv "$log" 
mkdir -pv "$wd/bld" "$wd/src"
download_sources 3>&1 1>>"$log" 2>&1

for arch in [email protected]; do
  # add arch to the log filename
  log="$wd/bld/build_${arch}.log"
  build_toolchain "$arch" 3>&1 1>>"$log" 2>&1
done
#rm -frv "$wd/bld" "$wd/src"
#rm -frv "$wd/bld"

exit 0

User avatar
Zeranoe
Site Admin
Posts: 644
Joined: Sat May 07, 2011 7:12 pm
Contact:

Re: building mingw toolchain with pthreads, gendef, widl

Post by Zeranoe » Sun Jul 09, 2017 6:15 pm

This looks like MSYS which hasn't been tested and isn't supported.

hydra3333
Posts: 123
Joined: Sun Apr 28, 2013 1:03 pm
Contact:

Re: building mingw toolchain with pthreads, gendef, widl

Post by hydra3333 » Mon Jul 10, 2017 11:29 am

OK. Here's a thing though ... mingw builds with pthreads OK using a variation of the "old" zeranoe mingw build script, but I can't figure why out it does and the "new v4.0.0" doesn't except to suggest maybe it seems to be due to the "new" path structures ?

In theory, there's no difference in the software being downloaded and built by the old and v4.0.0, only in the path structures and in the configured/build statements.

Here's the hacked zeranoe script which builds "OK with pthreads" (yes it isn't right with leftovers from tinkering, but it does build), called like this:

Code: Select all

--clean-build --disable-shared --default-configure --pthreads-w32-ver=2-9-1 --cpu-count=$gcc_cpu_count --mingw-w64-ver=git --gcc-ver=7.1.0 --deadsix27_patching=n --build-type=win64 --enable-gendef

Code: Select all

#!/bin/bash
script_ver='3.6.9' # based on rdp's 3.6.7 plus deadsix27's weak refs patch for GCC 6.3.0.
# local version: 4 and a bit
################################################################################
# MingGW-w64 Build Script
################################################################################
# Copyright (C) 2011-2015  Kyle Schwarz
... GPL statement removed solely so that it fits into one forum post.
################################################################################

about () {
clear
read -p \
"################################################################################
#                                                                              #
#                        MingGW-w64 Build Script $script_ver                         #
#                                                                              #
#                                                                              #
#            This script will build MinGW-w64 for Win32 and Win64.             #
#                                                                              #
#      This version will build the following packages into the toolchain       #
#                                                                              #
#          mingw-w64                        gmp                                #
#                                                                              #
#          mpfr                             mpc                                #
#                                                                              #
#          isl                              cloog                              #
#                                                                              #
#          binutils                         gcc                                #
#                                                                              #
#                                                                              #
#                            Press Enter to continue                           #
#                                                                              #
#                     Copyright (C) 2011-1015 Kyle Schwarz                     #
#                This program comes with ABSOLUTELY NO WARRANTY                #
#                                                                              #
################################################################################"
}

# Variables
build_type=""
working_dir="$(pwd)"
detected_cpu_count="$(grep -c processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu | tr -d '\n' 2>/dev/null)"
uname_m="$(uname -m)"
target_i686='i686-w64-mingw32'
target_x86_64='x86_64-w64-mingw32'

## Versions
#mingw_w64_release_ver='5.0.1' # or git :)
#gcc_release_ver='6.3.0' # 6.1.0 has problems with 64 bit ffmpeg with c++ deps
#gcc_old_release_ver='4.9.4' # default if none specified, was 4.9.4 cannot be same as gcc_release_ver above, apparently, as a note...
#mpfr_release_ver='3.1.3'
#mpc_release_ver='1.0.3'
#binutils_release_ver='2.27'
#gmp_release_ver='6.1.1'
#isl_release_ver='0.16.1'
#pthreads_w32_release_ver='2-9-1'
#----- # 2017.04.11 updates :
# refer 
# 0. http://mingw-w64.org/doku.php and v5.0.2 https://sourceforge.net/p/mingw-w64/mailman/message/35754067/
# 1. gcc 6.3.0 patch - weak ref patch, see https://github.com/Alexpux/MINGW-packages/issues/1580
#    https://github.com/rdp/ffmpeg-windows-build-helpers/issues/211#issuecomment-285759753
# 2. updates per https://github.com/DeadSix27/python_cross_compile_script/blob/dev/mingw-build-script.sh
#mingw_w64_release_ver='5.0.1' # or git :) #mingw_w64_ver='git'
#mingw_w64_release_ver='5.0.2' # or git :) #mingw_w64_ver='git'
mingw_w64_release_ver='5.0.2'
gcc_release_ver='7.1.0' # 6.1.0 has problems with 64 bit ffmpeg with c++ deps
#gcc_old_release_ver='4.9.4' # default if none specified, was 4.9.4 cannot be same as gcc_release_ver above, apparently, as a note...
gcc_old_release_ver='6.3.0' # default if none specified, was 4.9.4 cannot be same as gcc_release_ver above, apparently, as a note...
#mpfr_release_ver='3.1.3'
mpfr_release_ver='3.1.5'
mpc_release_ver='1.0.3'
#binutils_release_ver='2.27'
binutils_release_ver='2.28'
#gmp_release_ver='6.1.1'
gmp_release_ver='6.1.2'
#isl_release_ver='0.16.1'
isl_release_ver='0.18'
pthreads_w32_release_ver='2-9-1'

do_deadsix27_patching=n

## Locations
mingw_w64_source_dir="$working_dir/source"
mingw_w64_build_dir="$working_dir/build"
pkgs_dir="$working_dir/pkgs"

## Prefixes
mingw_w64_i686_prefix="$working_dir/mingw-w64-i686"
mingw_w64_x86_64_prefix="$working_dir/mingw-w64-x86_64"

display_help () {
cat <<EOF
Compile MinGW-w64 as a cross-toolchain for Win32 or Win64

Run options other than compiling (./mingw-w64-build-$script_ver OPTION):
  wipe    removes all MinGW-w64 files in the directory (build build_$build_type.log 
          mingw-w64-i686 mingw-w64-x86_64 pkgs source)

Available options are specified in parentheses.

Defaults for the options are specified in brackets.

General:
  -h, --help     display this help and exit
  -a, --about    display the "About" page
  -V, --version  display version information and exit

Compile Options:
  --build-type=TYPE           compile for TYPE (win32, win64, multi)
  --default-configure         compile with default options for all unset options
  --allow-overwrite           allow overwrite if no updates are found
  --rebuild-all               rebuild all packages
  --mingw-w64-ver=NUMBER      compile with MinGW-w64 VERSION ($mingw_w64_release_ver, git)
                              [$mingw_w64_release_ver]
  --cpu-count=NUMBER          use NUMBER of cores/threads to compile with (1-$detected_cpu_count,
                              max) [max]
  --binutils-ver=VERSION      compile with binutils VERSION ($binutils_release_ver, git)
                              [$binutils_release_ver]
  --gcc-ver=VERSION           compile with GCC VERSION ($gcc_release_ver, $gcc_old_release_ver, svn)
                              [$gcc_old_release_ver]
  --pthreads-w32-ver=VERSION  compile with Pthreads-w32 VERSION ($pthreads_w32_release_ver, cvs)
                              [cvs]
  --gcc-langs=LANG1,LANG2     compile GCC with support for LANG (ada, c, c++,
                              fortran, go, java, objc, obj-c++, all) [c,c++,lto]
  --enable-nls                enable "Native Language Support"
  --disable-shared            compile a static only toolchain
  --threads=LIB               compile with support for thread LIB (winpthreads,
                              pthreads-w32, disable) [pthreads-w32]
  --clean-build               remove the unneeded directories after a successful
                              compile, leaving only the built toolchain. The 
                              'build', 'source', and 'packages' directories will
                              be removed. 
  --enable-gendef             compile the MinGW-w64 tools gendef.
  --enable-widl               compile the Mingw-w64 tools widl
  --verbose                   show raw build output
  --deadsix27_patching=y/n    apply deadsix27 dx patches, default=n

Report bugs to <[email protected]>.
EOF
}

print_error ()
{
  printf 'error\n\nSee build_$build_type.log for more details.\n'
  exit 1
}

yes_no_sel () {
local usr_input
local question="$1"
shift
while [[ "$usr_input" != [YyNn] ]]; do
  printf '%s [y/n]: ' "$question"
  read usr_input
  if [[ "$usr_input" != [YyNn] ]]; then
    printf '\nYour selection was not vaild, please try again.\n\n'
  fi
done
case "$usr_input" in
  [Yy] ) return 0 ;;
  [Nn] ) return 1 ;;
esac
}

var_in_array() {
local var=$1
local array
shift
for array; do
  [[ $var = "$array" ]] && return
done
return 1
}

create_pkg_dirs () {
local pkg_name="$1"
mkdir -p "$pkg_name"
cd "$pkg_name" || print_error
mkdir -p 'build' 'source'
cd 'source' || print_error
}

use_cpu_count () {
if [[ "$cpu_count" -ge '2' ]]; then
  while [[ "$select_cpu_count" != [1-$cpu_count] ]]; do
    printf '\nA total of %d cores/threads were found. How many would you like to use to compile MinGW-w64? You can set this option with: "--cpu-count=NUMBER", see --help for more information. [1-%d]: ' "$detected_cpu_count" "$detected_cpu_count"
    read select_cpu_count
  done
  cpu_count="$select_cpu_count"
fi

if [[ "$cpu_count" -lt '1' ]]; then
  if yes_no_sel 'The number of cores/threads could not be found, would you like to manually enter the number of cores/threads your CPU has? (If "n" is selected, one core/thread will be used).'; then
    printf '\nPlease enter the number of cores/threads your CPU has. (Make sure the number you enter is correct, trying to use more cores/threads than your CPU has can cause your system to crash).: '
    read cpu_count
  else
    cpu_count='1'
  fi
fi
}

pkg_touch_success () {
local pkg_name="$1"
local pkg_ver="$2"
local pkg_state="$3"
local pkg_arch="$4"
shift 4
mkdir -p "$pkgs_dir/touch-files/$pkg_name"
touch "$pkgs_dir/touch-files/$pkg_name/$pkg_name-$pkg_ver-$pkg_arch.$pkg_state"
}

check_pkg_touch_success () {
local pkg_name="$1"
local pkg_ver="$2"
local pkg_state="$3"
local pkg_arch="$4"
shift 4

if [[ -f "$pkgs_dir/touch-files/$pkg_name/$pkg_name-$pkg_ver-$pkg_arch.$pkg_state" ]]; then
  return 0
fi
return 1
}

build_progress ()
{
if [[ "$verbose" != 'yes' ]]; then
  if [[ "$1" = 'done' ]]; then
    printf '%s\n' "$1"
    return 0
  fi

  local step_function="$1"
  local step_name="$2"
  shift 2
 
  printf '[%d/%d]: %s %s... ' "$current_step" "$total_steps" "$step_name" "$step_function"
  ((current_step++))
fi
}

build_log ()
{  
  if [[ "$verbose" = 'yes' ]]; then
    tee -a "$working_dir/build_$build_type.log"
  else
    cat >>"$working_dir/build_$build_type.log"
  fi
}

choose_mingw_w64_ver () {
while [[ "$mingw_w64_ver_select" != [1-2] ]]; do
cat <<EOF

Which MinGW-w64 version would you like to build? You can set this option with: '--mingw-w64-ver=NUMBER', see --help for more information.
  1. MinGW-w64 $mingw_w64_release_ver (default)
  2. MinGW-w64 git
EOF
printf 'Choose which MinGW-w64 version would would like to build. [1-2]: '
read mingw_w64_ver_select
case "$mingw_w64_ver_select" in
  1 ) mingw_w64_ver="$mingw_w64_release_ver" ;;
  2 ) mingw_w64_ver='git' ;;
  * ) printf '\nYour selection was not valid, please try again.\n\n' ;;
esac
done
}

choose_binutils_ver () {
while [[ "$binutils_ver_select" != [1-3] ]]; do
cat <<EOF

Which Binutils version would you like to build? You can set this option with: '--binutils-ver=VERSION', see --help for more information.
  1. Binutils $binutils_release_ver (default)
  2. Binutils git 
EOF
printf 'Choose which Binutils version would would like to build. [1-2]: '
read binutils_ver_select
case "$binutils_ver_select" in
  1 ) binutils_ver="$binutils_release_ver" ;;
  2 ) binutils_ver='git' ;;
  * ) printf '\nYour selection was not valid, please try again.\n\n' ;;
esac
done
}

choose_gcc_ver () {
while [[ "$gcc_ver_select" != [1-4] ]]; do
cat <<EOF

Which GCC version would you like to build? You can set this option with: '--gcc-ver=VERSION', see --help for more information.
  1. GCC $gcc_release_ver (default)
  2. GCC $gcc_release_ver
  3. GCC $svn
EOF
printf 'Choose which GCC version would would like to build. [1-3]: '
read gcc_ver_select
case "$gcc_ver_select" in
  1 ) gcc_ver="$gcc_release_ver" ;;
# always force last version
#  2 ) gcc_ver="$gcc_old_release_ver" ;;
  2 ) gcc_ver="$gcc_release_ver" ;;
  3 ) gcc_ver='svn' ;;
  * ) printf '\nYour selection was not valid, please try again.\n\n' ;;
esac
gcc_ver="$gcc_release_ver"
done
}

configure_gcc () {
if [[ "$enabled_langs" != *,* ]]; then
  printf -v enabled_langs '%s,' "${enabled_langs[@]}"
  enabled_langs="${enabled_langs%,}"
fi

echo "Should be choosing to configure gcc with NEW - lets see how it goes"
#case "$gcc_ver" in
#  $gcc_release_ver )     echo "#gcc_ver = gcc_release_ver = ${gcc_ver} so doing gcc-${gcc_ver}/configure based on NEW" ;;
#  $gcc_old_release_ver ) echo "#gcc_ver = gcc_old_release_ver = ${gcc_ver} so doing gcc-${gcc_ver}/configure based on OLD" ;;
#esac
#case "$gcc_ver" in
#  $gcc_old_release_ver ) "../source/gcc-$gcc_ver/configure" --build="$system_type" --target="$mingw_w64_target" "${static_build[@]}" "${disable_nls[@]}" --disable-multilib --prefix="$mingw_w64_prefix" --with-sysroot="$mingw_w64_prefix" --with-mpc="$mpc_prefix" --with-mpfr="$mpfr_prefix" --with-gmp="$gmp_prefix" --with-host-libstdcxx="-lstdc++" --with-cloog="$cloog_prefix" --with-isl="$isl_prefix" --enable-languages="$enabled_langs" --enable-fully-dynamic-string --enable-lto  > >(build_log) 2>&1 ;;
#  $gcc_release_ver ) "../source/gcc-$gcc_ver/configure" --build="$system_type" --target="$mingw_w64_target" "${static_build[@]}" "${disable_nls[@]}" --disable-multilib --prefix="$mingw_w64_prefix" --with-sysroot="$mingw_w64_prefix" --with-mpc="$mpc_prefix" --with-mpfr="$mpfr_prefix" --with-gmp="$gmp_prefix" --with-isl="$isl_prefix" --enable-languages="$enabled_langs" --enable-fully-dynamic-string --enable-lto  > >(build_log) 2>&1 || print_error ;;
#esac
echo "#gcc_ver = gcc_release_ver = ${gcc_ver} so doing gcc-${gcc_ver}/configure based on NEW"
"../source/gcc-$gcc_ver/configure" --build="$system_type" --target="$mingw_w64_target" "${static_build[@]}" "${disable_nls[@]}" --disable-multilib --prefix="$mingw_w64_prefix" --with-sysroot="$mingw_w64_prefix" --with-mpc="$mpc_prefix" --with-mpfr="$mpfr_prefix" --with-gmp="$gmp_prefix" --with-host-libstdcxx="-lstdc++" --with-cloog="$cloog_prefix" --with-isl="$isl_prefix" --enable-languages="$enabled_langs" --enable-fully-dynamic-string --enable-lto  > >(build_log) 2>&1

}

choose_static_build () {
if yes_no_sel "Would you like to build a fully static build? You can set this option with: '--disable-shared', see --help for more information. (Select \"n\" if you are not sure, \"n\" is the default)."; then
  static_build=('--disable-shared' '--enable-static')
else
  static_build=('--enable-shared' '--disable-static')
fi
}

choose_disable_nls () {
if yes_no_sel "Would you like to disable NLS support? Native Language Support (NLS), which lets GCC/Binutils output diagnostics in languages other than American English. You can set this option with: '--disable-nls', see --help for more information. (Select \"y\" if you are not sure, \"y\" is the default)."; then
  disable_nls=('--disable-nls')
else
  disable_nls=('--enable-nls')
fi
}

choose_lang_sel () {
if yes_no_sel "Would you like to manualy configure which languages GCC will support? You can set this option with: '--gcc-langs=LANG1,LANG2', see --help for more information. (if \"n\" is input only C and C++ will be enabled)."; then
  set_langs
else
  enabled_langs=('c' 'c++')
fi
}

set_langs () {
all_langs=('ada' 'c' 'c++' 'fortran' 'go' 'java' 'objc' 'obj-c++')
formated_langs=('Ada' 'C' 'C++' 'Fortran' 'Go' 'Java' 'Objective-C' 'Objective-C++')

cat <<'EOF'
Choose which languages you would like GCC to support.
  1. C and C++ (default)
  2. All detected
  3. Manually choose for each language.
EOF
printf 'Input your choice [1-3]: '
read sel_set_langs
case "$sel_set_langs" in
  1 ) enabled_langs=('c' 'c++')
      clear
      confirm_langs ;;
  2 ) enabled_langs=('all')
      clear
      confirm_langs ;;
  3 ) custom_langs ;;
  * ) printf '\nYour selection was not vaild, please try again.\n\n'
      set_langs
esac
}

custom_langs () {
unset enabled_langs
local num='0'
for lang in "${formated_langs[@]}"; do
  if yes_no_sel "Would you like to build GCC with $lang support?"; then
    enabled_langs=("${enabled_langs[@]}" "${all_langs[$num]}")
  fi
  ((num++))
done
confirm_langs
}

confirm_langs () {
if [[ "$enabled_langs" = 'all' ]]; then
  printf 'GCC will attempt to detect and build all of the following languages. It will silently disable the languages it can not find. (A "*" indicates that GCC will attempt to support the language).\n'
else
  printf 'The following languages will be supported in GCC. If one of the selected languages can not be found on your system when GCC is built it will fail and you will need to rerun this script after you have installed the failed language. (A "*" indicates that GCC will support the language).\n'
fi

local num='0'
for lang in "${all_langs[@]}"; do
  if var_in_array "$lang" "${enabled_langs[@]}" || [[ "${enabled_langs}" = 'all' ]]; then
    printf '  [*] %s\n' "${formated_langs[$num]}"
    printf '  [ ] %s\n' "${formated_langs[$num]}"
  fi
  ((num++))
done

printf 'Are the languages selected correct? (if "n" is selected, you will be allowed to reconfigure you language selection). [y/n]: '
read user_input
case "$user_input" in
  [Nn] ) clear
         unset enabled_langs
         set_langs ;;
  [Yy] ) ;;
  *    ) printf '\nYour selection was not valid, please try again.\n\n'
         confirm_langs ;;
esac
}

configure_build_fn () {
if yes_no_sel 'Would you like to manually choose which package versions to build into MinGW-w64 yourself, and configure the build?'; then
  if [[ -z "$mingw_w64_ver" ]]; then
    choose_mingw_w64_ver
  fi
  if [[ -z "$binutils_ver" ]]; then
    choose_binutils_ver
  fi
  if [[ -z "$gcc_ver" ]]; then
    choose_gcc_ver
  fi
  if [[ -z "$static_build" ]]; then
    choose_static_build
  fi
  if [[ -z "$disable_nls" ]]; then
    choose_disable_nls
  fi
  if [[ -z "$enabled_langs" ]]; then
    choose_lang_sel
  fi
  default_configure
else
  default_configure
fi
}

default_configure () {
default_config='yes'
if [[ -z "$mingw_w64_ver" ]]; then
  mingw_w64_ver="$mingw_w64_release_ver"
fi
if [[ -z "$binutils_ver" ]]; then
  binutils_ver="$binutils_release_ver"
fi
if [[ -z "$gcc_ver" ]]; then
  #gcc_ver="$gcc_old_release_ver"
  gcc_ver="$gcc_release_ver"
  echo "defaulting gcc_ver =  NEW ${gcc_ver}"
fi
if [[ -z "$disable_nls" ]]; then
  disable_nls=('--disable-nls')
fi
if [[ -z "$enabled_langs" ]]; then
  enabled_langs=('c' 'c++')
fi
if [[ -z "$thread_lib" ]]; then
  thread_lib='pthreads-w32'
fi
if [[ -z "$cpu_count" ]]; then
  cpu_count="$detected_cpu_count"
fi
}

download_extract () {
local download_urls=("$1" "$2")
shift 2 


for download_url in "${download_urls[@]}"; do
archive="${download_url##*/}"
package_name="${archive%.tar*}"
if [[ -d "$package_name" ]]; then
  return 0
fi

case "$archive" in
  *.tar.gz ) archive_type='gzip' ;;
  *.tar.bz2 ) archive_type='bzip2' ;;
  *.tar.xz ) archive_type='xz' ;;
esac
if [[ ! -f "$archive" ]]; then
  build_progress "$archive" 'Downloading'
  (wget -nv -t 5 "$download_url" > >(build_log) 2>&1) || (wget -nv -t 5 "$download_url" > >(build_log) 2>&1) || exit "unable to download $download_url"
  if [[ -f "$archive" ]]; then
    build_progress 'done'
  else
    exit 1
  fi
fi

if [[ ! -d "$package_name" ]]; then
  build_progress "$archive" 'Extracting'
  if "$archive_type" -d <"$archive" | pax -r ; then
    build_progress 'done'
    return 0
  else
    rm -rf "$archive" "$package_name"
    build_progress "$archive" 'Downloading'
    wget -nv "$download_url" > >(build_log) 2>&1
    build_progress 'done'
    build_progress "$archive" 'Extracting'
    "$archive_type" -d <"$archive" | pax -r
    build_progress 'done'
  fi
fi
done

if [[ ! -d "$package_name" ]]; then
  print_error
fi
}

clean_build () {
cd '..'
rm -fr 'build' || print_error
mkdir -p 'build'
cd 'build' || print_error
}

git_dl () {
local pkg="$1"
local git_url="$2"
shift 2

if cd "$pkg" 2>/dev/null; then
  read -r _ orig_git_commit < <(git log --date=iso | head -1)
  git pull> >(build_log) 2>&1 || print_error
  read -r _ git_commit < <(git log --date=iso | head -1)
  if [[ "$allow_overwrite" != 'yes' && "$orig_git_commit" = "$git_commit" &&  "$prefix_present" = 'yes' ]]; then
    if ! yes_no_sel "$pkg is already the latest version, continue with the build anyway?"; then
      exit 0
    fi
  fi
else

  build_progress "$pkg" 'Downloading'
  echo "git cloning ${git_url}"
  git clone "$git_url" "$pkg-git" > >(build_log) 2>&1 || print_error
  build_progress 'done'
fi
}

build_winpthreads () {
cd "$mingw_w64_build_dir" || print_error
rm -fr 'winpthreads '
mkdir -p 'winpthreads'
cd 'winpthreads' || print_error
local mingw_w64_target="$1"
local mingw_w64_prefix="$2"
shift 3
build_progress 'winpthreads' 'Configuring'
"../../source/mingw-w64-$mingw_w64_ver/mingw-w64-libraries/winpthreads/configure" --build="$system_type" --host="$mingw_w64_target" "${static_build[@]}" --prefix="$mingw_w64_prefix" > >(build_log) 2>&1 || print_error
build_progress 'done'

build_progress 'winpthreads' 'Building'
make > >(build_log) 2>&1 || print_error
build_progress 'done'

build_progress 'winpthreads' 'Installing'
make install > >(build_log) 2>&1 || print_error
build_progress 'done'
}

build_binutils () {
cd "$pkgs_dir" || print_error
create_pkg_dirs 'binutils' || print_error
if [[ "$binutils_ver" != 'git' ]]; then
  download_extract "https://ftp.gnu.org/gnu/binutils/binutils-$binutils_ver.tar.bz2" "ftp://ftp.gnu.org/gnu/binutils/binutils-$binutils_ver.tar.bz2"
else
  git_dl "binutils" "git://sourceware.org/git/binutils-gdb.git"
fi

cd '../build' || print_error

mkdir -p "$mingw_w64_target"
cd "$mingw_w64_target" || print_error

if ! check_pkg_touch_success 'binutils' "$binutils_ver" 'configure' "$mingw_w64_target"; then
  cd '..'
  rm -rf "$mingw_w64_target" || print_error
  mkdir "$mingw_w64_target"
  cd "$mingw_w64_target" || print_error
  build_progress 'binutils' 'Configuring'
  echo -- hello3 CC=gcc "../../source/binutils-$binutils_ver/configure" --build="$system_type" --target="$mingw_w64_target" "${static_build[@]}" "${disable_nls[@]}" --disable-multilib --with-sysroot="$mingw_w64_prefix" --prefix="$mingw_w64_prefix" > >(build_log) 2>&1
  CC=gcc "../../source/binutils-$binutils_ver/configure" --build="$system_type" --target="$mingw_w64_target" "${static_build[@]}" "${disable_nls[@]}" --disable-multilib --with-sysroot="$mingw_w64_prefix" --prefix="$mingw_w64_prefix" > >(build_log) 2>&1 || print_error
  build_progress 'done'
fi
pkg_touch_success 'binutils' "$binutils_ver" 'configure' "$mingw_w64_target"
if ! check_pkg_touch_success 'binutils' "$binutils_ver" 'compile' "$mingw_w64_target"; then
  build_progress 'binutils' 'Building'  
  make -j "$cpu_count" > >(build_log) 2>&1 || print_error
  build_progress 'done'
fi
pkg_touch_success 'binutils' "$binutils_ver" 'compile' "$mingw_w64_target"
build_progress 'binutils' 'Installing'  
make install > >(build_log) 2>&1 || print_error
build_progress 'done'
}

std_compile ()
{
  local pkg="$1"
  local ver="$2"
  local url="$3"
  shift 3

  if check_pkg_touch_success "$pkg" "$ver" 'install' "$uname_m"; then
    return
  fi

  cd "$pkgs_dir" || print_error
  create_pkg_dirs "$pkg" || print_error

  download_extract "$url"

  if ! check_pkg_touch_success "$pkg" "$ver" 'configure' "$uname_m"; then
    clean_build
    build_progress "$pkg" 'Configuring'
    [email protected] > >(build_log) 2>&1 || print_error
    build_progress 'done'
  fi
  pkg_touch_success "$pkg" "$ver" 'configure' "$uname_m"

  if ! check_pkg_touch_success "$pkg" "$ver" 'compile' "$uname_m"; then
    build_progress "$pkg" 'Building'
    make -j "$cpu_count" > >(build_log) 2>&1 || print_error
    build_progress 'done'
  fi
  pkg_touch_success "$pkg" "$ver" 'compile' "$uname_m"

  if ! check_pkg_touch_success "$pkg" "$ver" 'install' "$uname_m"; then
    build_progress "$pkg" 'Installing'
    make install > >(build_log) 2>&1 || print_error
    build_progress 'done'
  fi
  pkg_touch_success "$pkg" "$ver" 'install' "$uname_m"
}
std_compile_again () {
  local pkg="$1"
  local ver="$2"
  local url="$3"
  shift 3

  if check_pkg_touch_success "$pkg" "$ver" 'install_again' "$uname_m"; then
    return
  fi

  cd "$pkgs_dir" || print_error
  create_pkg_dirs "$pkg" || print_error

  #download_extract "$url"

  if ! check_pkg_touch_success "$pkg" "$ver" 'configure_again' "$uname_m"; then
    clean_build
    build_progress "$pkg" 'Configuring'
    [email protected] > >(build_log) 2>&1 || print_error
    build_progress 'done'
  fi
  pkg_touch_success "$pkg" "$ver" 'configure_again' "$uname_m"

  if ! check_pkg_touch_success "$pkg" "$ver" 'compile_again' "$uname_m"; then
    build_progress "$pkg" 'Building'
    make -j "$cpu_count" > >(build_log) 2>&1 || print_error
    build_progress 'done'
  fi
  pkg_touch_success "$pkg" "$ver" 'compile_again' "$uname_m"

  if ! check_pkg_touch_success "$pkg" "$ver" 'install_again' "$uname_m"; then
    build_progress "$pkg" 'Installing'
    make install > >(build_log) 2>&1 || print_error
    build_progress 'done'
  fi
  pkg_touch_success "$pkg" "$ver" 'install_again' "$uname_m"
}

build_mingw_w64 () {
local mingw_w64_target="$1"
local mingw_w64_prefix="$2"

# 2017.04.11 patch per https://github.com/rdp/ffmpeg-windows-build-helpers/issues/211#issuecomment-290362233
#                  and https://github.com/DeadSix27/python_cross_compile_script/blob/dev/mingw-build-script.sh
if [[ "${gcc_ver}" == "6.3.0" || "${gcc_ver}" == "7.1.0" ]]; then # We only support 6.3.0, patch the directx headers to work with vlc snd possibly other things, credits to: https://github.com/Alexpux/MINGW-packages/tree/master/mingw-w64-headers-git for the patches.
    echo "PASSED test gcc_ver == 6.3.0 || gcc_ver == 7.1.0 at value gcc_ver=\"${gcc_ver}\""
    if [[ $do_deadsix27_patching == "y" ]]; then
      echo "Passed test do_deadsix27_patching == y at value=$\"{do_deadsix27_patching}\""
	   cd "mingw-w64-$mingw_w64_ver"
	   echo "Patching mingw headers per deadsix27"
	   set -x
	   pwd
	   curl -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' -H 'Cache-Control: max-age=0' --retry 5 "https://raw.githubusercontent.com/hydra3333/ffmpeg-windows-build-helpers-withOpenCL/master/mingw_build_scripts/patches/0003-dxgi-Add-missing-dxgi-1.2-structs-and-interfaces.patch" -O --fail || exit 1
	   curl -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' -H 'Cache-Control: max-age=0' --retry 5 "https://raw.githubusercontent.com/hydra3333/ffmpeg-windows-build-helpers-withOpenCL/master/mingw_build_scripts/patches/0004-d3d11-Add-missing-d3d11-1.1-structs-and-interfaces.patch" -O --fail || exit 1
	   curl -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' -H 'Cache-Control: max-age=0' --retry 5 "https://raw.githubusercontent.com/hydra3333/ffmpeg-windows-build-helpers-withOpenCL/master/mingw_build_scripts/patches/0005-bessel_complex.patch" -O --fail || exit 1
	   curl -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' -H 'Cache-Control: max-age=0' --retry 5 "https://raw.githubusercontent.com/hydra3333/ffmpeg-windows-build-helpers-withOpenCL/master/mingw_build_scripts/patches/0006-processor_format.patch" -O --fail || exit 1
	   echo "applying patch 0003-dxgi-Add-missing-dxgi-1.2-structs-and-interfaces.patch"
	   patch -p1 < "0003-dxgi-Add-missing-dxgi-1.2-structs-and-interfaces.patch"
	   echo "applying patch 0004-d3d11-Add-missing-d3d11-1.1-structs-and-interfaces.patch"
	   patch -p1 < "0004-d3d11-Add-missing-d3d11-1.1-structs-and-interfaces.patch"
	   echo "applying patch 0005-bessel_complex.patch"
	   patch -p1 < "0005-bessel_complex.patch"
	   echo "applying patch 0006-processor_format.patch"
	   patch -p1 < "0006-processor_format.patch"
	   set +x
	   echo "Done"
	   #read -p "Press Enter to continue... or control-C if not happy"
	   cd ..
    else
       echo "Failed test do_deadsix27_patching == y at value=${do_deadsix27_patching}"
	fi
else
    echo "Failed test gcc_ver == 6.3.0 || gcc_ver == 7.1.0 at value gcc_ver=\"${gcc_ver}\""
    exit 1
fi
shift 2
if [[ "$rebuild" = 'yes' ]]; then
  rm -rf "$pkgs_dir/touch-files"
fi
cd "$working_dir" || print_error
rm -fr "$mingw_w64_prefix"
cd 'pkgs' || print_error
mkdir -p 'touch-files'

build_binutils

export PATH="$mingw_w64_prefix/bin:$PATH"
cd "$mingw_w64_build_dir" || print_error
clean_build
mkdir -p 'headers' 'crt'
cd 'headers' || print_error

build_progress 'mingw-w64 headers' 'Configuring'
"$mingw_w64_source_dir/mingw-w64-$mingw_w64_ver/mingw-w64-headers/configure" --enable-sdk=all --build="$system_type" --host="$mingw_w64_target" --prefix="$mingw_w64_prefix" > >(build_log) 2>&1 || print_error
build_progress 'done'

build_progress 'mingw-w64 headers' 'Installing'
make install > >(build_log) 2>&1 || print_error
build_progress 'done'

cd "$mingw_w64_prefix" || print_error
ln -s "./$mingw_w64_target" './mingw'
if [[ ! -d "./$mingw_w64_target/include" ]]; then
  cd "./$mingw_w64_target" || print_error
  ln -s '../include' './include'
  cd "$mingw_w64_prefix" || print_error
fi

case "$gcc_ver" in
  $gcc_release_ver ) isl_ver="$isl_release_ver" ;;
  "svn" ) isl_ver="$isl_release_ver" ;;
  #$gcc_old_release_ver ) isl_ver='0.12.2'; cloog_ver='0.18.1';  cloog_prefix="$pkgs_dir/cloog/cloog-$cloog_ver-$uname_m" ;;
  * )  isl_ver="$isl_release_ver" ;;
esac
case "$gcc_ver" in
  $gcc_release_ver ) echo "NEW gcc_ver=${gcc_ver} isl_ver=${isl_ver}" ;;
  "svn" ) echo "SVN NEW gcc_ver=${gcc_ver} isl_ver=${isl_ver}" ;;
  #$gcc_old_release_ver ) echo "OLD gcc_ver=${gcc_ver} isl_ver=${isl_ver}" ;;
  * ) echo "NEW gcc_ver=${gcc_ver} isl_ver=${isl_ver}" ;;
esac

mpfr_prefix="$pkgs_dir/mpfr/mpfr-$mpfr_release_ver-$uname_m"
mpc_prefix="$pkgs_dir/mpc/mpc-$mpc_release_ver-$uname_m"
isl_prefix="$pkgs_dir/isl/isl-$isl_ver-$uname_m"
gmp_prefix="$pkgs_dir/gmp/gmp-$gmp_release_ver-$uname_m"

if [[ -n $CC ]]; then
  old_cc="$CC"
  export CC=gcc
fi

# Build gmp
# 2017.04.29 gmplib.org is down, get it from 
#std_compile 'gmp' "$gmp_release_ver" "https://gmplib.org/download/gmp/gmp-$gmp_release_ver.tar.xz" "../source/gmp-$gmp_release_ver/configure" --build="$system_type" --prefix="$gmp_prefix" --enable-fat --enable-static --enable-cxx CPPFLAGS='-fexceptions'
std_compile 'gmp' "$gmp_release_ver" "http://ftp.gnu.org/gnu/gmp/gmp-$gmp_release_ver.tar.xz" "../source/gmp-$gmp_release_ver/configure" --build="$system_type" --prefix="$gmp_prefix" --enable-fat --enable-static --enable-cxx CPPFLAGS='-fexceptions'

#build mpfr
std_compile 'mpfr' "$mpfr_release_ver" "https://ftp.gnu.org/gnu/mpfr/mpfr-$mpfr_release_ver.tar.xz" "../source/mpfr-$mpfr_release_ver/configure" --build="$system_type" --prefix="$mpfr_prefix" --disable-shared --enable-static --with-gmp="$gmp_prefix"

#build mpc
std_compile 'mpc' "$mpc_release_ver" "https://ftp.gnu.org/gnu/mpc/mpc-$mpc_release_ver.tar.gz" "../source/mpc-$mpc_release_ver/configure" --build="$system_type" --prefix="$mpc_prefix" --with-gmp="$gmp_prefix" --with-mpfr="$mpfr_prefix" --disable-shared --enable-static

#build isl
#std_compile 'isl' "$isl_ver" "http://ftp.vim.org/languages/gcc/infrastructure/isl-$isl_ver.tar.bz2" "../source/isl-$isl_ver/configure" --prefix="$isl_prefix" --build="$system_type" --enable-static --disable-shared --with-gmp-prefix="$gmp_prefix" --with-piplib=no --with-clang=no
std_compile 'isl' "$isl_ver" "https://github.com/hydra3333/ffmpeg-windows-build-helpers-withOpenCL/raw/master/mingw_build_scripts/backups/isl-${isl_ver}-1-mingw32-src.tar.xz" "../source/isl-$isl_ver/configure" --prefix="$isl_prefix" --build="$system_type" --enable-static --disable-shared --with-gmp-prefix="$gmp_prefix" --with-piplib=no --with-clang=no

echo "# REBuild gmp now that isl is available"
# REBuild gmp now that isl is available
# 2017.04.29 gmplib.org is down, get it from 
#std_compile 'gmp' "$gmp_release_ver" "https://gmplib.org/download/gmp/gmp-$gmp_release_ver.tar.xz" "../source/gmp-$gmp_release_ver/configure" --build="$system_type" --prefix="$gmp_prefix" --enable-fat --enable-static --enable-cxx CPPFLAGS='-fexceptions'
std_compile_again 'gmp' "$gmp_release_ver" "http://ftp.gnu.org/gnu/gmp/gmp-$gmp_release_ver.tar.xz" "../source/gmp-$gmp_release_ver/configure" --build="$system_type" --prefix="$gmp_prefix" --enable-fat --enable-static --enable-cxx CPPFLAGS='-fexceptions'
#read -p "Press Enter to continue"

#build cloog
#if [[ "$gcc_ver" = "$gcc_old_release_ver" ]]; then
#  echo "BUILDING cloog ..."
#  std_compile 'cloog' "$cloog_ver" "http://ftp.vim.org/languages/gcc/infrastructure/cloog-$cloog_ver.tar.gz" "../source/cloog-$cloog_ver/configure" --prefix="$cloog_prefix" --build="$system_type" --enable-static --disable-shared --with-bits=gmp --with-isl=bundled --with-gmp-prefix="$gmp_prefix"
#else
  echo "NOT BUILDING cloog ..."
#fi
export CC="$old_cc"

# Build GCC (GCC only)
cd "$pkgs_dir" || print_error
create_pkg_dirs 'gcc'
cd "$pkgs_dir/gcc/source" || print_error
if [[ "$gcc_ver" != 'svn' ]]; then
	download_extract "https://ftp.gnu.org/gnu/gcc/gcc-$gcc_ver/gcc-$gcc_ver.tar.bz2" "ftp://ftp.gnu.org/gnu/gcc/gcc-$gcc_ver/gcc-$gcc_ver.tar.bz2"
# 2017.04.11 patch per https://github.com/rdp/ffmpeg-windows-build-helpers/issues/211#issuecomment-290362233
#                  and https://github.com/DeadSix27/python_cross_compile_script/blob/dev/mingw-build-script.sh
	if [ "$gcc_ver" == "6.3.0" ]; then #DeadSix27: Patch gcc 6.3.0 for mingw: https://github.com/Alexpux/MINGW-packages/issues/1580
	  # ALWAYS patch weak refs regardless of deadsix27 setting
	  #if [[ $do_deadsix27_patching == "y" ]]; then
		cd gcc-"$gcc_ver"
		echo "Patching GCC 6.3.0 weak refs"
		set -x
		pwd
		curl -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' -H 'Cache-Control: max-age=0' --retry 5 "https://raw.githubusercontent.com/hydra3333/ffmpeg-windows-build-helpers-withOpenCL/master/mingw_build_scripts/patches/0001-gcc_6_3_0_weak_refs_x86_64.patch" -O --fail || exit 1
		echo "applying patch"
		patch -p1 < "0001-gcc_6_3_0_weak_refs_x86_64.patch"
		set +x
		echo "Done"
		#read -p "Press Enter to continue... or control-C if not happy"
		cd ..
	  #fi
	fi
    if [ "$gcc_ver" = "7.1.0" ]; then #DeadSix27: Patch gcc 7.1.0 for mingw: https://github.com/Alexpux/MINGW-packages/issues/1580
		cd gcc-"$gcc_ver"
			echo "Patching GCC 7.1.0 weak refs"
			curl  -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' -H 'Cache-Control: max-age=0' --retry 5 "https://raw.githubusercontent.com/hydra3333/ffmpeg-windows-build-helpers-withOpenCL/master/mingw_build_scripts/patches/0001-gcc_7_1_0_weak_refs_x86_64.patch" -O --fail || exit 1
			echo "applying patch"
			patch -p1 < "0001-gcc_7_1_0_weak_refs_x86_64.patch"
			echo "Done"
			# https://gcc.gnu.org/ml/gcc-help/2017-05/msg00152.html
			# curl -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' -H 'Cache-Control: max-age=0' --retry 5 "https://dsix.site/gcc-7.1.0.libstdcpp-in-out.patch" -O --fail || exit 1
			# echo "applying libstdc++ patch"
			# patch -p1 < "gcc-7.1.0.libstdcpp-in-out.patch"
			# echo "Done"
			# cd 'libstdc++-v3'
			# sed -i 's/\b__in\b/___in/g' include/ext/random.tcc include/ext/vstring.tcc include/std/utility include/std/tuple include/std/istream include/tr2/bool_set.tcc include/tr2/bool_set include/bits/basic_string.h include/bits/basic_string.tcc include/bits/locale_facets.h include/bits/istream.tcc include/tr1/utility include/tr1/tuple
			# sed -i 's/\b__out\b/___out/g' include/ext/random.tcc include/ext/algorithm include/ext/pb_ds/detail/debug_map_base.hpp include/std/ostream include/std/thread include/tr2/bool_set include/bits/ostream.tcc include/bits/regex.tcc include/bits/stl_algo.h include/bits/locale_conv.h include/bits/regex.h include/bits/ostream_insert.h include/tr1/regex include/parallel/algo.h include/parallel/set_operations.h include/parallel/multiway_merge.h include/parallel/unique_copy.h include/experimental/algorithm config/locale/dragonfly/c_locale.h config/locale/generic/c_locale.h config/locale/gnu/c_locale.h
			# cd ..
		cd ..
	fi
else
  if cd 'gcc-svn' 2>/dev/null; then
    build_progress 'gcc-svn' 'Updating'
    svn update > >(build_log) 2>&1 || print_error
    build_progress 'done'
    cd '..'
  else
    build_progress 'gcc-svn' 'Downloading'
    svn checkout svn://gcc.gnu.org/svn/gcc/trunk gcc-svn > >(build_log) 2>&1 || print_error
    build_progress 'done'
  fi
fi

clean_build
build_progress 'gcc' 'Configuring'
configure_gcc "$gcc_ver" || print_error
build_progress 'done'

build_progress 'all-gcc' 'Building'
make -j "$cpu_count" all-gcc > >(build_log) 2>&1 || print_error
build_progress 'done'

build_progress 'gcc' 'Installing'
make install-gcc > >(build_log) 2>&1 || print_error
build_progress 'done'

# Build mingw-w64 CRT 
cd "$mingw_w64_build_dir/crt" || print_error

build_progress 'mingw-w64 crt' 'Configuring'
"$mingw_w64_source_dir/mingw-w64-$mingw_w64_ver/mingw-w64-crt/configure" --build="$system_type" --host="$mingw_w64_target" --prefix="$mingw_w64_prefix" --with-sysroot="$mingw_w64_prefix" > >(build_log) 2>&1 || print_error
build_progress 'done'

build_progress 'mingw-w64 crt' 'Building'
if [[ "$OSTYPE" = "darwin"* ]]; then
  make > >(build_log) 2>&1 || print_error
else
  make -j "$cpu_count" > >(build_log) 2>&1 || print_error
fi
build_progress 'done'

build_progress 'mingw-w64 crt' 'Installing'
make install > >(build_log) 2>&1 || print_error
build_progress 'done'

cd "$mingw_w64_prefix" || print_error
mv "./$mingw_w64_target/lib/"* './lib/'
rm -fr "./$mingw_w64_target/lib"
cd "./$mingw_w64_target"
ln -s '../lib' './lib'

echo "Calling build_thread_lib before GCC"
if [[ "$thread_lib" != 'disable' ]]; then
  build_thread_lib "$mingw_w64_target" "$mingw_w64_prefix" || print_error
fi

# Build GCC
cd "$pkgs_dir/gcc/build" || print_error
build_progress 'gcc target-libgcc' 'Building'
make -j "$cpu_count" all-target-libgcc > >(build_log) 2>&1 || print_error
build_progress 'done'

build_progress 'gcc target-libgcc' 'Installing'
make -j "$cpu_count" install-target-libgcc > >(build_log) 2>&1 || print_error
build_progress 'done'

build_progress 'gcc' 'Building'
make -j "$cpu_count" > >(build_log) 2>&1 || print_error
build_progress 'done'

#-----------
#read -p "after make in building gcc"
#-----------

build_progress 'gcc' 'Installing'
make install-strip > >(build_log) 2>&1 || print_error
build_progress 'done'

#echo "Calling build_thread_lib after GCC"
#if [[ "$thread_lib" != 'disable' ]]; then
#  build_thread_lib "$mingw_w64_target" "$mingw_w64_prefix" || print_error
#fi
#-----------
#read -p "after make install-strip in building gcc and build_thread_lib"
#-----------

if [[ "$enable_gendef" = 'yes' ]]; then
  cd "$mingw_w64_build_dir" || print_error
  rm -fr 'gendef'
  mkdir 'gendef'
  cd 'gendef' || print_error
  build_progress 'gendef' 'Configuring'
  "$mingw_w64_source_dir/mingw-w64-$mingw_w64_ver/mingw-w64-tools/gendef/configure" --build="$system_type" --prefix="$mingw_w64_prefix" --target="$mingw_w64_target" > >(build_log) 2>&1 || print_error
  build_progress 'done'

  build_progress 'gendef' 'Building'
  make > >(build_log) 2>&1 || print_error
  build_progress 'done'

  build_progress 'gendef' 'Installing'
  make install > >(build_log) 2>&1 || print_error
  build_progress 'done'
fi

if [[ "$enable_widl" = 'yes' ]]; then
  cd "$mingw_w64_build_dir" || print_error
  rm -fr 'widl'
  mkdir 'widl'
  cd 'widl' || print_error
  build_progress 'widl' 'Configuring'
  "$mingw_w64_source_dir/mingw-w64-$mingw_w64_ver/mingw-w64-tools/widl/configure" --build="$system_type" --prefix="$mingw_w64_prefix" --target="$mingw_w64_target" > >(build_log) 2>&1 || print_error
  build_progress 'done'

  build_progress 'widl' 'Building'
  make > >(build_log) 2>&1 || print_error
  build_progress 'done'

  build_progress 'widl' 'Installing'
  make install > >(build_log) 2>&1 || print_error
  build_progress 'done'
fi

return 0
}

clean_build_fn () {
if [[ "$clean_build" = 'yes' ]]; then
  cd "$working_dir" && rm -fr 'build' 'pkgs' 'source'
  return
fi
if [[ "$default_config" = 'yes' ]]; then
  return
fi
unset user_input
printf '\n'
while [[ "$user_input" != [YyNn] ]]; do
  printf 'Would you like to clean the build, leaving only the built toolchain? You can set this option with: "--clean-build", see --help for more information. The "build", "pkgs", and "source" directories along with all files within them will be removed if "y" is selected. [y/n]: '
  read user_input
  if [[ "$user_input" = [Yy] ]]; then
    cd "$working_dir" && rm -fr 'build' 'pkgs' 'source' # 'build_$build_type.log'
  fi
  if [[ "$user_input" != [YyNn] ]]; then
    printf '\n\nYour selection was not vaild, please try again.\n\n'
  fi
done
}

download_source () {
case "$1" in
  'multi' ) if [[ -d "$mingw_w64_i686_prefix" && -d "$mingw_w64_x86_64_prefix" ]]; then  prefix_present='yes'; fi ;;
  'win32' ) if [[ -d "$mingw_w64_i686_prefix" ]]; then  prefix_present='yes'; fi ;;
  'win64' ) if [[ -d "$mingw_w64_x86_64_prefix" ]]; then  prefix_present='yes'; fi ;;
esac
shift

mkdir -p 'pkgs' 'source' 'build'
cd 'pkgs' || print_error
rm -fr 'config.guess'
build_progress 'config.guess' 'Downloading'
wget -nv -O config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' > >(build_log) 2>&1 || { ping -c 1 git.savannah.gnu.org >/dev/null 2>&1 || printf '\nsavannah.gnu.org seems to be offline right now and is needed to download the file "config.guess", please try again later.\n\n'; rm -f 'config.guess' && exit 1; }
build_progress 'done'
system_type="$(sh config.guess)"

cd "$mingw_w64_source_dir" || print_error
if [[ "$mingw_w64_ver" = 'git' ]]; then
  git_dl "mingw-w64" "https://git.code.sf.net/p/mingw-w64/mingw-w64"
else
  if [[ -d "mingw-w64-$mingw_w64_release_ver" && "$allow_overwrite" != 'yes' &&  "$prefix_present" = 'yes' ]]; then
    if ! yes_no_sel "MinGW-w64 is already the latest version, continue with the build anyway? You can set this option with: '--allow-overwrite', see '--help' for more information."; then
      exit 0
    fi
  fi

  if [[ ! -d "mingw-w64-$mingw_w64_release_ver" || ! -f "mingw-w64-$mingw_w64_release_ver.tar.bz2" ]]; then
    rm -f "mingw-w64-$mingw_w64_release_ver.tar.bz2" "mingw-w64-$mingw_w64_release_ver"
    build_progress "mingw-w64-$mingw_w64_release_ver.tar.bz2" 'Downloading'
    wget -nv -O "mingw-w64-$mingw_w64_release_ver.tar.bz2" "https://downloads.sourceforge.net/project/mingw-w64/mingw-w64/mingw-w64-release/mingw-w64-v${mingw_w64_release_ver}.tar.bz2" > >(build_log) 2>&1 || print_error
    build_progress 'done'
    build_progress "mingw-w64-$mingw_w64_release_ver.tar.bz2" 'Extracting'
    bzip2 -d <"mingw-w64-$mingw_w64_release_ver.tar.bz2" | pax -r
    build_progress 'done'
    mv "mingw-w64-v$mingw_w64_release_ver" "mingw-w64-$mingw_w64_release_ver"
  fi
fi
}

check_missing_packages () {
local check_packages=('bison' 'm4' 'flex' 'git' 'svn' 'gcc' 'yasm' 'cvs' 'g++' 'make' 'xz' 'bzip2' 'pax' 'gunzip' 'wget')
for package in "${check_packages[@]}"; do
  command -v "$package" >/dev/null || missing_packages=("$package" "${missing_packages[@]}")
done

if [[ -n "${missing_packages[@]}" ]]; then
  printf '\nCould not find the following packages: %s\n' "${missing_packages[*]}"
  printf 'Install the missing packages before running this script.\n\n'
  exit 1
fi
}

build_pthreads_w32 () {
if [[ -z "$pthreads_w32_ver" ]]; then
  pthreads_w32_ver='cvs'
fi

local target prefix
target="$1"
prefix="$2"

shift 2
cd "$pkgs_dir" || print_error
create_pkg_dirs 'pthread-w32' || print_error

if [[ "$pthreads_w32_ver" = "$pthreads_w32_release_ver" ]]; then
  download_extract "https://mirrors.kernel.org/sourceware/pthreads-win32/pthreads-w32-$pthreads_w32_release_ver-release.tar.gz"
  if [[ ! -d "pthreads-w32-$pthreads_w32_release_ver" ]]; then
    mv "pthreads-w32-$pthreads_w32_release_ver-release" "pthreads-w32-$pthreads_w32_release_ver" || print_error
  fi
else
  unset oldmd5 newmd5
  if cd 'pthreads-w32-cvs' 2>/dev/null; then
    build_progress 'pthreads-w32 cvs' 'Updating'
    cvs update > >(build_log) 2>&1 || print_error
    build_progress 'done'
    cd '..'
  else
    build_progress 'pthreads-w32 cvs' 'Downloading'
    cvs -d :pserver:[email protected]:/cvs/pthreads-win32 checkout pthreads > >(build_log) 2>&1 || print_error
    build_progress 'done'
    mv 'pthreads' 'pthreads-w32-cvs'
  fi
fi

cd "pthreads-w32-$pthreads_w32_ver" || print_error
make realclean > >(build_log) 2>&1 || print_error
if [[ "${static_build[@]}" != *"disable-shared"* ]]; then
  build_progress 'pthreads-w32 shared' 'Building'
  make CROSS="$target-" realclean GC ARCH="$pthread_arch" > >(build_log) 2>&1 || print_error
  build_progress 'done'

  cp 'pthreadGC2.dll' "$prefix/lib/" || print_error
  cd "$prefix/lib" || print_error
  ln -s "./pthreadGC2.dll" "./libpthread.dll"
  cd "$pkgs_dir/pthread-w32/source/pthreads-w32-$pthreads_w32_ver" || print_error
fi
build_progress 'pthreads-w32 static' 'Building'
make CROSS="$target-" realclean GC-static ARCH="$pthread_arch" > >(build_log) 2>&1 || print_error
build_progress 'done'

cp 'libpthreadGC2.a' "$prefix/lib/" || print_error
cp 'pthread.h' 'sched.h' 'semaphore.h' "$prefix/include/" || print_error
cd "$prefix/lib" || print_error
ln -s "./libpthreadGC2.a" "./libpthread.a"
cd '../include' || print_error

for file in 'pthread.h' 'sched.h' 'semaphore.h'; do
  if ! ed -s "$prefix/include/$file" <<< $',s/ __declspec (dllexport)//g\n,s/ __declspec (dllimport)//g\nw\nq' > >(build_log) 2>&1; then
    mv "$file" "$file".orig
    sed 's/ __declspec (dllexport)//g;s/ __declspec (dllimport)//g' "$file".orig > "$file"
    rm -f "$file".orig
  fi
done
}

build_thread_lib () {
local target prefix
target="$1"
prefix="$2"
shift 2
case "$thread_lib" in
  'winpthreads' ) build_winpthreads "$target" "$prefix" ;;
  'pthreads-w32' ) build_pthreads_w32 "$target" "$prefix" ;;
  * ) build_pthreads_w32 "$target" "$prefix" ;;
esac
}

completed_build () {
local arch="$1"
case "$arch" in
  multi ) local new_path="$mingw_w64_i686_prefix/bin:$mingw_w64_x86_64_prefix/bin";;
  win32 ) local new_path="$mingw_w64_i686_prefix/bin";;
  win64 ) local new_path="$mingw_w64_x86_64_prefix/bin";;
esac
printf 'To add MinGW-w64 to the PATH variable run: export PATH="%s:$PATH"\n' "$new_path"
}

no_errors='MinGW-w64 has been built without errors.'

calculate_steps ()
{
case "$arch" in
  'multi' ) total_steps='69';;
  'win32' ) total_steps='53';;
  'win64' ) total_steps='53';;
esac

if [[ "$arch" = 'multi' ]]; then
  if [[ "${static_build[@]}" = *"disable-shared"* ]]; then
    total_steps=$((total_steps-2))
  fi

  if [[ "$enable_gendef" = 'yes' ]]; then
    total_steps=$((total_steps+6))
  fi
  if [[ "$enable_widl" = 'yes' ]]; then
    total_steps=$((total_steps+6))
  fi
#  if [[ "$gcc_ver" = "$gcc_old_release_ver" ]]; then
#    total_steps=$((total_steps+5))
#  fi
else
  if [[ "${static_build[@]}" = *"disable-shared"* ]]; then
    total_steps=$((total_steps-1))
  fi

  if [[ "$enable_gendef" = 'yes' ]]; then
    total_steps=$((total_steps+3))
  fi
  if [[ "$enable_widl" = 'yes' ]]; then
    total_steps=$((total_steps+3))
  fi
#  if [[ "$gcc_ver" = "$gcc_old_release_ver" ]]; then
#    total_steps=$((total_steps+5))
#  fi
fi
}

build_mingw_w64_toolchain () {
current_step='1'
local arch="$1"
calculate_steps "$arch"
check_missing_packages || print_error
if [[ -z "$build_type" || -z "$mingw_w64_ver" || -z "$binutils_ver" || -z "$gcc_ver" || -z "$enabled_langs" ]]; then
  configure_build_fn || print_error
fi
if [[ -z "$cpu_count" ]]; then
  use_cpu_count
fi
download_source "$arch" || print_error
case "$arch" in
  'multi' ) build_mingw_w64 "$target_i686" "$mingw_w64_i686_prefix" && build_mingw_w64 "$target_x86_64" "$mingw_w64_x86_64_prefix" || print_error ;;
  'win32' ) build_mingw_w64 "$target_i686" "$mingw_w64_i686_prefix" || print_error ;;
  'win64' ) build_mingw_w64 "$target_x86_64" "$mingw_w64_x86_64_prefix" || print_error ;;
esac
clean_build_fn
printf '\n\n%s\n' "$no_errors"
completed_build "$arch"
}

test_opt () {
test_valid_opt 'build_type' 'win32' 'win64' 'multi'
test_valid_opt 'mingw_w64_ver' "$mingw_w64_release_ver" 'git'
test_valid_opt 'thread_lib' 'winpthreads' 'pthreads-w32' 'disable'
test_valid_opt 'pthreads_w32_ver' "$pthreads_w32_release_ver" 'cvs'
test_valid_opt 'do_deadsix27_patching'  'y' 'n'
if [[ -n "$pthreads_w32_ver" ]]; then
 thread_lib='pthreads-w32'
fi
if [[ -n "$cpu_count_opt" ]]; then
  check_cpu_count_optarg
fi
test_valid_opt 'binutils_ver' "$binutils_release_ver" 'git'
if ! command -v makeinfo >/dev/null; then
  printf 'makeinfo is needed to compile binutils and will need be installed. On Debian/Ubuntu it is part of the "texinfo" software package.\n'
  exit 1
fi
#test_valid_opt 'gcc_ver' "$gcc_release_ver" "$gcc_old_release_ver" 'svn'
test_valid_opt 'gcc_ver' "$gcc_release_ver" 'svn'
}

check_cpu_count_optarg () {
if [[ "$cpu_count_opt" = "max" ]]; then
  cpu_count="$detected_cpu_count"
  return 0
fi

if [[ "$cpu_count_opt" -gt "$detected_cpu_count" ]]; then
  if ! yes_no_sel "The input number of cores/threads was higher than the number detected ($detected_cpu_count were detected). Trying to use more cores/threads than your CPU has can cause your system to crash. Are you sure you want to continue?"; then
    exit 1
  fi
fi
cpu_count="$cpu_count_opt"
}

wipe () {
if yes_no_sel "Are you sure you want to remove all MinGW-w64 files? Files/directories 'build' 'build_$build_type.log' 'mingw-w64-i686' 'mingw-w64-x86_64' 'pkgs' 'source' will be removed."; then
  rm -fr 'build' 'mingw-w64-i686' 'mingw-w64-x86_64' 'pkgs' 'source' # 'build_$build_type.log' 
fi

exit 0
}

test_valid_opt () {
if [[ -z "${!1}" ]]; then
  return
fi
local opt
local valid_arg
opt="$1"
shift

for args do
  if [[ "$args" = "${!opt}" ]]; then
    valid_arg='yes'
  fi
done

if [[ "$valid_arg" != 'yes' ]]; then
  clear
  printf 'Error, "%s" is not a valid option for --%s. The valid options are: %s\n' "${!opt}" "${opt//_/-}" "${*}"
  exit 1
fi
}

main_menu () {
if [[ "$build_type" != '' ]]; then
  build_mingw_w64_toolchain "$build_type" 2>&1 | tee "$working_dir/build_$build_type.log"
  exit 0
fi
clear
while [[ "$build_choice" != [1-3] ]]; do
if [[ -n "${unknown_opts[@]}" ]]; then
  printf 'Unknown option(s)'
  for unknown_opt in "${unknown_opts[@]}"; do
    printf ' "%s"' "$unknown_opt"
  done
  printf ', ignored.\n\n'
fi
cat <<EOF
What version of MinGW-w64 would you like to build or update?
  1. Both Win32 and Win64
  2. Win32 (32-bit only)
  3. Win64 (64-bit only)
  4. About
  5. Exit

For a list of all available options, exit and run: 'bash ./mingw-w64-build-$script_ver --help'

EOF
printf 'Input your choice [1-5]: '
read build_choice
case "$build_choice" in
  1 ) build_mingw_w64_toolchain 'multi';;
  2 ) build_mingw_w64_toolchain 'win32';;
  3 ) build_mingw_w64_toolchain 'win64';;
  4 ) about; clear ;;
  5 ) exit 0 ;;
  * ) printf '\nYour choice was not valid, please try again.\n\n' ;;
esac
done
}

while true; do
  case $1 in
    -h | --help ) display_help; exit 0 ;;
    -a | --about ) about; exit 0 ;;
    -V | --version ) printf '%s\n' "$script_ver"; exit 0 ;;
    --build-type=* ) build_type="${1#*=}"; shift ;;
    --default-configure ) default_configure; shift ;;
    --rebuild-all ) rebuild='yes'; shift ;;
    --allow-overwrite ) allow_overwrite='yes'; shift ;;
    --mingw-w64-ver=* ) mingw_w64_ver="${1#*=}"; shift ;;
    --cpu-count=* ) cpu_count_opt="${1#*=}"; shift ;;
    --binutils-ver=* ) binutils_ver="${1#*=}"; shift ;;
    --gcc-ver=* ) gcc_ver="${1#*=}"; shift ;;
    --pthreads-w32-ver=* ) pthreads_w32_ver="${1#*=}" ; shift ;;
    --gcc-langs=* ) enabled_langs="${1#*=}"; shift ;;
    --enable-nls ) disable_nls=('--enable-nls'); shift ;;
    --disable-shared ) static_build=('--disable-shared' '--enable-static'); shift ;;
    --threads=* ) thread_lib="${1#*=}"; shift ;;
    --clean-build ) clean_build='yes'; shift ;;
    --enable-gendef ) enable_gendef='yes';  shift ;;
    --enable-widl ) enable_widl='yes'; shift ;;
    --verbose ) verbose='yes'; shift ;;
	--deadsix27_patching=* ) do_deadsix27_patching="${1#*=}"; shift ;;
    wipe ) wipe; shift ;;
    -- ) shift; break ;;
    -* ) printf 'Error, unknown option: "%s".\n' "$1"; exit 1 ;;
    * ) break ;;
  esac
done

test_opt

main_menu

exit 0
... GPL statement removed solely so that it fits into one forum post.

Post Reply