Skip to content

Instantly share code, notes, and snippets.

@nathan-osman
Last active Dec 13, 2015
Embed
What would you like to do?
This script provides an easy way to build Qt5 for both 32 and 64-bit Windows. This script assumes that the Mingw-w64 compilers are installed on the host as well as Perl.
#!/bin/bash
#===========================================
# Download URLs for the required libraries.
#===========================================
# NOTE: if you add a URL here, you also need to add it to the
# $packages_to_build list to ensure the proper order.
declare -A urls=(
[openssl]="http://www.openssl.org/source/openssl-1.0.1e.tar.gz"
[icu]="http://download.icu-project.org/files/icu4c/50.1.2/icu4c-50_1_2-src.tgz"
[qt5]="http://releases.qt-project.org/qt5/5.0.1/single/qt-everywhere-opensource-src-5.0.1.tar.gz"
)
#===================
# End download URLs
#===================
# All of the building takes place in ~/qt5 and all of the
# files are installed to ~/<toolchain> where <toolchain>
# is one of i686-w64-mingw32 or x86_64-w64-mingw32.
script_path=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd`
build_path=`echo ~/qt5`
install_path=`echo ~`
# Methods for displaying colored output.
print_debug() { echo -e "\E[1;32m$1\E[0m"; }
print_warning() { echo -e "\E[1;33m$1\E[0m"; }
print_error() { echo -e "\E[1;31m$1\E[0m"; exit 1; }
# Determines if an array contains a certain value.
# - $1 array
# - $2 value
array_contains() {
local a=(${!1})
for i in ${a[@]} ; do
if [ $i = $2 ] ; then
return 0
fi
done
return 1
}
# Utility method to download a URL if not already in the download cache.
# - $1 download URL
download_archive() {
mkdir -p cache
cd cache
if test -e `basename $1` ; then
print_debug "'`basename $1`' already exists in cache."
else
print_debug "Downloading '`basename $1`'..."
wget $1
fi
cd ..
}
# Extracts the specified archive to the specified directory.
# - $1 the name of the package
# - $2 the architecture being built
extract_archive() {
if test -d $1-$2 ; then
print_warning "The directory '$1-$2' already exists. It will be overwritten."
yes | rm -r $1-$2
fi
mkdir -p $1-$2
cd $1-$2
print_debug "Extracting '`basename ${urls[$1]}`' to '$1-$2'..."
tar --strip-components 1 -xf ../cache/`basename ${urls[$1]}`
cd ..
}
# Additional flags passed to the linker.
static_qt5=
# Build the OpenSSL library.
# - $1 architecture
# - $2 toolchain installation path
build_openssl() {
local openssl_target=`if [ $1 = i686 ] ; then echo mingw ; else echo mingw64 ; fi`
./Configure --cross-compile-prefix=$1-w64-mingw32- --openssldir=$2 $openssl_target
make
make install
}
# Build the host copy of ICU (the current directory is expected to
# contain the 'source' directory). The build is skipped if it has completed.
build_icu_host() {
cp -r source ../icu-host
local cwd=`pwd`
cd ../icu-host
./configure
make
touch
cd $cwd
}
# Build the ICU library.
# - $1 architecture
# - $2 toolchain installation path
build_icu() {
# ICU is unique in that we need to actually have a host build and
# a target build. Begin with the host build.
cp -r source source-host
mv source source-target
cd source-host
local host_build=`pwd`
./configure
make
cd ..
cd source-target
# First, apply the two patches to the source directory.
print_debug "Patching ICU source..."
cat $script_path/icu4c-50_1_2-crossbuild.patch | patch -p2
local bit=`if [ $1 = i686 ] ; then echo 32 ; else echo 64 ; fi`
cat $script_path/icu4c-4_6_1-win$bit.patch | patch -p2
# Now continue building...
./configure --host=$1-w64-mingw32 --prefix=$2 --with-cross-build=$host_build
make
make install
cd ..
}
# Build the Qt5 library.
# - $1 architecture
# - $2 toolchain installation path
build_qt5() {
./configure -prefix $2 -opensource -confirm-license -release -nomake demos \
-nomake examples -xplatform win32-g++ -device-option CROSS_COMPILE=$1-w64-mingw32- \
-I$2/include -L$2/lib $static_qt5
make
make install
}
# By default, we build all packages for all architectures.
packages_to_build=( openssl icu qt5 )
architectures_to_build="i686 x86_64"
# Analyze the command-line arguments.
for i in `seq 1 $#` ; do
eval arg=\$$i
case $arg in
--help)
print_debug "Usage: $0 [--skip-<package>] [--only-<package>]"
print_debug " [--32] [--64] [--static]"
exit 0
;;
--skip-*)
if array_contains packages_to_build[@] ${arg:7} ; then
print_debug "${arg:7} will NOT be built."
unset packages_to_build[${arg:7}]
else
print_error "** Error: no package named ${arg:7}."
fi
;;
--only-*)
if array_contains packages_to_build[@] ${arg:7} ; then
print_debug "Only building ${arg:7}."
packages_to_build=${arg:7}
else
print_error "** Error: no package named ${arg:7}."
fi
;;
--32)
print_debug "Only building for i686."
architectures_to_build=i686
;;
--64)
print_debug "Only building for x86_64."
architectures_to_build=x86_64
;;
--static)
print_debug "Qt5 will build static libraries."
static_qt5="-static"
;;
*)
print_error "** Error: unrecognized option '$arg'."
esac
done
mkdir -p $build_path
cd $build_path
# Loop over each package and perform the build steps.
for package in $packages_to_build; do
download_archive ${urls[$package]}
# Each step below is done twice - once for each architecture.
for architecture in $architectures_to_build; do
extract_archive $package $architecture
cd $package-$architecture
# Invoke the build command for this package.
print_debug "Building $package..."
eval build_$package $architecture $install_path/$architecture-w64-mingw32
cd ..
done
done
print_debug "All packages have finished building."
--- icu/source/config/mh-mingw 2011-05-25 02:59:51.523815290 +0200
+++ icu/source/config/mh-mingw 2011-05-25 02:57:58.715695508 +0200
@@ -133,7 +133,7 @@
LDLIBRARYPATH_ENVVAR = PATH
# The type of assembly to write for generating an object file
-GENCCODE_ASSEMBLY=-a gcc-cygwin
+GENCCODE_ASSEMBLY=-a gcc-mingw-x86
# These are needed to allow the pkgdata GNU make files to work
PKGDATA_DEFS = -DU_MAKE=\"$(MAKE)\"
--- icu/source/config/mh-mingw 2011-05-25 02:59:51.523815290 +0200
+++ icu/source/config/mh-mingw 2011-05-25 02:57:58.715695508 +0200
@@ -133,7 +133,7 @@
LDLIBRARYPATH_ENVVAR = PATH
# The type of assembly to write for generating an object file
-GENCCODE_ASSEMBLY=-a gcc-cygwin
+GENCCODE_ASSEMBLY=-a gcc-mingw-x64
# These are needed to allow the pkgdata GNU make files to work
PKGDATA_DEFS = -DU_MAKE=\"$(MAKE)\"
--- icu/source/config/icu-config-bottom 2013-01-11 01:23:56.000000000 +0100
+++ icu/source/config/icu-config-bottom 2013-01-24 17:32:54.452298936 +0100
@@ -3,7 +3,7 @@
## Copyright (c) 2002-2011, International Business Machines Corporation and
## others. All Rights Reserved.
-ICUUC_FILE="${libdir}/${ICULIBS_COMMON_LIB_NAME}"
+ICUUC_FILE="${bindir}/${ICULIBS_COMMON_LIB_NAME}"
ICUUC_FILE_A="${libdir}/${ICULIBS_COMMON_LIB_NAME_A}"
# echo ENABLE RPATH $ENABLE_RPATH and RPATHLDFLAGS=${RPATH_LDFLAGS}
--- icu/source/config/icu.pc.in 2013-01-11 01:23:56.000000000 +0100
+++ icu/source/config/icu.pc.in 2013-01-24 17:33:21.745635620 +0100
@@ -1,27 +1,27 @@
# Copyright (C) 2010, International Business Machines Corporation. All Rights Reserved.
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-#bindir = @bindir@
-libdir = @libdir@
-includedir = @includedir@
-baselibs = @LIBS@
-#datarootdir = @datarootdir@
-#datadir = @datadir@
-#sbindir = @sbindir@
-#mandir = @mandir@
-#sysconfdir = @sysconfdir@
-CFLAGS = @CFLAGS@
-#CXXFLAGS = @CXXFLAGS@
-DEFS = @DEFS@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+#bindir=@bindir@
+libdir=@libdir@
+includedir=@includedir@
+baselibs=@LIBS@
+#datarootdir=@datarootdir@
+#datadir=@datadir@
+#sbindir=@sbindir@
+#mandir=@mandir@
+#sysconfdir=@sysconfdir@
+CFLAGS=@CFLAGS@
+#CXXFLAGS=@CXXFLAGS@
+DEFS=@DEFS@
UNICODE_VERSION=@UNICODE_VERSION@
ICUPREFIX=icu
ICULIBSUFFIX=@ICULIBSUFFIX@
-LIBICU=lib${ICUPREFIX}
+LIBICU=${ICUPREFIX}
#SHAREDLIBCFLAGS=-fPIC
pkglibdir=${libdir}/@PACKAGE@${ICULIBSUFFIX}/@VERSION@
#pkgdatadir=${datadir}/@PACKAGE@${ICULIBSUFFIX}/@VERSION@
-ICUDATA_NAME = icudt@LIB_VERSION_MAJOR@@ICUDATA_CHAR@
+ICUDATA_NAME=icudata@LIB_VERSION_MAJOR@@ICUDATA_CHAR@
#ICUPKGDATA_DIR=@libdir@
#ICUDATA_DIR=${pkgdatadir}
ICUDESC=International Components for Unicode
--- icu/source/config/Makefile.inc.in 2013-01-11 01:23:56.000000000 +0100
+++ icu/source/config/Makefile.inc.in 2013-01-24 18:07:14.400256655 +0100
@@ -41,7 +41,7 @@
# The prefix for ICU libraries, normally 'icu'
ICUPREFIX = icu
PACKAGE = @PACKAGE@
-LIBICU = lib$(ICUPREFIX)
+LIBICU = $(ICUPREFIX)
# Static library prefix and file extension
STATIC_PREFIX = s
@@ -106,18 +106,19 @@
# - $(ICULIBS_LAYOUT) - ICU layout library.
# - $(ICULIBS_ICUIO) - ICU stdio equivalent library
-ICULIBS_COMMON = -l$(ICUPREFIX)uc$(ICULIBSUFFIX)$(ICULIBSUFFIX_VERSION)
-ICULIBS_DATA = -l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)$(ICULIBSUFFIX_VERSION)
-ICULIBS_I18N = -l$(ICUPREFIX)$(I18N_STUBNAME)$(ICULIBSUFFIX)$(ICULIBSUFFIX_VERSION)
-ICULIBS_TOOLUTIL = -l$(ICUPREFIX)tu$(ICULIBSUFFIX)$(ICULIBSUFFIX_VERSION)
-ICULIBS_CTESTFW = -l$(ICUPREFIX)ctestfw$(ICULIBSUFFIX)$(ICULIBSUFFIX_VERSION)
-ICULIBS_ICUIO = -l$(ICUPREFIX)io$(ICULIBSUFFIX)$(ICULIBSUFFIX_VERSION)
-ICULIBS_OBSOLETE = -l$(ICUPREFIX)obsolete$(ICULIBSUFFIX)$(ICULIBSUFFIX_VERSION)
-ICULIBS_LAYOUT = -l$(ICUPREFIX)le$(ICULIBSUFFIX)$(ICULIBSUFFIX_VERSION)
-ICULIBS_LAYOUTEX = -l$(ICUPREFIX)lx$(ICULIBSUFFIX)$(ICULIBSUFFIX_VERSION)
+ICULIBS_COMMON = -l$(ICUPREFIX)uc$(ICULIBSUFFIX)
+ICULIBS_DATA = -l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)
+ICULIBS_I18N = -l$(ICUPREFIX)$(I18N_STUBNAME)$(ICULIBSUFFIX)
+ICULIBS_TOOLUTIL = -l$(ICUPREFIX)tu$(ICULIBSUFFIX)
+ICULIBS_CTESTFW = -l$(ICUPREFIX)ctestfw$(ICULIBSUFFIX)
+ICULIBS_ICUIO = -l$(ICUPREFIX)io$(ICULIBSUFFIX)
+ICULIBS_OBSOLETE = -l$(ICUPREFIX)obsolete$(ICULIBSUFFIX)
+ICULIBS_LAYOUT = -l$(ICUPREFIX)le$(ICULIBSUFFIX)
+ICULIBS_LAYOUTEX = -l$(ICUPREFIX)lx$(ICULIBSUFFIX)
ICULIBS_BASE = $(LIBS) -L$(libdir)
# for icu-config to test with
+SO = dll
ICULIBS_COMMON_LIB_NAME = ${LIBICU}${COMMON_STUBNAME}${ICULIBSUFFIX}${ICULIBSUFFIX_VERSION}.${SO}
ICULIBS_COMMON_LIB_NAME_A = ${LIBICU}${COMMON_STUBNAME}${ICULIBSUFFIX}.${A}
--- icu/source/config/mh-mingw 2013-01-11 01:23:56.000000000 +0100
+++ icu/source/config/mh-mingw 2013-01-24 18:42:02.996026071 +0100
@@ -41,8 +41,8 @@
LD_SOOPTIONS= -Wl,-Bsymbolic
## Commands to make a shared library
-SHLIB.c= $(CC) $(CFLAGS) $(LDFLAGS) -shared $(LD_SOOPTIONS) -Wl,--enable-auto-import -Wl,--out-implib=$(dir $@)$(notdir $(@:$(SO_TARGET_VERSION_MAJOR).$(SO)=))$(IMPORT_LIB_EXT)#M#
-SHLIB.cc= $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(LD_SOOPTIONS) -Wl,--enable-auto-import -Wl,--out-implib=$(dir $@)$(notdir $(@:$(SO_TARGET_VERSION_MAJOR).$(SO)=))$(IMPORT_LIB_EXT)#M#
+SHLIB.c= $(CC) $(CFLAGS) $(LDFLAGS) -shared $(LD_SOOPTIONS) -Wl,--enable-auto-import -Wl,--out-implib=$(dir $@)$(LIBPREFIX)$(notdir $(@:$(SO_TARGET_VERSION_MAJOR).$(SO)=))$(IMPORT_LIB_EXT)#M#
+SHLIB.cc= $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(LD_SOOPTIONS) -Wl,--enable-auto-import -Wl,--out-implib=$(dir $@)$(LIBPREFIX)$(notdir $(@:$(SO_TARGET_VERSION_MAJOR).$(SO)=))$(IMPORT_LIB_EXT)#M#
## Compiler switch to embed a runtime search path
LD_RPATH=
@@ -63,19 +63,15 @@
endif
# Static library prefix and file extension
-LIBSICU = $(LIBPREFIX)$(STATIC_PREFIX)$(ICUPREFIX)
+LIBSICU = $(LIBPREFIX)$(ICUPREFIX)
A = a
## An import library is needed for z/OS and MSVC
-IMPORT_LIB_EXT = .lib
+IMPORT_LIB_EXT = .dll.a
LIBPREFIX=
-# Change the stubnames so that poorly working FAT disks and installation programs can work.
-# This is also for backwards compatibility.
-DATA_STUBNAME = dt
-I18N_STUBNAME = in
-LIBICU = $(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)
+LIBICU = $(ICUPREFIX)
# The #M# is used to delete lines for icu-config
# Current full path directory.
@@ -115,7 +111,7 @@
FINAL_SO_TARGET=$(basename $(SO_TARGET))$(SO_TARGET_VERSION_MAJOR).$(SO)
MIDDLE_SO_TARGET=$(FINAL_SO_TARGET)
-FINAL_IMPORT_LIB = $(dir $(SO_TARGET))$(notdir $(basename $(SO_TARGET)))$(IMPORT_LIB_EXT)#M#
+FINAL_IMPORT_LIB = $(dir $(SO_TARGET))$(LIBPREFIX)$(notdir $(basename $(SO_TARGET)))$(IMPORT_LIB_EXT)#M#
IMPORT_LIB = $(FINAL_IMPORT_LIB)#M#
MIDDLE_IMPORT_LIB = $(FINAL_IMPORT_LIB)#M#
@@ -124,6 +120,9 @@
#ICUPKGDATA_INSTALL_DIR = $(shell cygpath -dma $(DESTDIR)$(ICUPKGDATA_DIR))#M#
#ICUPKGDATA_INSTALL_LIBDIR = $(shell cygpath -dma $(DESTDIR)$(libdir))#M#
+# The following is for Makefile.inc's use.
+ICULIBSUFFIX_VERSION = $(LIB_VERSION_MAJOR)
+
## Versioned libraries rules
#%$(SO_TARGET_VERSION_MAJOR).$(SO): %$(SO_TARGET_VERSION).$(SO)
# $(RM) $@ && cp ${<F} $@
@@ -139,5 +138,17 @@
# These are needed to allow the pkgdata GNU make files to work
PKGDATA_DEFS = -DU_MAKE=\"$(MAKE)\"
+# Just the libs.
+ICULIBS_DT = -l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)
+ICULIBS_UC = -l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(COMMON_STUBNAME)$(ICULIBSUFFIX)
+ICULIBS_I18N = -l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(I18N_STUBNAME)$(ICULIBSUFFIX)
+ICULIBS_LE = -l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(LAYOUT_STUBNAME)$(ICULIBSUFFIX)
+ICULIBS_LX = -l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(LAYOUTEX_STUBNAME)$(ICULIBSUFFIX)
+ICULIBS_IO = -l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(IO_STUBNAME)$(ICULIBSUFFIX)
+ICULIBS_CTESTFW = -l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(CTESTFW_STUBNAME)$(ICULIBSUFFIX)
+ICULIBS_TOOLUTIL = -l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(TOOLUTIL_STUBNAME)$(ICULIBSUFFIX)
+# Link commands to link to ICU libs
+LLIBDIR = -L$(LIBDIR)
+
## End Cygwin/MinGW specific setup
--- icu/source/tools/toolutil/pkg_genc.c 2013-01-11 01:23:40.000000000 +0100
+++ icu/source/tools/toolutil/pkg_genc.c 2013-01-24 17:32:54.453298904 +0100
@@ -150,6 +150,22 @@
".long ","",HEX_0X
},
+ {"gcc-mingw-x86",
+ ".globl _%s\n"
+ "\t.section .rdata,\"dr\"\n"
+ "\t.align 4\n"
+ "_%s:\n\n",
+
+ ".long ","",HEX_0X
+ },
+ {"gcc-mingw-x64",
+ ".globl %s\n"
+ "\t.section .rdata,\"dr\"\n"
+ "\t.align 16\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
+ "%s:\n\n",
+
+ ".long ","",HEX_0X
+ },
{"sun",
"\t.section \".rodata\"\n"
"\t.align 8\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment