Home | History | Annotate | Download | only in x86_64-w64-mingw32-4.8
      1 #!/bin/sh
      2 #
      3 # Copyright (C) 2016 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 #
     17 # Rebuild the mingw64 cross-toolchain from scratch
     18 #
     19 # See --help for usage example.
     20 
     21 PROGNAME=$(basename $0)
     22 PROGDIR=$(dirname $0)
     23 PROGDIR=$(cd $PROGDIR && pwd)
     24 ANDROID_BUILD_TOP=$(realpath $PROGDIR/../..)
     25 TOOLCHAIN_DIR=$(realpath $ANDROID_BUILD_TOP/toolchain)
     26 
     27 HELP=
     28 VERBOSE=2
     29 
     30 # This will be reset later.
     31 LOG_FILE=/dev/null
     32 
     33 panic ()
     34 {
     35     1>&2 echo "Error: $@"
     36     exit 1
     37 }
     38 
     39 fail_panic ()
     40 {
     41     if [ $? != 0 ]; then
     42         panic "$@"
     43     fi
     44 }
     45 
     46 var_value ()
     47 {
     48     eval echo \"$1\"
     49 }
     50 
     51 var_append ()
     52 {
     53     local _varname=$1
     54     local _varval=$(var_value $_varname)
     55     shift
     56     if [ -z "$_varval" ]; then
     57         eval $_varname=\"$*\"
     58     else
     59         eval $_varname=\$$_varname\" $*\"
     60     fi
     61 }
     62 
     63 run ()
     64 {
     65     if [ "$VERBOSE" -gt 0 ]; then
     66         echo "COMMAND: >>>> $@" >> $LOG_FILE
     67     fi
     68     if [ "$VERBOSE" -gt 1 ]; then
     69         echo "COMMAND: >>>> $@"
     70     fi
     71     if [ "$VERBOSE" -gt 1 ]; then
     72         "$@"
     73     else
     74        "$@" > /dev/null 2>&1
     75     fi
     76 }
     77 
     78 log ()
     79 {
     80     if [ "$LOG_FILE" ]; then
     81         echo "$@" >> $LOG_FILE
     82     fi
     83     if [ "$VERBOSE" -gt 0 ]; then
     84         echo "$@"
     85     fi
     86 }
     87 
     88 NUM_CORES=$(grep -c -e '^processor' /proc/cpuinfo)
     89 JOBS=$(( $NUM_CORES * 2 ))
     90 
     91 GMP_VERSION=5.0.5
     92 MPFR_VERSION=3.1.1
     93 MPC_VERSION=1.0.1
     94 BINUTILS_VERSION=2.25
     95 GCC_VERSION=4.8.3
     96 MINGW_W64_VERSION=v5.0.0
     97 
     98 TARGET_ARCH=x86_64
     99 TARGET_MULTILIBS=true  # not empty to enable multilib
    100 CLEANUP=
    101 
    102 OPT_GCC_VERSION=
    103 
    104 for opt; do
    105     optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
    106     case $opt in
    107         -h|-?|--help) HELP=true;;
    108         --verbose) VERBOSE=$(( $VERBOSE + 1 ));;
    109         --quiet) VERBOSE=$(( $VERBOSE - 1 ));;
    110         -j*|--jobs=*) JOBS=$optarg;;
    111         --target-arch=*) TARGET_ARCH=$optarg;;
    112         --no-multilib) TARGET_MULTILIBS="";;
    113         --gcc-version=*) OPT_GCC_VERSION=$optarg;;
    114         --cleanup) CLEANUP=true;;
    115         -*) panic "Unknown option '$opt', see --help for list of valid ones.";;
    116         *) panic "This script doesn't take any parameter, see --help for details.";;
    117     esac
    118 done
    119 
    120 
    121 if [ "$HELP" ]; then
    122     cat <<EOF
    123 Usage: $PROGNAME [options]
    124 
    125 This program is used to rebuild a mingw64 cross-toolchain from scratch.
    126 
    127 All toolchain binaries can generate both Win32 and Win64 executables. Use -m32
    128 or -m64 at compile/link time to select a specific target.
    129 
    130 Valid options:
    131   -h|-?|--help                 Print this message."
    132   --verbose                    Increase verbosity."
    133   --quiet                      Decrease verbosity."
    134   --jobs=<num>                 Run <num> build tasks in parallel [$JOBS]."
    135   -j<num>                      Same as --jobs=<num>."
    136   --no-multilib                Disable multilib toolchain build."
    137   --target-arch=<arch>         Select default target architecture [$TARGET_ARCH]."
    138   --gcc-version=<version>      Select alternative GCC version [$GCC_VERSION]"
    139 EOF
    140     exit 0
    141 fi
    142 
    143 if [ "$OPT_GCC_VERSION" ]; then
    144     GCC_VERSION=$OPT_GCC_VERSION
    145 fi
    146 
    147 GCC_SRC_DIR=$TOOLCHAIN_DIR/gcc/gcc-$GCC_VERSION
    148 if [ ! -d "$GCC_SRC_DIR" ]; then
    149     panic "Missing GCC source directory: $GCC_SRC_DIR"
    150 fi
    151 
    152 GCC_MAJOR_MINOR=$(echo "$GCC_VERSION" | cut -d. -f1-2)
    153 
    154 # Top level out directory.
    155 OUT_DIR=$ANDROID_BUILD_TOP/out
    156 
    157 # Name of the directory inside the package.
    158 PACKAGE_DIR=x86_64-w64-mingw32-$GCC_MAJOR_MINOR
    159 
    160 # Directory to isolate the install package from any similarly named directories.
    161 OUTER_INSTALL_DIR=$OUT_DIR/install
    162 
    163 # Actual install path.
    164 INSTALL_DIR=$OUTER_INSTALL_DIR/$PACKAGE_DIR
    165 
    166 # Install directory for build dependencies that are not in the final package
    167 # (gmp and whatnot).
    168 SUPPORT_DIR=$INSTALL_DIR
    169 
    170 # For the final artifacts. Will be archived on the build server.
    171 if [ -z "$DIST_DIR" ]; then
    172   DIST_DIR=$OUT_DIR/dist
    173 fi
    174 
    175 BUILD_TAG64=x86_64-linux-gnu
    176 BUILD_TAG32=i686-linux-gnu
    177 
    178 # We don't want debug executables
    179 BUILD_CFLAGS="-O2 -fomit-frame-pointer -s"
    180 BUILD_LDFLAGS=""
    181 
    182 rm -rf $OUT_DIR
    183 mkdir -p $OUT_DIR
    184 mkdir -p $INSTALL_DIR
    185 mkdir -p $DIST_DIR
    186 mkdir -p $SUPPORT_DIR
    187 
    188 LOG_FILE=$OUT_DIR/build.log
    189 rm -f $LOG_FILE && touch $LOG_FILE
    190 if [ "$VERBOSE" -eq 1 ]; then
    191     echo  "To follow build, use in another terminal: tail -F $LOG_FILE"
    192 fi
    193 
    194 case $TARGET_ARCH in
    195     x86_64) TARGET_BITS=64;;
    196     i686) TARGET_BITS=32;;
    197     *) panic "Invalid --target parameter. Valid values are: x86_64 i686";;
    198 esac
    199 TARGET_TAG=$TARGET_ARCH-w64-mingw32
    200 log "Target arch: $TARGET_TAG"
    201 log "Target bits: $TARGET_BITS"
    202 
    203 HOST_ARCH=x86_64
    204 HOST_BITS=64
    205 
    206 HOST_TAG=$HOST_ARCH-linux-gnu
    207 log "Host arch: $HOST_TAG"
    208 
    209 # Copy this script
    210 cp $0 $INSTALL_DIR/ &&
    211 echo "This file has been automatically generated on $(date) with the following command:" > $INSTALL_DIR/README &&
    212 echo "$PROGNAME $@" >> $INSTALL_DIR/README &&
    213 echo "" >> $INSTALL_DIR/README &&
    214 echo "The MD5 hashes for the original sources packages are:" >> $INSTALL_DIR/README
    215 fail_panic "Could not copy script to installation directory."
    216 
    217 PREFIX_FOR_TARGET=$INSTALL_DIR/$TARGET_TAG
    218 WITH_WIDL=$INSTALL_DIR/bin
    219 MINGW_W64_SRC=$TOOLCHAIN_DIR/mingw/mingw-w64-$MINGW_W64_VERSION
    220 
    221 setup_host_build_env ()
    222 {
    223     local BINPREFIX=$ANDROID_BUILD_TOP/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8/bin/x86_64-linux-
    224 
    225     CC=${BINPREFIX}gcc
    226     CXX=${BINPREFIX}g++
    227     LD=${BINPREFIX}ld
    228     AS=${BINPREFIX}as
    229     AR=${BINPREFIX}ar
    230     RANLIB=${BINPREFIX}ranlib
    231     STRIP=${BINPREFIX}strip
    232     export CC CXX LD AS AR RANLIB STRIP
    233 
    234     export CFLAGS="$BUILD_CFLAGS"
    235     export CXXFLAGS="$BUILD_CFLAGS"
    236     export LDFLAGS="$BUILD_LDFLAGS"
    237 }
    238 
    239 setup_mingw_build_env ()
    240 {
    241     local BINPREFIX=$INSTALL_DIR/bin/x86_64-w64-mingw32-
    242 
    243     CC=${BINPREFIX}gcc
    244     CXX=${BINPREFIX}g++
    245     LD=${BINPREFIX}ld
    246     AS=${BINPREFIX}as
    247     AR=${BINPREFIX}ar
    248     RANLIB=${BINPREFIX}ranlib
    249     RC=${BINPREFIX}windres
    250     STRIP=${BINPREFIX}strip
    251     export CC CXX LD AS AR RANLIB RC STRIP
    252 
    253 }
    254 
    255 setup_install_env ()
    256 {
    257     export PATH=$INSTALL_DIR/bin:$PATH
    258 }
    259 
    260 build_binutils_package ()
    261 {
    262     local PKGNAME=$1
    263     shift
    264 
    265     (
    266         mkdir -p $OUT_DIR/$PKGNAME &&
    267         cd $OUT_DIR/$PKGNAME &&
    268         setup_host_build_env &&
    269         log "$PKGNAME: Configuring" &&
    270         run $TOOLCHAIN_DIR/binutils/$PKGNAME/configure "$@"
    271         fail_panic "Can't configure $PKGNAME !!"
    272 
    273         log "$PKGNAME: Building" &&
    274         run make -j$JOBS MAKEINFO=true
    275         fail_panic "Can't build $PKGNAME !!"
    276 
    277         log "$PKGNAME: Installing" &&
    278         run make install MAKEINFO=true
    279         fail_panic "Can't install $PKGNAME"
    280     ) || exit 1
    281 }
    282 
    283 # The GCC build in Android is insane and stores gmp and friends as tarballs and
    284 # extracts them as a part of the build step (in the meta-configure of all
    285 # places). No one understands how any of that mess works, so just deal with
    286 # extracting them here...
    287 EXTRACTED_PACKAGES=$OUT_DIR/packages
    288 mkdir -p $EXTRACTED_PACKAGES
    289 fail_panic "Could not create directory for packages."
    290 
    291 log "gmp-$GMP_VERSION: Extracting" &&
    292 tar xf $TOOLCHAIN_DIR/gmp/gmp-$GMP_VERSION.tar.bz2 -C $EXTRACTED_PACKAGES
    293 log "mpfr-$MPFR_VERSION: Extracting" &&
    294 tar xf $TOOLCHAIN_DIR/mpfr/mpfr-$MPFR_VERSION.tar.bz2 -C $EXTRACTED_PACKAGES
    295 log "mpc-$MPC_VERSION: Extracting" &&
    296 tar xf $TOOLCHAIN_DIR/mpc/mpc-$MPC_VERSION.tar.gz -C $EXTRACTED_PACKAGES
    297 
    298 build_host_package ()
    299 {
    300     local PKGNAME=$1
    301     shift
    302 
    303     (
    304         mkdir -p $OUT_DIR/$PKGNAME &&
    305         cd $OUT_DIR/$PKGNAME &&
    306         setup_host_build_env &&
    307         log "$PKGNAME: Configuring" &&
    308         run $EXTRACTED_PACKAGES/$PKGNAME/configure "$@"
    309         fail_panic "Can't configure $PKGNAME !!"
    310 
    311         log "$PKGNAME: Building" &&
    312         run make -j$JOBS
    313         fail_panic "Can't build $PKGNAME !!"
    314 
    315         log "$PKGNAME: Installing" &&
    316         run make install
    317         fail_panic "Can't install $PKGNAME"
    318     ) || exit 1
    319 }
    320 
    321 export ABI=$HOST_BITS
    322 SUPPORT_INSTALL=
    323 BASE_HOST_OPTIONS="--prefix=$SUPPORT_DIR --disable-shared"
    324 build_host_package gmp-$GMP_VERSION $BASE_HOST_OPTIONS
    325 var_append BASE_HOST_OPTIONS "--with-gmp=$SUPPORT_DIR"
    326 
    327 build_host_package mpfr-$MPFR_VERSION $BASE_HOST_OPTIONS
    328 var_append BASE_HOST_OPTIONS "--with-mpfr=$SUPPORT_DIR"
    329 
    330 build_host_package mpc-$MPC_VERSION $BASE_HOST_OPTIONS
    331 var_append BASE_HOST_OPTIONS "--with-mpc=$SUPPORT_DIR"
    332 
    333 BINUTILS_CONFIGURE_OPTIONS=$BASE_HOST_OPTIONS
    334 var_append BINUTILS_CONFIGURE_OPTIONS "--target=$TARGET_TAG --disable-nls"
    335 if [ "$TARGET_MULTILIBS" ]; then
    336     var_append BINUTILS_CONFIGURE_OPTIONS "--enable-targets=x86_64-w64-mingw32,i686-w64-mingw32"
    337 fi
    338 
    339 var_append BINUTILS_CONFIGURE_OPTIONS "--with-sysroot=$INSTALL_DIR"
    340 var_append BINUTILS_CONFIGURE_OPTIONS "--enable-lto --enable-plugin --enable-gold"
    341 
    342 build_binutils_package binutils-$BINUTILS_VERSION $BINUTILS_CONFIGURE_OPTIONS
    343 
    344 build_mingw_tools ()
    345 {
    346     local PKGNAME=$1
    347 
    348     (
    349         mkdir -p $OUT_DIR/$PKGNAME &&
    350         cd $OUT_DIR/$PKGNAME &&
    351         log "$PKGNAME: Configuring" &&
    352         run $MINGW_W64_SRC/mingw-w64-tools/widl/configure --prefix=$INSTALL_DIR --target=$TARGET_TAG --includedir=$OUT_DIR/install/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/
    353         fail_panic "Can't configure mingw-64-tools"
    354         log "$PKGNAME: Installing" &&
    355         run make install -j$JOBS
    356     ) || exit 1
    357 }
    358 
    359 build_mingw_pthreads_lib ()
    360 {
    361     local PKGNAME=$1
    362     local CONFIGURE_EXTRA_ARGS=$2
    363 
    364     (
    365         mkdir -p $OUT_DIR/$PKGNAME &&
    366         cd $OUT_DIR/$PKGNAME &&
    367         setup_mingw_build_env &&
    368         log "$PKGNAME (32-bit): Configuring" &&
    369         run $MINGW_W64_SRC/mingw-w64-libraries/winpthreads/configure --prefix=$PREFIX_FOR_TARGET --target=$TARGET_TAG --host=$TARGET_TAG $CONFIGURE_EXTRA_ARGS &&
    370         fail_panic "Can't configure $PKGNAME"
    371     ) || exit 1
    372 
    373     # run it once so fakelib/libgcc.a is created and make subsequently fails
    374     # while looking for libpthread.a.  Copy libgcc.a to libpthread.a and
    375     # retry.
    376     cd $OUT_DIR/$PKGNAME && run make install -j$JOBS
    377 
    378     (
    379         cd $OUT_DIR/$PKGNAME
    380         cp fakelib/libgcc.a fakelib/libpthread.a &&
    381         log "$PKGNAME: Installing" &&
    382         run make install -j$JOBS
    383     ) || exit 1
    384 }
    385 
    386 build_mingw_pthreads ()
    387 {
    388     local PKGNAME=$1
    389 
    390     (
    391         CFLAGS="$CFLAGS -m32"
    392         CXXFLAGS="$CXXFLAGS -m32"
    393         LDFLAGS="-m32"
    394         RCFLAGS="-F pe-i386"
    395         export CFLAGS CXXFLAGS LDFLAGS RCFLAGS
    396         build_mingw_pthreads_lib $PKGNAME-32 "--build=$BUILD_TAG32 --libdir=$PREFIX_FOR_TARGET/lib32"
    397         (run cp $PREFIX_FOR_TARGET/bin/libwinpthread-1.dll $PREFIX_FOR_TARGET/lib32) || exit 1
    398     )
    399 
    400     build_mingw_pthreads_lib $PKGNAME-64 "--build=$BUILD_TAG64"
    401 }
    402 
    403 # Install the right mingw64 headers into the sysroot
    404 build_mingw_headers ()
    405 {
    406     local PKGNAME=$1
    407 
    408     (
    409         mkdir -p $OUT_DIR/$PKGNAME &&
    410         cd $OUT_DIR/$PKGNAME &&
    411         log "$PKGNAME: Configuring" &&
    412         run $MINGW_W64_SRC/mingw-w64-headers/configure --prefix=$PREFIX_FOR_TARGET --host=$TARGET_TAG \
    413             --build=$HOST_TAG --enable-sdk=all --enable-secure-api
    414         fail_panic "Can't configure mingw-64-headers"
    415 
    416         run make
    417         log "$PKGNAME: Installing" &&
    418         run make install -j$JOBS &&
    419         run cd $INSTALL_DIR &&
    420         run ln -s $TARGET_TAG mingw &&
    421         run cd $INSTALL_DIR/mingw &&
    422         run ln -s lib lib$TARGET_BITS
    423         fail_panic "Can't install mingw-64-headers"
    424     ) || exit 1
    425 }
    426 
    427 # Slightly different from build_host_package because we need to call
    428 # 'make all-gcc' and 'make install-gcc' as a special case.
    429 #
    430 build_core_gcc ()
    431 {
    432     local PKGNAME=$1
    433     shift
    434 
    435     (
    436         mkdir -p $OUT_DIR/$PKGNAME &&
    437         cd $OUT_DIR/$PKGNAME &&
    438         setup_host_build_env &&
    439         log "core-$PKGNAME: Configuring" &&
    440         run $TOOLCHAIN_DIR/gcc/$PKGNAME/configure "$@"
    441         fail_panic "Can't configure $PKGNAME !!"
    442 
    443         log "core-$PKGNAME: Building" &&
    444         run make -j$JOBS all-gcc
    445         fail_panic "Can't build $PKGNAME !!"
    446 
    447         log "core-$PKGNAME: Installing" &&
    448         run make -j$JOBS install-gcc
    449         fail_panic "Can't install $PKGNAME"
    450     ) || exit 1
    451 }
    452 
    453 
    454 # Build and install the C runtime files needed by the toolchain
    455 build_mingw_crt ()
    456 {
    457     local PKGNAME=$1
    458     shift
    459 
    460     (
    461         mkdir -p $OUT_DIR/$PKGNAME &&
    462         cd $OUT_DIR/$PKGNAME &&
    463         export PATH=$INSTALL_DIR/bin:$PATH
    464         log "$PKGNAME: Configuring" &&
    465         run $MINGW_W64_SRC/mingw-w64-crt/configure "$@"
    466         fail_panic "Can't configure $PKGNAME !!"
    467 
    468         log "$PKGNAME: Building" &&
    469         run make -j$JOBS
    470         fail_panic "Can't build $PKGNAME !!"
    471 
    472         log "$PKGNAME: Installing" &&
    473         run make -j$JOBS install
    474         fail_panic "Can't install $PKGNAME"
    475     ) || exit 1
    476 }
    477 
    478 
    479 build_libgcc ()
    480 {
    481     local PKGNAME=$1
    482     shift
    483 
    484     (
    485         # No configure step here! We're resuming work that was started
    486         # in build_core_gcc.
    487         cd $OUT_DIR/$PKGNAME &&
    488         setup_host_build_env &&
    489         log "libgcc-$PKGNAME: Building" &&
    490         run make -j$JOBS
    491         fail_panic "Can't build libgcc-$PKGNAME !!"
    492 
    493         log "libgcc-$PKGNAME: Installing" &&
    494         run make -j$JOBS install
    495         fail_panic "Can't install libgcc-$PKGNAME"
    496     ) || exit 1
    497 }
    498 
    499 GCC_CONFIGURE_OPTIONS=$BASE_HOST_OPTIONS
    500 var_append GCC_CONFIGURE_OPTIONS "--target=$TARGET_TAG"
    501 if [ "$TARGET_MULTILIBS" ]; then
    502     var_append GCC_CONFIGURE_OPTIONS "--enable-targets=all"
    503 fi
    504 var_append GCC_CONFIGURE_OPTIONS "--enable-languages=c,c++"
    505 var_append GCC_CONFIGURE_OPTIONS "--with-sysroot=$INSTALL_DIR"
    506 var_append GCC_CONFIGURE_OPTIONS "--enable-threads=posix"
    507 
    508 build_mingw_tools mingw-w64-tools
    509 build_mingw_headers mingw-w64-headers
    510 
    511 build_core_gcc gcc-$GCC_VERSION $GCC_CONFIGURE_OPTIONS
    512 
    513 CRT_CONFIGURE_OPTIONS="--host=$TARGET_TAG --with-sysroot=$INSTALL_DIR --prefix=$PREFIX_FOR_TARGET"
    514 if [ "$TARGET_MULTILIBS" ]; then
    515     var_append CRT_CONFIGURE_OPTIONS "--enable-lib32"
    516 fi
    517 
    518 build_mingw_crt mingw-w64-crt $CRT_CONFIGURE_OPTIONS
    519 
    520 # Build winpthreads
    521 build_mingw_pthreads mingw-w64-pthreads
    522 
    523 build_libgcc gcc-$GCC_VERSION
    524 
    525 # Let's generate the licenses/ directory
    526 LICENSE_DIRS="$SRC_DIR"
    527 var_append LICENSE_DIRS "$TOOLCHAIN_DIR/binutils/binutils-$BINUTILS_VERSION"
    528 var_append LICENSE_DIRS "$GCC_SRC_DIR"
    529 var_append LICENSE_DIRS "$EXTRACTED_PACKAGES"
    530 
    531 echo > $INSTALL_DIR/NOTICE
    532 for LICENSE in $(find $LICENSE_DIRS -name "COPYING*"); do
    533     cat $SRC_DIR/$LICENSE >> $INSTALL_DIR/NOTICE
    534 done
    535 
    536 touch $INSTALL_DIR/MODULE_LICENSE_GPL
    537 
    538 # The build server generates a repo.prop file that contains the current SHAs of
    539 # each project.
    540 REPO_PROP_PATH=$INSTALL_DIR/repo.prop
    541 if [ -f $DIST_DIR/repo.prop ]; then
    542     cp $DIST_DIR/repo.prop $REPO_PROP_PATH
    543 else
    544     # Generate our own if we're building locally.
    545     # The pushd/popd is to ensure that we're at least somewhere within our
    546     # source tree. There aren't any assumptions made about our CWD.
    547     pushd $ANDROID_BUILD_TOP
    548     repo forall \
    549         -c 'echo $REPO_PROJECT $(git rev-parse HEAD)' > $REPO_PROP_PATH
    550     popd
    551 fi
    552 
    553 PACKAGE_NAME=$DIST_DIR/$TARGET_TAG-linux-x86_64.tar.bz2
    554 log "Packaging $TARGET_TAG toolchain to $PACKAGE_NAME"
    555 run tar cjf $PACKAGE_NAME -C $OUTER_INSTALL_DIR $PACKAGE_DIR/
    556 fail_panic "Could not package $TARGET_TAG toolchain!"
    557 log "Done. See $DIST_DIR:"
    558 ls -l $PACKAGE_NAME
    559 
    560 exit 0
    561