#!/bin/bash

#
# The BSD 3-Clause License. http://www.opensource.org/licenses/BSD-3-Clause
#
# This file is part of 'mingw-builds' project.
# Copyright (c) 2011,2012, by niXman (i dotty nixman doggy gmail dotty com)
# All rights reserved.
#
# Project: mingw-builds ( http://sourceforge.net/projects/mingwbuilds/ )
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# - Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in
#     the documentation and/or other materials provided with the distribution.
# - Neither the name of the 'mingw-builds' nor the names of its contributors may
#     be used to endorse or promote products derived from this software
#     without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

# **************************************************************************

. ./scripts/functions.sh

ENABLE_LANGUAGES='c,c++,fortran'

BASE_CFLAGS="-O2 -pipe -fomit-frame-pointer"
BASE_CXXFLAGS="$BASE_CFLAGS"
BASE_CPPFLAGS=""
BASE_LDFLAGS="-pipe"

PROCESSOR_OPTIMIZATION_TUNE_32='core2'
PROCESSOR_OPTIMIZATION_TUNE_64='core2'
PROCESSOR_OPTIMIZATION_ARCH_32='i686'
PROCESSOR_OPTIMIZATION_ARCH_64='nocona'

LINK_TYPE_BOTH="--enable-shared --enable-static"
LINK_TYPE_SHARED="--enable-shared --disable-static"
LINK_TYPE_STATIC="--enable-static --disable-shared"
GCC_DEPS_LINK_TYPE=$LINK_TYPE_STATIC
LINK_TYPE_SUFFIX="static"

#LOGVIEWER="c:/progra~1/notepad++/notepad++.exe"
LOGVIEWER="c:/progra~2/notepad++/notepad++.exe"

SHOW_LOG_ON_ERROR=yes

JOBS=1

# **************************************************************************

MINGW_BUILDS_VERSION="MinGW-builds-1.0.0"
PKG_VERSION="Built by MinGW-builds project"
BUG_URL=http://sourceforge.net/projects/mingwbuilds/

ORIGINAL_PATH=$PATH

TOP_DIR=$(func_simplify_path "$PWD")
PATCHES_DIR=$TOP_DIR/patches
SOURCES_DIR=$TOP_DIR/sources
TESTS_DIR=$TOP_DIR/tests
TOOLCHAINS_DIR=$TOP_DIR/toolchains

x32_HOST_MINGW_PATH=$TOOLCHAINS_DIR/mingw32
x64_HOST_MINGW_PATH=$TOOLCHAINS_DIR/mingw64

x32_HOST_MINGW_PATH_URL=http://sourceforge.net/projects/mingwbuilds/files\
/host-windows/releases/4.7.2/32-bit/threads-posix/sjlj/x32-4.7.2-release-posix-sjlj-rev8.7z
x64_HOST_MINGW_PATH_URL=http://sourceforge.net/projects/mingwbuilds/files\
/host-windows/releases/4.7.2/64-bit/threads-posix/sjlj/x64-4.7.2-release-posix-sjlj-rev8.7z

# **************************************************************************

RUN_ARGS="$@"
[[ $# == 1 && $1 == --help	|| $[ $# == 0 ] == 1 ]] && {
	echo "usage:"
	echo "  ./${0##*/} <gcc version> <x32|x64> [OPTIONS]"
	echo "  help:"
	echo "    --buildroot=<path>     - specifies the build root directory"
	echo "    --preload              - firstly downloads then builds"
	echo "    --download             - download only the sources"
	echo "    --exceptions=<type>    - specifies exceptions model for GCC"
	echo "                             available: dwarf, seh, sjlj"
	echo "    --use-lto              - build with LTO using"
	echo "    --no-multilib          - build GCC without multilib support"
	echo "    --no-strip             - don't strip dll's & executables on install"
	echo "    --dyn-deps             - build GCC with dynamically dependencies"
	echo "    --jobs=N               - specifies number of parallel make threads"
	echo "    --rev=N                - specifies number of the build revision"
	echo "    --threads=<model>      - specifies the threads model for GCC/libstdc++"
	echo "                             available: win32, posix"
	echo "    --version              - pring the version of the MinGW-builds scripts"
	echo "    --mingw-compress       - compressing MinGW"
	echo "    --srcs-compress        - compressing sources"
	echo "    --mingw-upload=<user>  - upload toolchain archives to sf-project"
	echo "    --src-upload=<user>    - upload sources archive to sf-project"
	echo "    --cflags='<flags>'     - additional CFLAGS"
	echo "    --cxxflags='<flags>'   - additional CXXFLAGS"
	echo "    --cppflags='<flags>'   - additional CPPFLAGS"
	echo "    --ldflags='<flags>'    - additional LDFLAGS"
	echo "  available gcc versions:"
	echo "    gcc-4.6.2 (4.6.2 release)"
	echo "    gcc-4.6.3 (4.6.3 release)"
	#echo "    gcc-4.6.4 (4.6.4 release)"
	#echo "    gcc-4.6.5 (4.6.5 release)"
	#echo "    gcc-4.6.6 (4.6.6 release)"
	echo "    gcc-4.7.0 (4.7.0 release)"
	echo "    gcc-4.7.1 (4.7.1 release)"
	echo "    gcc-4.7.2 (4.7.2 release)"
	#echo "    gcc-4.8.0 (4.8.0 release)"
	#echo "    gcc-4.8.1 (4.8.1 release)"
	echo "    gcc-4_6-branch (currently 4.6.4-prerelease)"
	echo "    gcc-4_7-branch (currently 4.7.3-prerelease)"
	#echo "    gcc-4_8-branch (currently 4.8.1-prerelease)"
	echo "    gcc-trunk (currently 4.8.0-snapshot)"

	exit 0
}

[[ $SHOW_LOG_ON_ERROR == yes && ! -f $LOGVIEWER ]] && {
	LOGVIEWER=/c/Windows/system32/notepad.exe
}

[[ -d /mingw ]] && {
	echo "please remove \"/mingw\" directory. terminate."
	exit 1
}

[[ -n $(which "gcc.exe" 2>/dev/null) || \
	-n $(which "i686-pc-mingw32-gcc.exe" 2>/dev/null) || \
	-n $(which "i686-w64-mingw32-gcc.exe" 2>/dev/null) || \
	-n $(which "x86_64-w64-mingw32-gcc.exe" 2>/dev/null) \
]] && {
	echo "remove from PATH any existing MinGW directory. terminate."
	exit 1
}

# **************************************************************************

ROOT_DIR=$(func_simplify_path "$HOME")

PRELOAD_MODE=no
DOWNLOAD_MODE=no
BUILD_ARCHITECTURES=()
EXCEPTIONS_MODEL=sjlj
USE_MULTILIB=yes
STRIP_ON_INSTALL=yes
THREADS_MODEL=posix
REV_NUM=""
GCC_NAME=""
COMPRESSING_MINGW=no
COMPRESSING_SRCS=no
UPLOAD_BIN_TO_SF=no
UPLOAD_SRC_TO_SF=no
SF_USER=""


while [[ $# > 0 ]]; do
	case $1 in
		--cflags=*) BASE_CFLAGS="$BASE_CFLAGS ${1/--cflags=/}" ;;
		--cxxflags=*) BASE_CXXFLAGS="$BASE_CXXFLAGS ${1/--cxxflags=/}" ;;
		--cppflags=*) BASE_CPPFLAGS="$BASE_CPPFLAGS ${1/--cppflags=/}" ;;
		--ldflags=*) BASE_LDFLAGS="$BASE_LDFLAGS ${1/--ldflags=/}" ;;
		--buildroot=*)
			ROOT_DIR=${1/--buildroot=/}
			ROOT_DIR=${ROOT_DIR//:/:\/}
			ROOT_DIR=${ROOT_DIR//\/\//\/}
			mkdir -p ${ROOT_DIR} || die "Incorrect directory ${ROOT_DIR}"
			pushd ${ROOT_DIR} > /dev/null
			ROOT_DIR=`pwd`
			popd > /dev/null
		;;
		--preload) PRELOAD_MODE=yes ;;
		--download) DOWNLOAD_MODE=yes ;;
		--exceptions=*)
			EXCEPTIONS_MODEL=${1/--exceptions=/}
			case $EXCEPTIONS_MODEL in
			dwarf)
				USE_MULTILIB=no
				[[ ${BUILD_ARCHITECTURES[@]} =~ x32 ]] && { shift; continue; }
				BUILD_ARCHITECTURES=( x32 )
			;;
			seh)
				USE_MULTILIB=no
				[[ ${BUILD_ARCHITECTURES[@]} =~ x64 ]] && { shift; continue; }
				BUILD_ARCHITECTURES=( x64 )
			;;
			sjlj)
				USE_MULTILIB=yes			
			;;
			*)
				echo "$EXCEPTIONS_MODEL is not valid exception model. Available models: dwarf, seh, sjlj"
				exit 1
			;;
			esac	
		;;
		--use-lto)
			BASE_CFLAGS="$BASE_CFLAGS -flto"
			BASE_CXXFLAGS="$BASE_CXXFLAGS -flto"
			BASE_LDFLAGS="$BASE_LDFLAGS -flto"
		;;
		--no-multilib) USE_MULTILIB=no ;;
		--no-strip) STRIP_ON_INSTALL=no ;;
		--dyn-deps)
			GCC_DEPS_LINK_TYPE=$LINK_TYPE_SHARED
			LINK_TYPE_SUFFIX="shared"
		;;
		--jobs=*)
			[[ ${1/--jobs=/} == 0 ]] && {
				echo "jobs value must be greater then 0. terminate."
				exit 1
			}
			JOBS=${1/--jobs=/}
		;;
		--threads=*) 
			THREADS_MODEL=${1/--threads=/}
			case $THREADS_MODEL in
			win32 | posix)
			;;
			*)
				echo "$THREADS_MODEL is not valid threads model. Available models: posix, win32"
				exit 1
			;;
			esac
		;;
		--rev=*)
			REV_NUM=${1/--rev=/}
			PKG_VERSION="rev$REV_NUM, $PKG_VERSION"
		;;
		x32)
			[[ ${BUILD_ARCHITECTURES[@]} =~ x32 ]] && { shift; continue; }
			BUILD_ARCHITECTURES=( ${BUILD_ARCHITECTURES[@]} x32 )
		;;
		x64)
			[[ ${BUILD_ARCHITECTURES[@]} =~ x64 ]] && { shift; continue; }
			BUILD_ARCHITECTURES=( ${BUILD_ARCHITECTURES[@]} x64 )
		;;
		gcc-*)
			[[ ! -f scripts/$1.sh ]] && {
				echo "bad gcc version. terminate."; exit 1;
			} || {
				GCC_NAME=$1
			}
		;;
		--version)echo $MINGW_BUILDS_VERSION; exit 0 ;;
		--mingw-compress) COMPRESSING_MINGW=yes ;;
		--srcs-compress) COMPRESSING_SRCS=yes ;;
		--mingw-upload=*) UPLOAD_BIN_TO_SF=yes; SF_USER=${1/--upload=/} ;;
		--src-upload=*) UPLOAD_SRC_TO_SF=yes; SF_USER=${1/--upload=/} ;;
		*)
			echo "bad command line: \"$1\""
			echo "terminate."
			exit 1
		;;
	esac
	shift
done

# **************************************************************************

[[ ! -d $ROOT_DIR ]] && {
	mkdir -p $ROOT_DIR
	[[ $? == 0 ]] && {
		rm -Rf $ROOT_DIR
	} || {
		echo "bad build root directory. terminate."
		exit 1
	}
}

SRCS_DIR=$ROOT_DIR/src
PREREQ_DIR=$ROOT_DIR/mingw-prereq
RUNTIME_DIR=$ROOT_DIR/mingw-runtime
ARCHIVES_DIR=$ROOT_DIR/mingw-archives
mkdir -p $SRCS_DIR $ARCHIVES_DIR $PREREQ_DIR $RUNTIME_DIR

# **************************************************************************

[[ -z $GCC_NAME ]] && {
	echo "please specify GCC version. terminate."
	exit 1
}

[[ $THREADS_MODEL != win32 && $THREADS_MODEL != posix ]] && {
	echo "bad threads model. terminate."
	exit 1
}

[[ ${#BUILD_ARCHITECTURES[@]} > 2 || ${#BUILD_ARCHITECTURES[@]} == 0 || \
	${BUILD_ARCHITECTURES[0]} == ${BUILD_ARCHITECTURES[1]} ]] && {
	echo "error in build architectures(${BUILD_ARCHITECTURES[@]}). terminate."
	exit 1
}
[[ $EXCEPTIONS_MODEL != sjlj && $USE_MULTILIB == yes ]] && {
	echo "$EXCEPTIONS_MODEL exceptions not allowed on multilib architecture. terminate."
	exit 1
}
[[ $EXCEPTIONS_MODEL == dwarf ]] && {
	[[ ${BUILD_ARCHITECTURES[@]} =~ x64 ]] && {
		echo "DWARF exceptions not allowed on x86_64 architecture. terminate."
		exit 1
	}
	[[ ${#BUILD_ARCHITECTURES[@]} > 1 ]] && {
		echo "error in build architectures(${BUILD_ARCHITECTURES[@]}). terminate."
		exit 1
	}
}
[[ $EXCEPTIONS_MODEL == seh ]] && {
	[[ ${BUILD_ARCHITECTURES[@]} =~ x32 ]] && {
		echo "SEH exceptions not allowed on x86 architecture. terminate."
		exit 1
	}
	[[ ${#BUILD_ARCHITECTURES[@]} > 1 ]] && {
		echo "error in build architectures(${BUILD_ARCHITECTURES[@]}). terminate."
		exit 1
	}
}

[[ $(env | grep PROCESSOR_ARCHITEW6432) =~ AMD64 ]] && {
	IS_64BIT_HOST=yes
} || {
	IS_64BIT_HOST=no
}

[[ $IS_64BIT_HOST == no && ${BUILD_ARCHITECTURES[@]} =~ x64 ]] && {
	echo "you can't build 64-bit MinGW using 32-bit OS. terminate."
	exit 1
}

[[ $IS_64BIT_HOST == no && $USE_MULTILIB == yes ]] && {
	echo "you can't build multitarget MinGW using 32-bit OS. terminate."
	exit 1
}

[[ $[ $COMPRESSING_MINGW == yes || $COMPRESSING_SRCS == yes ] == 1 && ! -f /bin/7za.exe ]] && {
	echo "7za.exe is not found in your /bin directory. terminate."
	exit 1
}

# **************************************************************************

[[ ! -d $x32_HOST_MINGW_PATH || ! -d $x64_HOST_MINGW_PATH ]] && {
	[[ $EXCEPTIONS_MODEL == dwarf && ! -d $x32_HOST_MINGW_PATH ]] || \
	[[ $EXCEPTIONS_MODEL == seh && ! -d $x64_HOST_MINGW_PATH ]] || \
	[[ $EXCEPTIONS_MODEL == sjlj && ! -d $x64_HOST_MINGW_PATH ]] && {
		echo -n "host toolchains is not installed. you wish to install (y/n)?"
		while :
		do
			read -s -n1
			echo ": $REPLY"
			[[ $REPLY != y && $REPLY != n ]] && continue
			[[ $REPLY == n ]] && {
				echo "you can't build MinGW without installed host toolchains. terminate."
				exit 1
			}
			[[ $REPLY == y ]] && break
		done

		mkdir -p $TOOLCHAINS_DIR
		[[ $? != 0 ]] && {
			echo "can't create toolchains directory. terminate."
			exit 1
		}

		func_install_toolchain \
			$TOOLCHAINS_DIR \
			$x32_HOST_MINGW_PATH \
			$x64_HOST_MINGW_PATH \
			$x32_HOST_MINGW_PATH_URL \
			$x64_HOST_MINGW_PATH_URL
		func_res=$?
		[[ $func_res != 0 ]] && {
			echo "toolchain install error. terminate."
			echo "see log-files in \"$TOOLCHAINS_DIR\" directory."
			exit $func_res
		}
	}
}

# **************************************************************************

LIBICONV_X32_SUBTARGETS=(
	libiconv-x32-pre
	libiconv-x32
	libiconv-x32-post
)

LIBICONV_X64_SUBTARGETS=(
	libiconv-x64-pre
	libiconv-x64
	libiconv-x64-post
)

WINPTHREADS_X32_SUBTARGETS=(
	winpthreads-x32-pre
	winpthreads-x32
	winpthreads-x32-post
)

WINPTHREADS_X64_SUBTARGETS=(
	winpthreads-x64-pre
	winpthreads-x64
	winpthreads-x64-post
)

ZLIB_X32_SUBTARGETS=(
	zlib
	zlib-x32-post
)

ZLIB_X64_SUBTARGETS=(
	zlib
	zlib-x64-post
)

SUBTARGETS_PART1=(
	gmp
	mpfr
	mpc
	ppl
	cloog
	mingw-w64-api
	mingw-w64-crt
)

SUBTARGETS_PART2=(
	mingw-w64-runtime-post
	binutils
	binutils-post
	$GCC_NAME
	gcc-post
	mingw-w64-libraries-libmangle
	#mingw-w64-libraries-pseh
	mingw-w64-tools-gendef
	mingw-w64-tools-genidl
	mingw-w64-tools-genpeimg
	mingw-w64-tools-widl
	libgnurx
	bzip2
	libffi
	expat
	#tcl
	#tk
	#xz
	sqlite
	ncurses
	readline
	python2
	#python3
	3rdparty-post
	gdbinit
	gdb
	gdb-wrapper
	make_cvs
	cleanup
	licenses
	put-versions
	put-info
	tests
	$([[ $COMPRESSING_MINGW == yes ]] && echo mingw-compress)
)

[[ ${BUILD_ARCHITECTURES[@]} =~ x32 && ${BUILD_ARCHITECTURES[@]} =~ x64 ]] && {
	build_for_both=1
} || {
	build_for_both=0
}

[[ $USE_MULTILIB == yes || $build_for_both == 1 ]] && {
	SUBTARGETS=(
		${LIBICONV_X32_SUBTARGETS[@]}
		${LIBICONV_X64_SUBTARGETS[@]}
		${ZLIB_X32_SUBTARGETS[@]}
		${ZLIB_X64_SUBTARGETS[@]}		
		${SUBTARGETS_PART1[@]}
		${WINPTHREADS_X32_SUBTARGETS[@]}
		${WINPTHREADS_X64_SUBTARGETS[@]}
		${SUBTARGETS_PART2[@]}
	)
} || {
	[[ ${BUILD_ARCHITECTURES[@]} =~ x32 ]] && {
		SUBTARGETS=(
			${LIBICONV_X32_SUBTARGETS[@]}
			${ZLIB_X32_SUBTARGETS[@]}
			${SUBTARGETS_PART1[@]}
			${WINPTHREADS_X32_SUBTARGETS[@]}
			${SUBTARGETS_PART2[@]}
		)
	} || {
		SUBTARGETS=(
			${LIBICONV_X64_SUBTARGETS[@]}
			${ZLIB_X64_SUBTARGETS[@]}
			${SUBTARGETS_PART1[@]}
			${WINPTHREADS_X64_SUBTARGETS[@]}
			${SUBTARGETS_PART2[@]}
		)
	}
}

# **************************************************************************

[[ $PRELOAD_MODE == yes || $DOWNLOAD_MODE == yes ]] && {
	[[ $PRELOAD_MODE == yes ]] && {
		echo -n "-> preload sources for building MinGW-${GCC_NAME}-"
	} || {
		[[ $DOWNLOAD_MODE == yes ]] && {
			echo -n "-> download sources for MinGW-${GCC_NAME}-"
		}
	}
	[[ $USE_MULTILIB == yes && $EXCEPTIONS_MODEL == sjlj ]] && echo -n "multilib-"
	[[ $build_for_both == 1 ]] && {
		echo -n "x32/x64-"
	} || {
		[[ ${BUILD_ARCHITECTURES[@]} =~ x32 ]] && echo -n "x32-" || echo -n "x64-"
	}
	echo "$EXCEPTIONS_MODEL"

	for sub in ${SUBTARGETS[@]}; do
		[[ $sub == put-versions || $sub == put-info ]] && continue
		[[ -n $( grep 'URL=' $TOP_DIR/scripts/${sub}.sh ) ]] && {
			echo -e "-> \E[32;40m$sub\E[37;40m"
			[[ ! -f $TOP_DIR/scripts/$sub.sh ]] && {
				echo "script for subtarget \"$sub\" is not exists. terminate."
				exit 1
			}

			NAME=""
			cd $TOP_DIR && . ./scripts/$sub.sh

			[[ -z $NAME ]] && continue

			mkdir -p $SRCS_DIR/$SRC_DIR_NAME

			func_download \
				$SRCS_DIR \
				$SRC_DIR_NAME \
				$TYPE \
				$URL \
				$SRCS_DIR/$SRC_DIR_NAME/download.log \
				$SRCS_DIR/$SRC_DIR_NAME/_download.marker \
				$( grep 'REV=' $TOP_DIR/scripts/${sub}.sh | sed 's|REV=||' )
			func_res=$?
			[[ $func_res != 0 ]] && {
				[[ $SHOW_LOG_ON_ERROR == yes ]] && $LOGVIEWER $SRCS_DIR/$SRC_DIR_NAME/download.log &
				exit $func_res
			}

			func_uncompress \
				$SRCS_DIR \
				$SRC_DIR_NAME \
				$TYPE \
				$SRCS_DIR/$SRC_DIR_NAME/_uncompress.marker \
				$SRCS_DIR/$SRC_DIR_NAME/uncompress.log
			func_res=$?
			[[ $func_res != 0 ]] && {
				[[ $SHOW_LOG_ON_ERROR == yes ]] && $LOGVIEWER $SRCS_DIR/$SRC_DIR_NAME/uncompress.log &
				exit $func_res
			}
		}
	done
}

[[ $DOWNLOAD_MODE == yes ]] && {
	echo "-> sources downloaded successfully."
	exit 0
}

# **************************************************************************

for ARCHITECTURE in ${BUILD_ARCHITECTURES[@]}; do
	[[ -n $REV_NUM ]] && REV_STRING="-r$REV_NUM" || REV_STRING=""
	GCC_PART_NAME=${GCC_NAME/gcc-/}
	GCC_PART_NAME=${GCC_PART_NAME/-branch/b}
	GCC_TYPE_STRING=$(func_map_gcc_name_to_gcc_type $GCC_NAME)
	PREREQ_BUILD_DIR=$ROOT_DIR/prereq-build
	PREREQ_LOGS_DIR=$ROOT_DIR/prereq-logs
	BASE_BUILD_DIR=$ROOT_DIR/$ARCHITECTURE-$GCC_PART_NAME-$THREADS_MODEL-$EXCEPTIONS_MODEL${REV_STRING}
	BUILDS_DIR=$BASE_BUILD_DIR/build
	LIBS_DIR=$BASE_BUILD_DIR/libs
	LOGS_DIR=$BASE_BUILD_DIR/logs
	PREFIX=$BASE_BUILD_DIR/prefix

	MINGW_BUILD_NAME=$ARCHITECTURE-${GCC_NAME/gcc-/}
	MINGW_BUILD_NAME=$MINGW_BUILD_NAME$([[ $USE_MULTILIB == yes ]] && echo -n -multilib)-$THREADS_MODEL-$EXCEPTIONS_MODEL
	MINGW_BUILD_NAME=$MINGW_BUILD_NAME$([[ -n $REV_NUM ]] && echo -n -rev$REV_NUM)
	echo "-> start building $MINGW_BUILD_NAME"

	[[ $ARCHITECTURE == x32 ]] && {
		HOST=i686-w64-mingw32
		BUILD=i686-w64-mingw32
		TARGET=i686-w64-mingw32
		
		[[ $USE_MULTILIB == yes ]] && {
			TVIN_HOST=x86_64-w64-mingw32
			TVIN_BUILD=x86_64-w64-mingw32
			TVIN_TARGET=x86_64-w64-mingw32
		}
		
		[[ $USE_MULTILIB == yes ]] && {
			ENABLE_TARGETS=i686-w64-mingw32,x86_64-w64-mingw32
		} || {
			ENABLE_TARGETS=i686-w64-mingw32
		}
		[[ ! -f $x32_HOST_MINGW_PATH/bin/gcc.exe ]] && {
			echo "gcc.exe is not exists in the \"$x32_HOST_MINGW_PATH/bin\" directory. terminate."
			exit 1
		}
		export PATH=$LIBS_DIR/bin:$PREREQ_DIR/$HOST-$LINK_TYPE_SUFFIX/bin:$PREFIX/opt/bin:$x32_HOST_MINGW_PATH/bin:$PREFIX/bin:$ORIGINAL_PATH
	} || {
		HOST=x86_64-w64-mingw32
		BUILD=x86_64-w64-mingw32
		TARGET=x86_64-w64-mingw32
		
		[[ $USE_MULTILIB == yes ]] && {
			TVIN_HOST=i686-w64-mingw32
			TVIN_BUILD=i686-w64-mingw32
			TVIN_TARGET=i686-w64-mingw32
		}
		
		[[ $USE_MULTILIB == yes ]] && {
			ENABLE_TARGETS=x86_64-w64-mingw32,i686-w64-mingw32
		} || {
			ENABLE_TARGETS=x86_64-w64-mingw32
		}
		[[ ! -f $x64_HOST_MINGW_PATH/bin/gcc.exe ]] && {
			echo "gcc.exe is not exists in the \"$x64_HOST_MINGW_PATH/bin\" directory. terminate."
			exit 1
		}
		export PATH=$LIBS_DIR/bin:$PREREQ_DIR/$HOST-$LINK_TYPE_SUFFIX/bin:$PREFIX/opt/bin:$x64_HOST_MINGW_PATH/bin:$PREFIX/bin:$ORIGINAL_PATH
	}

	mkdir -p $BASE_BUILD_DIR $BUILDS_DIR $LIBS_DIR $LOGS_DIR $PREFIX $PREREQ_BUILD_DIR $PREREQ_LOGS_DIR

	COMMON_CFLAGS="$BASE_CFLAGS -I$LIBS_DIR/include -I$PREREQ_DIR/$ARCHITECTURE-zlib/include -I$PREREQ_DIR/$HOST-$LINK_TYPE_SUFFIX/include"
	COMMON_CXXFLAGS="$COMMON_CFLAGS"
	COMMON_CPPFLAGS="$BASE_CPPFLAGS"
	COMMON_LDFLAGS="$BASE_LDFLAGS -L$LIBS_DIR/lib -L$PREREQ_DIR/$ARCHITECTURE-zlib/lib -L$PREREQ_DIR/$HOST-$LINK_TYPE_SUFFIX/lib -L$PREFIX/opt/lib"

	[[ $USE_MULTILIB == yes ]] && {
		SUBTARGETS=(
			${LIBICONV_X32_SUBTARGETS[@]}
			${LIBICONV_X64_SUBTARGETS[@]}
			${ZLIB_X32_SUBTARGETS[@]}
			${ZLIB_X64_SUBTARGETS[@]}	
			${SUBTARGETS_PART1[@]}
			${WINPTHREADS_X32_SUBTARGETS[@]}
			${WINPTHREADS_X64_SUBTARGETS[@]}
			${SUBTARGETS_PART2[@]}
		)
		PROCESSOR_OPTIMIZATION="--with-arch-32=$PROCESSOR_OPTIMIZATION_ARCH_32 --with-arch-64=$PROCESSOR_OPTIMIZATION_ARCH_64"
		PROCESSOR_TUNE="--with-tune-32=$PROCESSOR_OPTIMIZATION_TUNE_32 --with-tune-64=$PROCESSOR_OPTIMIZATION_TUNE_64"
	} || {
		[[ $ARCHITECTURE == x32 ]] && {
			SUBTARGETS=(
				${LIBICONV_X32_SUBTARGETS[@]}
				${ZLIB_X32_SUBTARGETS[@]}
				${SUBTARGETS_PART1[@]}
				${WINPTHREADS_X32_SUBTARGETS[@]}
				${SUBTARGETS_PART2[@]}
			)
			PROCESSOR_OPTIMIZATION="--with-arch=$PROCESSOR_OPTIMIZATION_ARCH_32"
			PROCESSOR_TUNE="--with-tune=$PROCESSOR_OPTIMIZATION_TUNE_32"
		} || {
			SUBTARGETS=(
				${LIBICONV_X64_SUBTARGETS[@]}
				${ZLIB_X64_SUBTARGETS[@]}
				${SUBTARGETS_PART1[@]}
				${WINPTHREADS_X64_SUBTARGETS[@]}
				${SUBTARGETS_PART2[@]}
			)
			PROCESSOR_OPTIMIZATION="--with-arch=$PROCESSOR_OPTIMIZATION_ARCH_64"
			PROCESSOR_TUNE="--with-tune=$PROCESSOR_OPTIMIZATION_TUNE_64"
		}
	}

	for sub in ${SUBTARGETS[@]}; do
		echo -e "-> \E[32;40m$sub\E[37;40m"
		[[ ! -f $TOP_DIR/scripts/$sub.sh ]] && {
			echo "script for subtarget \"$sub\" is not exists. terminate."
			exit 1
		}

		NAME=""
		PRIORITY=""
		EXECUTE_AFTER_DOWNLOAD=()
		EXECUTE_AFTER_UNCOMPRESS=()
		EXECUTE_AFTER_PATCH=()
		EXECUTE_AFTER_INSTALL=()

		cd $TOP_DIR && . ./scripts/$sub.sh
	
		[[ $sub == "gcc-post" ]] && {
			echo -n "--> Switching to new compiler..."
			export PATH=$PREFIX/bin:$PREFIX/opt/bin:$LIBS_DIR/bin:$ORIGINAL_PATH
			echo "done"
		}

		[[ -z $NAME ]] && continue

		case $PRIORITY in
			prereq | runtime)
				CURR_LOGS_DIR=$PREREQ_LOGS_DIR
				CURR_BUILD_DIR=$PREREQ_BUILD_DIR
			;;
			main | extra)
				CURR_LOGS_DIR=$LOGS_DIR
				CURR_BUILD_DIR=$BUILDS_DIR
			;;
			*)
				CURR_LOGS_DIR=$LOGS_DIR
				CURR_BUILD_DIR=$BUILDS_DIR			
			;;
		esac
		
		DOWNLOAD_LOG=$SRCS_DIR/$SRC_DIR_NAME/download.log
		DOWNLOAD_MARKER=$SRCS_DIR/$SRC_DIR_NAME/_download.marker
		UNCOMPRESS_LOG=$SRCS_DIR/$SRC_DIR_NAME/uncompress.log
		UNCOMPRESS_MARKER=$SRCS_DIR/$SRC_DIR_NAME/_uncompress.marker
		CONFIGURE_LOG=$CURR_LOGS_DIR/$NAME/configure.log
		MAKE_LOG=$CURR_LOGS_DIR/$NAME/make.log
		INSTALL_LOG=$CURR_LOGS_DIR/$NAME/install.log

		mkdir -p $SRCS_DIR/$SRC_DIR_NAME
		mkdir -p {$CURR_LOGS_DIR/,$CURR_BUILD_DIR/}$NAME
		#[[ $NAME != $SRC_DIR_NAME ]] && mkdir -p {$BUILDS_DIR/,$LOGS_DIR/}$NAME

		func_download \
			$SRCS_DIR \
			$SRC_DIR_NAME \
			$TYPE \
			$URL \
			$DOWNLOAD_LOG \
			$DOWNLOAD_MARKER \
			$( grep 'REV=' $TOP_DIR/scripts/${sub}.sh | sed 's|REV=||' )
		func_res=$?
		[[ $func_res != 0 ]] && {
			[[ $SHOW_LOG_ON_ERROR == yes ]] && $LOGVIEWER $DOWNLOAD_LOG &
			exit $func_res
		}

		func_uncompress \
			$SRCS_DIR \
			$SRC_DIR_NAME \
			$TYPE \
			$UNCOMPRESS_MARKER \
			$UNCOMPRESS_LOG
		func_res=$?
		[[ $func_res != 0 ]] && {
			[[ $SHOW_LOG_ON_ERROR == yes ]] && $LOGVIEWER $UNCOMPRESS_LOG &
			exit $func_res
		}

		[[ ${#EXECUTE_AFTER_UNCOMPRESS[@]} >0 ]] && {
			func_execute \
				$SRCS_DIR \
				$SRC_DIR_NAME \
				"execute commands..." \
				"after_unpack" \
				$CURR_LOGS_DIR \
				EXECUTE_AFTER_UNCOMPRESS[@]
			func_res=$?
			[[ $func_res != 0 ]] && {
				[[ $SHOW_LOG_ON_ERROR == yes ]] && $LOGVIEWER $SRCS_DIR/$SRC_DIR_NAME/exec-after_unpack-$_index.log &
				exit $func_res
			}
		}

		func_apply_patches \
			$SRCS_DIR \
			$SRC_DIR_NAME \
			$CURR_LOGS_DIR \
			$PATCHES_DIR \
			PATCHES[@]
		func_res=$?
		[[ $func_res != 0 ]] && {
			[[ $SHOW_LOG_ON_ERROR == yes ]] && $LOGVIEWER $SRCS_DIR/$SRC_DIR_NAME/patch-$_index.log &
			exit $func_res
		}

		[[ ${#EXECUTE_AFTER_PATCH[@]} >0 ]] && {
			func_execute \
				$SRCS_DIR \
				$SRC_DIR_NAME \
				"execute commands..." \
				"after_patch" \
				$CURR_LOGS_DIR \
				EXECUTE_AFTER_PATCH[@]
			func_res=$?
			[[ $func_res != 0 ]] && {
				[[ $SHOW_LOG_ON_ERROR == yes ]] && $LOGVIEWER $SRCS_DIR/$SRC_DIR_NAME/exec-after_patch-$_index.log &
				exit $func_res
			}
		}

		[[ ${#CONFIGURE_FLAGS[@]} >0 ]] && {
			configure_flags="${CONFIGURE_FLAGS[@]}"
			func_configure \
				$NAME \
				$SRC_DIR_NAME \
				"$configure_flags" \
				$CONFIGURE_LOG \
				$CURR_BUILD_DIR
			func_res=$?
			[[ $func_res != 0 ]] && {
				[[ $SHOW_LOG_ON_ERROR == yes ]] && $LOGVIEWER $CONFIGURE_LOG &
				exit $func_res
			}
		}

		[[ ${#MAKE_FLAGS[@]} >0 ]] && {
			make_flags="/bin/make ${MAKE_FLAGS[@]}"
			func_make \
				$NAME \
				$SRC_DIR_NAME \
				"$make_flags" \
				$MAKE_LOG \
				"building..." \
				"built" \
				$CURR_BUILD_DIR
			func_res=$?
			[[ $func_res != 0 ]] && {
				[[ $SHOW_LOG_ON_ERROR == yes ]] && $LOGVIEWER $MAKE_LOG &
				exit $func_res
			}
		}

		[[ ${#INSTALL_FLAGS[@]} >0 ]] && {
			install_flags="/bin/make ${INSTALL_FLAGS[@]}"
			func_make \
				$NAME \
				$SRC_DIR_NAME \
				"$install_flags" \
				$INSTALL_LOG \
				"installing..." \
				"installed" \
				$CURR_BUILD_DIR
			func_res=$?
			[[ $func_res != 0 ]] && {
				[[ $SHOW_LOG_ON_ERROR == yes ]] && $LOGVIEWER $INSTALL_LOG &
				exit $func_res
			}
		}
		
		[[ ${#EXECUTE_AFTER_INSTALL[@]} >0 ]] && {
			func_execute \
				$SRCS_DIR \
				$SRC_DIR_NAME \
				"execute commands..." \
				"after_install" \
				$CURR_LOGS_DIR \
				EXECUTE_AFTER_INSTALL[@]
			func_res=$?
			[[ $func_res != 0 ]] && {
				[[ $SHOW_LOG_ON_ERROR == yes ]] && $LOGVIEWER $SRCS_DIR/$SRC_DIR_NAME/exec-after_install-$_index.log &
				exit $func_res
			}
		}
   done
done

# ***************************************************************************

[[ $COMPRESSING_SRCS == yes ]] && {
	echo -e "-> \E[32;40mcompress mingw sources\E[37;40m"
	cd $TOP_DIR && . ./scripts/srcs-compress.sh
}

# ***************************************************************************

[[ $UPLOAD_BIN_TO_SF == yes ]] && {
	cd $TOP_DIR; . ./scripts/upload.sh
	[[ -z $SF_USER ]] && {
		echo "user name is not specified. terminate."
		exit 0
	}

	for ARCHITECTURE in ${BUILD_ARCHITECTURES[@]}; do
		mingw_archive_name=$( \
			func_create_mingw_archive_name \
				$ARCHIVES_DIR \
				$SRCS_DIR \
				$GCC_NAME \
				$ARCHITECTURE \
				$EXCEPTIONS_MODEL \
				$THREADS_MODEL \
				$REV_NUM \
		)

		upload_cmd=$( \
			func_create_mingw_upload_cmd \
				$ARCHIVES_DIR \
				$SF_USER \
				$GCC_NAME \
				$mingw_archive_name \
				$ARCHITECTURE \
				$THREADS_MODEL \
				$EXCEPTIONS_MODEL \
		)
		echo -e -n "-> \E[32;40mupload $ARCHITECTURE archive...\E[37;40m"
#		echo "mingw_upload: ${upload_cmd}"
		eval "${upload_cmd} > $LOGS_DIR/$GCC_NAME/$ARCHITECTURE-upload.log 2>&1"

		func_res=$?
		[[ $func_res != 0 ]] && {
			echo "upload finished with error($func_res). terminate."
			exit $func_res
		} || {
			echo "done"
		}
	done
}

[[ $UPLOAD_SRC_TO_SF == yes ]] && {
	cd $TOP_DIR; . ./scripts/upload.sh
	[[ -z $SF_USER ]] && {
		echo "user name is not specified. terminate."
		exit 0
	}
	
	sources_archive_name=$( \
		func_create_sources_archive_name \
			$ARCHIVES_DIR \
			$SRCS_DIR \
			$GCC_NAME \
			$REV_NUM \
	)
	upload_cmd=$( \
		func_create_sources_upload_cmd \
			$ARCHIVES_DIR \
			$SF_USER \
			$GCC_NAME \
			$sources_archive_name \
	)
#	echo "mingw_upload: ${upload_cmd}"
	eval "${upload_cmd} > $LOGS_DIR/$GCC_NAME/sources-upload.log 2>&1"
	func_res=$?
	[[ $func_res != 0 ]] && {
		echo "upload finished with error($func_res). terminate."
		exit $func_res
	}
}

exit 0

# ***************************************************************************
