Home | History | Annotate | Download | only in tools
      1 #!/bin/sh
      2 #
      3 # Copyright (C) 2011 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 #  This shell script is used to rebuild the prebuilt GNU libsupc++ and
     18 #  libstdc++ binaries from their sources. It requires an NDK installation
     19 #  that contains valid plaforms files and toolchain binaries.
     20 #
     21 
     22 # include common function and variable definitions
     23 . `dirname $0`/prebuilt-common.sh
     24 
     25 PROGRAM_PARAMETERS="<src-dir>"
     26 
     27 PROGRAM_DESCRIPTION=\
     28 "Rebuild the prebuilt GNU libsupc++ / libstdc++ binaries for the Android NDK.
     29 
     30 This script is called when packaging a new NDK release. It will simply
     31 rebuild the GNU libsupc++ and libstdc++ static and shared libraries from
     32 sources.
     33 
     34 This requires a temporary NDK installation containing platforms and
     35 toolchain binaries for all target architectures, as well as the path to
     36 the corresponding gcc source tree.
     37 
     38 By default, this will try with the current NDK directory, unless
     39 you use the --ndk-dir=<path> option.
     40 
     41 The output will be placed in appropriate sub-directories of
     42 <ndk>/$GNUSTL_SUBDIR/<gcc-version>, but you can override this with the --out-dir=<path>
     43 option.
     44 "
     45 GCC_VERSION_LIST=$DEFAULT_GCC_VERSION_LIST
     46 register_var_option "--gcc-version-list=<vers>" GCC_VERSION_LIST "List of GCC versions"
     47 
     48 PACKAGE_DIR=
     49 register_var_option "--package-dir=<path>" PACKAGE_DIR "Put prebuilt tarballs into <path>."
     50 
     51 NDK_DIR=
     52 register_var_option "--ndk-dir=<path>" NDK_DIR "Specify NDK root path for the build."
     53 
     54 BUILD_DIR=
     55 OPTION_BUILD_DIR=
     56 register_var_option "--build-dir=<path>" OPTION_BUILD_DIR "Specify temporary build dir."
     57 
     58 OUT_DIR=
     59 register_var_option "--out-dir=<path>" OUT_DIR "Specify output directory directly."
     60 
     61 ABIS=$(spaces_to_commas $PREBUILT_ABIS)
     62 register_var_option "--abis=<list>" ABIS "Specify list of target ABIs."
     63 
     64 NO_MAKEFILE=
     65 register_var_option "--no-makefile" NO_MAKEFILE "Do not use makefile to speed-up build"
     66 
     67 VISIBLE_LIBGNUSTL_STATIC=
     68 register_var_option "--visible-libgnustl-static" VISIBLE_LIBGNUSTL_STATIC "Do not use hidden visibility for libgnustl_static.a"
     69 
     70 WITH_DEBUG_INFO=
     71 register_var_option "--with-debug-info" WITH_DEBUG_INFO "Build with -g.  STL is still built with optimization but with debug info"
     72 
     73 register_jobs_option
     74 
     75 extract_parameters "$@"
     76 
     77 SRCDIR=$(echo $PARAMETERS | sed 1q)
     78 check_toolchain_src_dir "$SRCDIR"
     79 
     80 ABIS=$(commas_to_spaces $ABIS)
     81 
     82 # Handle NDK_DIR
     83 if [ -z "$NDK_DIR" ] ; then
     84     NDK_DIR=$ANDROID_NDK_ROOT
     85     log "Auto-config: --ndk-dir=$NDK_DIR"
     86 else
     87     if [ ! -d "$NDK_DIR" ] ; then
     88         echo "ERROR: NDK directory does not exists: $NDK_DIR"
     89         exit 1
     90     fi
     91 fi
     92 
     93 if [ -z "$OPTION_BUILD_DIR" ]; then
     94     BUILD_DIR=$NDK_TMPDIR/build-gnustl
     95 else
     96     BUILD_DIR=$OPTION_BUILD_DIR
     97 fi
     98 
     99 HOST_TAG_LIST="$HOST_TAG $HOST_TAG32"
    100 
    101 rm -rf "$BUILD_DIR"
    102 mkdir -p "$BUILD_DIR"
    103 fail_panic "Could not create build directory: $BUILD_DIR"
    104 
    105 # $1: ABI name
    106 # $2: Build directory
    107 # $3: "static" or "shared"
    108 # $4: GCC version
    109 # $5: optional "thumb"
    110 build_gnustl_for_abi ()
    111 {
    112     local ARCH BINPREFIX SYSROOT GNUSTL_SRCDIR
    113     local ABI=$1
    114     local BUILDDIR="$2"
    115     local LIBTYPE="$3"
    116     local GCC_VERSION="$4"
    117     local THUMB="$5"
    118     local DSTDIR=$NDK_DIR/$GNUSTL_SUBDIR/$GCC_VERSION/libs/$ABI/$THUMB
    119     local SRC OBJ OBJECTS CFLAGS CXXFLAGS CPPFLAGS
    120 
    121     prepare_target_build $ABI $PLATFORM $NDK_DIR
    122     fail_panic "Could not setup target build."
    123 
    124     INSTALLDIR=$BUILDDIR/install-$ABI-$GCC_VERSION/$THUMB
    125     BUILDDIR=$BUILDDIR/$LIBTYPE-${ABI}${THUMB}-$GCC_VERSION
    126 
    127     mkdir -p $DSTDIR
    128 
    129     ARCH=$(convert_abi_to_arch $ABI)
    130     for TAG in $HOST_TAG_LIST; do
    131         BINPREFIX=$NDK_DIR/$(get_toolchain_binprefix_for_arch $ARCH $GCC_VERSION $TAG)
    132         if [ -f ${BINPREFIX}gcc ]; then
    133             break;
    134         fi
    135     done
    136     GNUSTL_SRCDIR=$SRCDIR/gcc/gcc-$GCC_VERSION/libstdc++-v3
    137     # Sanity check
    138     if [ ! -d "$GNUSTL_SRCDIR" ]; then
    139         echo "ERROR: Not a valid toolchain source tree."
    140         echo "Can't find: $GNUSTL_SRCDIR"
    141         exit 1
    142     fi
    143 
    144     if [ ! -f "$GNUSTL_SRCDIR/configure" ]; then
    145         echo "ERROR: Configure script missing: $GNUSTL_SRCDIR/configure"
    146         exit 1
    147     fi
    148 
    149     SYSROOT=$NDK_DIR/$(get_default_platform_sysroot_for_arch $ARCH)
    150     LDIR=$SYSROOT"/usr/"$(get_default_libdir_for_arch $ARCH)
    151     # Sanity check
    152     if [ ! -f "$LDIR/libc.a" ]; then
    153 	echo "ERROR: Empty sysroot! you probably need to run gen-platforms.sh before this script."
    154 	exit 1
    155     fi
    156     if [ ! -f "$LDIR/libc.so" ]; then
    157         echo "ERROR: Sysroot misses shared libraries! you probably need to run gen-platforms.sh"
    158         echo "*without* the --minimal flag before running this script."
    159         exit 1
    160     fi
    161 
    162     case $ARCH in
    163         arm)
    164             BUILD_HOST=arm-linux-androideabi
    165             ;;
    166         arm64)
    167             BUILD_HOST=aarch64-linux-android
    168             ;;
    169         x86)
    170             BUILD_HOST=i686-linux-android
    171             ;;
    172         x86_64)
    173             BUILD_HOST=x86_64-linux-android
    174             ;;
    175         mips)
    176             BUILD_HOST=mipsel-linux-android
    177             ;;
    178         mips64)
    179             BUILD_HOST=mips64el-linux-android
    180             ;;
    181     esac
    182 
    183     EXTRA_FLAGS="-ffunction-sections -fdata-sections"
    184     if [ -n "$THUMB" ] ; then
    185         EXTRA_FLAGS="-mthumb"
    186     fi
    187     CFLAGS="-fPIC $CFLAGS --sysroot=$SYSROOT -fexceptions -funwind-tables -D__BIONIC__ -O2 $EXTRA_FLAGS"
    188     CXXFLAGS="-fPIC $CXXFLAGS --sysroot=$SYSROOT -fexceptions -frtti -funwind-tables -D__BIONIC__ -O2 $EXTRA_FLAGS"
    189     CPPFLAGS="$CPPFLAGS --sysroot=$SYSROOT"
    190     if [ "$WITH_DEBUG_INFO" ]; then
    191         CFLAGS="$CFLAGS -g"
    192         CXXFLAGS="$CXXFLAGS -g"
    193     fi
    194     export CFLAGS CXXFLAGS CPPFLAGS
    195 
    196     export CC=${BINPREFIX}gcc
    197     export CXX=${BINPREFIX}g++
    198     export AS=${BINPREFIX}as
    199     export LD=${BINPREFIX}ld
    200     export AR=${BINPREFIX}ar
    201     export RANLIB=${BINPREFIX}ranlib
    202     export STRIP=${BINPREFIX}strip
    203 
    204     setup_ccache
    205 
    206     export LDFLAGS="-lc $EXTRA_FLAGS"
    207 
    208     if [ "$ABI" = "armeabi-v7a" -o "$ABI" = "armeabi-v7a-hard" ]; then
    209         CXXFLAGS=$CXXFLAGS" -march=armv7-a -mfpu=vfpv3-d16"
    210         LDFLAGS=$LDFLAGS" -Wl,--fix-cortex-a8"
    211         if [ "$ABI" != "armeabi-v7a-hard" ]; then
    212             CXXFLAGS=$CXXFLAGS" -mfloat-abi=softfp"
    213         else
    214             CXXFLAGS=$CXXFLAGS" -mhard-float -D_NDK_MATH_NO_SOFTFP=1"
    215             LDFLAGS=$LDFLAGS" -Wl,--no-warn-mismatch -lm_hard"
    216         fi
    217     fi
    218 
    219     LIBTYPE_FLAGS=
    220     if [ $LIBTYPE = "static" ]; then
    221         # Ensure we disable visibility for the static library to reduce the
    222         # size of the code that will be linked against it.
    223         if [ -z "$VISIBLE_LIBGNUSTL_STATIC" ] ; then
    224             LIBTYPE_FLAGS="--enable-static --disable-shared"
    225             if [ $GCC_VERSION = "4.4.3" -o $GCC_VERSION = "4.6" ]; then
    226                 LIBTYPE_FLAGS=$LIBTYPE_FLAGS" --disable-visibility"
    227             else
    228                 LIBTYPE_FLAGS=$LIBTYPE_FLAGS" --disable-libstdcxx-visibility"
    229             fi
    230             CXXFLAGS=$CXXFLAGS" -fvisibility=hidden -fvisibility-inlines-hidden"
    231         fi
    232     else
    233         LIBTYPE_FLAGS="--disable-static --enable-shared"
    234         #LDFLAGS=$LDFLAGS" -lsupc++"
    235     fi
    236 
    237     if [ "$ARCH" == "x86_64" -o "$ARCH" == "mips64" ]; then
    238         MULTILIB_FLAGS=  # Both x86_64 and mips64el toolchains are built with multilib options
    239     else
    240         MULTILIB_FLAGS=--disable-multilib
    241     fi
    242 
    243     PROJECT="gnustl_$LIBTYPE gcc-$GCC_VERSION $ABI $THUMB"
    244     echo "$PROJECT: configuring"
    245     mkdir -p $BUILDDIR && rm -rf $BUILDDIR/* &&
    246     cd $BUILDDIR &&
    247     run $GNUSTL_SRCDIR/configure \
    248         --prefix=$INSTALLDIR \
    249         --host=$BUILD_HOST \
    250         $LIBTYPE_FLAGS \
    251         --enable-libstdcxx-time \
    252         --disable-symvers \
    253         $MULTILIB_FLAGS \
    254         --disable-nls \
    255         --disable-sjlj-exceptions \
    256         --disable-tls \
    257         --disable-libstdcxx-pch \
    258         --with-gxx-include-dir=$INSTALLDIR/include/c++/$GCC_VERSION
    259 
    260     fail_panic "Could not configure $PROJECT"
    261 
    262     echo "$PROJECT: compiling"
    263     run make -j$NUM_JOBS
    264     fail_panic "Could not build $PROJECT"
    265 
    266     echo "$PROJECT: installing"
    267     run make install
    268     fail_panic "Could not create $ABI $THUMB prebuilts for GNU libsupc++/libstdc++"
    269 }
    270 
    271 
    272 HAS_COMMON_HEADERS=
    273 
    274 # $1: ABI
    275 # $2: Build directory
    276 # $3: GCC_VERSION
    277 copy_gnustl_libs ()
    278 {
    279     local ABI="$1"
    280     local BUILDDIR="$2"
    281     local ARCH=$(convert_abi_to_arch $ABI)
    282     local GCC_VERSION="$3"
    283     local PREFIX=$(get_default_toolchain_prefix_for_arch $ARCH)
    284     PREFIX=${PREFIX%%-}
    285 
    286     local SDIR="$BUILDDIR/install-$ABI-$GCC_VERSION"
    287     local DDIR="$NDK_DIR/$GNUSTL_SUBDIR/$GCC_VERSION"
    288 
    289     local GCC_VERSION_NO_DOT=$(echo $GCC_VERSION|sed 's/\./_/g')
    290     # Copy the common headers only once per gcc version
    291     if [ -z `var_value HAS_COMMON_HEADERS_$GCC_VERSION_NO_DOT` ]; then
    292         copy_directory "$SDIR/include/c++/$GCC_VERSION" "$DDIR/include"
    293         rm -rf "$DDIR/include/$PREFIX"
    294 	eval HAS_COMMON_HEADERS_$GCC_VERSION_NO_DOT=true
    295     fi
    296 
    297     rm -rf "$DDIR/libs/$ABI" &&
    298     mkdir -p "$DDIR/libs/$ABI/include"
    299 
    300     # Copy the ABI-specific headers
    301     copy_directory "$SDIR/include/c++/$GCC_VERSION/$PREFIX/bits" "$DDIR/libs/$ABI/include/bits"
    302     if [ "$ARCH" = "x86_64" -o "$ARCH" = "mips64" ]; then
    303         copy_directory "$SDIR/include/c++/$GCC_VERSION/$PREFIX/32/bits" "$DDIR/libs/$ABI/include/32/bits"
    304         if [ "$ARCH" = "x86_64" ]; then
    305             copy_directory "$SDIR/include/c++/$GCC_VERSION/$PREFIX/x32/bits" "$DDIR/libs/$ABI/include/x32/bits"
    306         else
    307             copy_directory "$SDIR/include/c++/$GCC_VERSION/$PREFIX/n32/bits" "$DDIR/libs/$ABI/include/n32/bits"
    308         fi
    309     fi
    310 
    311     LDIR=lib
    312     if [ "$ARCH" != "${ARCH%%64*}" ]; then
    313         #Can't call $(get_default_libdir_for_arch $ARCH) which contain hack for arm64 and mips64
    314         LDIR=lib64
    315     fi
    316 
    317     # Copy the ABI-specific libraries
    318     # Note: the shared library name is libgnustl_shared.so due our custom toolchain patch
    319     copy_file_list "$SDIR/$LDIR" "$DDIR/libs/$ABI" libsupc++.a libgnustl_shared.so
    320     # Note: we need to rename libgnustl_shared.a to libgnustl_static.a
    321     cp "$SDIR/$LDIR/libgnustl_shared.a" "$DDIR/libs/$ABI/libgnustl_static.a"
    322     if [ "$ARCH" = "x86_64" -o "$ARCH" = "mips64" ]; then
    323        # for multilib we copy full set. Keep native libs in $ABI dir for compatibility.
    324        # TODO: remove it in $ABI top directory
    325        copy_file_list "$SDIR/lib" "$DDIR/libs/$ABI/lib" libsupc++.a libgnustl_shared.so
    326        copy_file_list "$SDIR/lib64" "$DDIR/libs/$ABI/lib64" libsupc++.a libgnustl_shared.so
    327        cp "$SDIR/lib/libgnustl_shared.a" "$DDIR/libs/$ABI/lib/libgnustl_static.a"
    328        cp "$SDIR/lib64/libgnustl_shared.a" "$DDIR/libs/$ABI/lib64/libgnustl_static.a"
    329        if [ "$ARCH" = "x86_64" ]; then
    330          copy_file_list "$SDIR/libx32" "$DDIR/libs/$ABI/libx32" libsupc++.a libgnustl_shared.so
    331          cp "$SDIR/libx32/libgnustl_shared.a" "$DDIR/libs/$ABI/libx32/libgnustl_static.a"
    332        else
    333          copy_file_list "$SDIR/lib32" "$DDIR/libs/$ABI/lib32" libsupc++.a libgnustl_shared.so
    334          cp "$SDIR/lib32/libgnustl_shared.a" "$DDIR/libs/$ABI/lib32/libgnustl_static.a"
    335        fi
    336     fi
    337     if [ -d "$SDIR/thumb" ] ; then
    338         copy_file_list "$SDIR/thumb/$LDIR" "$DDIR/libs/$ABI/thumb" libsupc++.a libgnustl_shared.so
    339         cp "$SDIR/thumb/$LDIR/libgnustl_shared.a" "$DDIR/libs/$ABI/thumb/libgnustl_static.a"
    340     fi
    341 }
    342 
    343 GCC_VERSION_LIST=$(commas_to_spaces $GCC_VERSION_LIST)
    344 for ABI in $ABIS; do
    345     ARCH=$(convert_abi_to_arch $ABI)
    346     DEFAULT_GCC_VERSION=$(get_default_gcc_version_for_arch $ARCH)
    347     for VERSION in $GCC_VERSION_LIST; do
    348         # Only build for this GCC version if it on or after DEFAULT_GCC_VERSION
    349         if [ "${VERSION%%l}" \< "$DEFAULT_GCC_VERSION" ]; then
    350             continue
    351         fi
    352 
    353         build_gnustl_for_abi $ABI "$BUILD_DIR" static $VERSION
    354         build_gnustl_for_abi $ABI "$BUILD_DIR" shared $VERSION
    355         # build thumb version of libraries for 32-bit arm
    356         if [ "$ABI" != "${ABI%%arm*}" -a "$ABI" = "${ABI%%64*}" ] ; then
    357             build_gnustl_for_abi $ABI "$BUILD_DIR" static $VERSION thumb
    358             build_gnustl_for_abi $ABI "$BUILD_DIR" shared $VERSION thumb
    359         fi
    360         copy_gnustl_libs $ABI "$BUILD_DIR" $VERSION
    361     done
    362 done
    363 
    364 # If needed, package files into tarballs
    365 if [ -n "$PACKAGE_DIR" ] ; then
    366     for VERSION in $GCC_VERSION_LIST; do
    367         # First, the headers as a single package for a given gcc version
    368         PACKAGE="$PACKAGE_DIR/gnu-libstdc++-headers-$VERSION.tar.bz2"
    369         dump "Packaging: $PACKAGE"
    370         pack_archive "$PACKAGE" "$NDK_DIR" "$GNUSTL_SUBDIR/$VERSION/include"
    371 
    372         # Then, one package per version/ABI for libraries
    373         for ABI in $ABIS; do
    374             if [ ! -d "$NDK_DIR/$GNUSTL_SUBDIR/$VERSION/libs/$ABI" ]; then
    375                 continue
    376             fi
    377             FILES=""
    378             case "$ABI" in
    379                 x86_64)
    380                     MULTILIB="include/32/bits include/x32/bits
    381                               lib/libsupc++.a lib/libgnustl_static.a lib/libgnustl_shared.so
    382                               libx32/libsupc++.a libx32/libgnustl_static.a libx32/libgnustl_shared.so
    383                               lib64/libsupc++.a lib64/libgnustl_static.a lib64/libgnustl_shared.so"
    384                     ;;
    385                 mips64)
    386                     MULTILIB="include/32/bits include/n32/bits
    387                               lib/libsupc++.a lib/libgnustl_static.a lib/libgnustl_shared.so
    388                               lib32/libsupc++.a lib32/libgnustl_static.a lib32/libgnustl_shared.so
    389                               lib64/libsupc++.a lib64/libgnustl_static.a lib64/libgnustl_shared.so"
    390                     ;;
    391                 *)
    392                     MULTILIB=
    393                     ;;
    394             esac
    395             for LIB in include/bits $MULTILIB libsupc++.a libgnustl_static.a libgnustl_shared.so; do
    396                 FILES="$FILES $GNUSTL_SUBDIR/$VERSION/libs/$ABI/$LIB"
    397                 THUMB_FILE="$GNUSTL_SUBDIR/$VERSION/libs/$ABI/thumb/$LIB"
    398                 if [ -f "$NDK_DIR/$THUMB_FILE" ] ; then
    399                     FILES="$FILES $THUMB_FILE"
    400                 fi
    401             done
    402             PACKAGE="$PACKAGE_DIR/gnu-libstdc++-libs-$VERSION-$ABI"
    403             if [ "$WITH_DEBUG_INFO" ]; then
    404                 PACKAGE="${PACKAGE}-g"
    405             fi
    406             PACKAGE="${PACKAGE}.tar.bz2"
    407             dump "Packaging: $PACKAGE"
    408             pack_archive "$PACKAGE" "$NDK_DIR" "$FILES"
    409             fail_panic "Could not package $ABI GNU libstdc++ binaries!"
    410         done
    411     done
    412 fi
    413 
    414 if [ -z "$OPTION_BUILD_DIR" ]; then
    415     log "Cleaning up..."
    416     rm -rf $BUILD_DIR
    417 else
    418     log "Don't forget to cleanup: $BUILD_DIR"
    419 fi
    420 
    421 log "Done!"
    422