#!/bin/sh # # Copyright (C) 2011 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This shell script is used to rebuild the prebuilt GNU libsupc++ and # libstdc++ binaries from their sources. It requires an NDK installation # that contains valid plaforms files and toolchain binaries. # # include common function and variable definitions . $NDK_BUILDTOOLS_PATH/prebuilt-common.sh STL_DIR=sources/cxx-stl GNUSTL_DIR=gnu-libstdc++ PROGRAM_PARAMETERS="<src-dir>" PROGRAM_DESCRIPTION=\ "Rebuild the prebuilt GNU libsupc++ / libstdc++ binaries for the Android NDK. This script is called when packaging a new NDK release. It will simply rebuild the GNU libsupc++ and libstdc++ static and shared libraries from sources. This requires a temporary NDK installation containing platforms and toolchain binaries for all target architectures, as well as the path to the corresponding gcc source tree. By default, this will try with the current NDK directory, unless you use the --ndk-dir=<path> option. The output will be placed in appropriate sub-directories of <ndk>/$GNUSTL_SUBDIR, but you can override this with the --out-dir=<path> option. " GCC_VERSION_LIST= register_var_option "--gcc-version-list=<vers>" GCC_VERSION_LIST "List of GCC versions" PACKAGE_DIR= register_var_option "--package-dir=<path>" PACKAGE_DIR "Put prebuilt tarballs into <path>." NDK_DIR= register_var_option "--ndk-dir=<path>" NDK_DIR "Specify NDK root path for the build." BUILD_DIR= OPTION_BUILD_DIR= register_var_option "--build-dir=<path>" OPTION_BUILD_DIR "Specify temporary build dir." OUT_DIR= register_var_option "--out-dir=<path>" OUT_DIR "Specify output directory directly." ABIS=$(spaces_to_commas $PREBUILT_ABIS) register_var_option "--abis=<list>" ABIS "Specify list of target ABIs." NO_MAKEFILE= register_var_option "--no-makefile" NO_MAKEFILE "Do not use makefile to speed-up build" VISIBLE_LIBGNUSTL_STATIC= register_var_option "--visible-libgnustl-static" VISIBLE_LIBGNUSTL_STATIC "Do not use hidden visibility for libgnustl_static.a" WITH_DEBUG_INFO= register_var_option "--with-debug-info" WITH_DEBUG_INFO "Build with -g. STL is still built with optimization but with debug info" WITH_LIBSUPPORT= register_var_option "--with-libsupport" WITH_LIBSUPPORT "Build with -landroid_support." register_jobs_option register_try64_option extract_parameters "$@" # set compiler version to any even earlier than default EXPLICIT_COMPILER_VERSION=1 if [ -z "$GCC_VERSION_LIST" ]; then EXPLICIT_COMPILER_VERSION= GCC_VERSION_LIST=$DEFAULT_GCC_VERSION_LIST fi SRCDIR=$(echo $PARAMETERS | sed 1q) check_toolchain_src_dir "$SRCDIR" ABIS=$(commas_to_spaces $ABIS) # Handle NDK_DIR if [ -z "$NDK_DIR" ] ; then NDK_DIR=$ANDROID_NDK_ROOT log "Auto-config: --ndk-dir=$NDK_DIR" else if [ ! -d "$NDK_DIR" ] ; then echo "ERROR: NDK directory does not exists: $NDK_DIR" exit 1 fi fi if [ -z "$OPTION_BUILD_DIR" ]; then BUILD_DIR=$NDK_TMPDIR/build-gnustl else BUILD_DIR=$OPTION_BUILD_DIR fi HOST_TAG_LIST="$HOST_TAG $HOST_TAG32" rm -rf "$BUILD_DIR" mkdir -p "$BUILD_DIR" fail_panic "Could not create build directory: $BUILD_DIR" # $1: ABI name # $2: Build directory # $3: "static" or "shared" # $4: GCC version # $5: optional "thumb" build_gnustl_for_abi () { local ARCH BINPREFIX SYSROOT GNUSTL_SRCDIR local ABI=$1 local BUILDDIR="$2" local LIBTYPE="$3" local GCC_VERSION="$4" local THUMB="$5" local DSTDIR=$NDK_DIR/$GNUSTL_SUBDIR/libs/$ABI/$THUMB local PREBUILT_NDK=$ANDROID_BUILD_TOP/prebuilts/ndk/current local SRC OBJ OBJECTS CFLAGS CXXFLAGS CPPFLAGS prepare_target_build $ABI $PLATFORM $NDK_DIR fail_panic "Could not setup target build." INSTALLDIR=$BUILDDIR/install-$ABI-$GCC_VERSION/$THUMB BUILDDIR=$BUILDDIR/$LIBTYPE-${ABI}${THUMB}-$GCC_VERSION mkdir -p $DSTDIR ARCH=$(convert_abi_to_arch $ABI) for TAG in $HOST_TAG_LIST; do BINPREFIX=$ANDROID_BUILD_TOP/prebuilts/ndk/current/$(get_toolchain_binprefix_for_arch $ARCH $GCC_VERSION $TAG) if [ -f ${BINPREFIX}gcc ]; then break; fi done GNUSTL_SRCDIR=$SRCDIR/gcc/gcc-$GCC_VERSION/libstdc++-v3 # Sanity check if [ ! -d "$GNUSTL_SRCDIR" ]; then echo "ERROR: Not a valid toolchain source tree." echo "Can't find: $GNUSTL_SRCDIR" exit 1 fi if [ ! -f "$GNUSTL_SRCDIR/configure" ]; then echo "ERROR: Configure script missing: $GNUSTL_SRCDIR/configure" exit 1 fi SYSROOT=$PREBUILT_NDK/$(get_default_platform_sysroot_for_arch $ARCH) LDIR=$SYSROOT"/usr/"$(get_default_libdir_for_arch $ARCH) # Sanity check if [ ! -f "$LDIR/libc.a" ]; then echo "ERROR: Empty sysroot! you probably need to run gen-platforms.sh before this script." exit 1 fi if [ ! -f "$LDIR/libc.so" ]; then echo "ERROR: Sysroot misses shared libraries! you probably need to run gen-platforms.sh" echo "*without* the --minimal flag before running this script." exit 1 fi EXTRA_CFLAGS="-ffunction-sections -fdata-sections" EXTRA_LDFLAGS= if [ -n "$THUMB" ] ; then EXTRA_CFLAGS="$EXTRA_CFLAGS -mthumb" EXTRA_LDFLAGS="$EXTRA_LDFLAGS -mthumb" fi case $ARCH in arm) BUILD_HOST=arm-linux-androideabi ;; arm64) BUILD_HOST=aarch64-linux-android ;; x86) BUILD_HOST=i686-linux-android # ToDo: remove the following once all x86-based device call JNI function with # stack aligned to 16-byte EXTRA_CFLAGS="$EXTRA_CFLAGS -mstackrealign" ;; x86_64) BUILD_HOST=x86_64-linux-android # ToDo: remove the following once all x86-based device call JNI function with # stack aligned to 16-byte EXTRA_CFLAGS="$EXTRA_CFLAGS -mstackrealign" ;; mips) BUILD_HOST=mipsel-linux-android ;; mips64) BUILD_HOST=mips64el-linux-android ;; esac CFLAGS="-fPIC $CFLAGS --sysroot=$SYSROOT -fexceptions -funwind-tables -D__BIONIC__ -O2 $EXTRA_CFLAGS" CXXFLAGS="-fPIC $CXXFLAGS --sysroot=$SYSROOT -fexceptions -frtti -funwind-tables -D__BIONIC__ -O2 $EXTRA_CFLAGS" CPPFLAGS="$CPPFLAGS --sysroot=$SYSROOT" if [ "$WITH_DEBUG_INFO" ]; then CFLAGS="$CFLAGS -g" CXXFLAGS="$CXXFLAGS -g" fi if [ "$WITH_LIBSUPPORT" ]; then CFLAGS="$CFLAGS -I$NDK_DIR/$SUPPORT_SUBDIR/include" CXXFLAGS="$CXXFLAGS -I$NDK_DIR/$SUPPORT_SUBDIR/include" EXTRA_LDFLAGS="$EXTRA_LDFLAGS -L$NDK_DIR/$SUPPORT_SUBDIR/libs/$ABI -landroid_support" fi export CFLAGS CXXFLAGS CPPFLAGS export CC=${BINPREFIX}gcc export CXX=${BINPREFIX}g++ export AS=${BINPREFIX}as export LD=${BINPREFIX}ld export AR=${BINPREFIX}ar export RANLIB=${BINPREFIX}ranlib export STRIP=${BINPREFIX}strip setup_ccache export LDFLAGS="$EXTRA_LDFLAGS -lc" case $ABI in armeabi-v7a|armeabi-v7a-hard) CXXFLAGS=$CXXFLAGS" -march=armv7-a -mfpu=vfpv3-d16" LDFLAGS=$LDFLAGS" -Wl,--fix-cortex-a8" if [ "$ABI" != "armeabi-v7a-hard" ]; then CXXFLAGS=$CXXFLAGS" -mfloat-abi=softfp" else CXXFLAGS=$CXXFLAGS" -mhard-float -D_NDK_MATH_NO_SOFTFP=1" LDFLAGS=$LDFLAGS" -Wl,--no-warn-mismatch -lm_hard" fi ;; arm64-v8a) CFLAGS="$CFLAGS -mfix-cortex-a53-835769" CXXFLAGS=$CXXFLAGS" -mfix-cortex-a53-835769" ;; esac if [ "$ABI" = "armeabi" -o "$ABI" = "armeabi-v7a" -o "$ABI" = "armeabi-v7a-hard" ]; then CFLAGS=$CFLAGS" -minline-thumb1-jumptable" CXXFLAGS=$CXXFLAGS" -minline-thumb1-jumptable" fi LIBTYPE_FLAGS= if [ $LIBTYPE = "static" ]; then # Ensure we disable visibility for the static library to reduce the # size of the code that will be linked against it. if [ -z "$VISIBLE_LIBGNUSTL_STATIC" ] ; then LIBTYPE_FLAGS="--enable-static --disable-shared" LIBTYPE_FLAGS=$LIBTYPE_FLAGS" --disable-libstdcxx-visibility" CXXFLAGS=$CXXFLAGS" -fvisibility=hidden -fvisibility-inlines-hidden" fi else LIBTYPE_FLAGS="--disable-static --enable-shared" #LDFLAGS=$LDFLAGS" -lsupc++" fi if [ "$ARCH" = "x86_64" -o "$ARCH" = "mips64" -o "$ARCH" = "mips" ] ; then MULTILIB_FLAGS= else MULTILIB_FLAGS=--disable-multilib fi PROJECT="gnustl_$LIBTYPE gcc-$GCC_VERSION $ABI $THUMB" echo "$PROJECT: configuring" mkdir -p $BUILDDIR && rm -rf $BUILDDIR/* && cd $BUILDDIR && run $GNUSTL_SRCDIR/configure \ --prefix=$INSTALLDIR \ --host=$BUILD_HOST \ $LIBTYPE_FLAGS \ --enable-libstdcxx-time \ --disable-symvers \ $MULTILIB_FLAGS \ --disable-nls \ --disable-sjlj-exceptions \ --disable-tls \ --disable-libstdcxx-pch \ --with-gxx-include-dir=$INSTALLDIR/include/c++/$GCC_VERSION fail_panic "Could not configure $PROJECT" echo "$PROJECT: compiling" run make -j$NUM_JOBS fail_panic "Could not build $PROJECT" echo "$PROJECT: installing" run make install fail_panic "Could not create $ABI $THUMB prebuilts for GNU libsupc++/libstdc++" } HAS_COMMON_HEADERS= # $1: ABI # $2: Build directory # $3: GCC_VERSION copy_gnustl_libs () { local ABI="$1" local BUILDDIR="$2" local ARCH=$(convert_abi_to_arch $ABI) local GCC_VERSION="$3" local PREFIX=$(get_default_toolchain_prefix_for_arch $ARCH) PREFIX=${PREFIX%%-} local SDIR="$BUILDDIR/install-$ABI-$GCC_VERSION" local DDIR="$NDK_DIR/$GNUSTL_SUBDIR" local GCC_VERSION_NO_DOT=$(echo $GCC_VERSION|sed 's/\./_/g') # Copy the common headers only once per gcc version if [ -z `var_value HAS_COMMON_HEADERS_$GCC_VERSION_NO_DOT` ]; then copy_directory "$SDIR/include/c++/$GCC_VERSION" "$DDIR/include" rm -rf "$DDIR/include/$PREFIX" eval HAS_COMMON_HEADERS_$GCC_VERSION_NO_DOT=true fi rm -rf "$DDIR/libs/$ABI" && mkdir -p "$DDIR/libs/$ABI/include" # Copy the ABI-specific headers copy_directory "$SDIR/include/c++/$GCC_VERSION/$PREFIX/bits" "$DDIR/libs/$ABI/include/bits" case "$ARCH" in x86_64) copy_directory "$SDIR/include/c++/$GCC_VERSION/$PREFIX/32/bits" "$DDIR/libs/$ABI/include/32/bits" copy_directory "$SDIR/include/c++/$GCC_VERSION/$PREFIX/x32/bits" "$DDIR/libs/$ABI/include/x32/bits" ;; mips64) copy_directory "$SDIR/include/c++/$GCC_VERSION/$PREFIX/32/mips-r1/bits" "$DDIR/libs/$ABI/include/32/mips-r1/bits" copy_directory "$SDIR/include/c++/$GCC_VERSION/$PREFIX/32/mips-r2/bits" "$DDIR/libs/$ABI/include/32/mips-r2/bits" copy_directory "$SDIR/include/c++/$GCC_VERSION/$PREFIX/32/mips-r6/bits" "$DDIR/libs/$ABI/include/32/mips-r6/bits" ;; mips) copy_directory "$SDIR/include/c++/$GCC_VERSION/$PREFIX/mips-r2/bits" "$DDIR/libs/$ABI/include/mips-r2/bits" copy_directory "$SDIR/include/c++/$GCC_VERSION/$PREFIX/mips-r6/bits" "$DDIR/libs/$ABI/include/mips-r6/bits" ;; esac LDIR=lib if [ "$ABI" = "mips32r6" ]; then LDIR=libr6 elif [ "$ARCH" != "${ARCH%%64*}" ]; then #Can't call $(get_default_libdir_for_arch $ARCH) which contain hack for arm64 LDIR=lib64 fi # Copy the ABI-specific libraries # Note: the shared library name is libgnustl_shared.so due our custom toolchain patch copy_file_list "$SDIR/$LDIR" "$DDIR/libs/$ABI" libsupc++.a libgnustl_shared.so # Note: we need to rename libgnustl_shared.a to libgnustl_static.a cp "$SDIR/$LDIR/libgnustl_shared.a" "$DDIR/libs/$ABI/libgnustl_static.a" case "$ARCH" in # for multilib we copy full set. Keep native libs in $ABI dir for compatibility. # TODO: remove it in $ABI top directory x86_64) copy_file_list "$SDIR/lib" "$DDIR/libs/$ABI/lib" libsupc++.a libgnustl_shared.so copy_file_list "$SDIR/lib64" "$DDIR/libs/$ABI/lib64" libsupc++.a libgnustl_shared.so copy_file_list "$SDIR/libx32" "$DDIR/libs/$ABI/libx32" libsupc++.a libgnustl_shared.so cp "$SDIR/lib/libgnustl_shared.a" "$DDIR/libs/$ABI/lib/libgnustl_static.a" cp "$SDIR/lib64/libgnustl_shared.a" "$DDIR/libs/$ABI/lib64/libgnustl_static.a" cp "$SDIR/libx32/libgnustl_shared.a" "$DDIR/libs/$ABI/libx32/libgnustl_static.a" ;; mips64) copy_file_list "$SDIR/lib" "$DDIR/libs/$ABI/lib" libsupc++.a libgnustl_shared.so copy_file_list "$SDIR/libr2" "$DDIR/libs/$ABI/libr2" libsupc++.a libgnustl_shared.so copy_file_list "$SDIR/libr6" "$DDIR/libs/$ABI/libr6" libsupc++.a libgnustl_shared.so copy_file_list "$SDIR/lib64" "$DDIR/libs/$ABI/lib64" libsupc++.a libgnustl_shared.so cp "$SDIR/lib/libgnustl_shared.a" "$DDIR/libs/$ABI/lib/libgnustl_static.a" cp "$SDIR/libr2/libgnustl_shared.a" "$DDIR/libs/$ABI/libr2/libgnustl_static.a" cp "$SDIR/libr6/libgnustl_shared.a" "$DDIR/libs/$ABI/libr6/libgnustl_static.a" cp "$SDIR/lib64/libgnustl_shared.a" "$DDIR/libs/$ABI/lib64/libgnustl_static.a" ;; mips) copy_file_list "$SDIR/lib" "$DDIR/libs/$ABI/lib" libsupc++.a libgnustl_shared.so copy_file_list "$SDIR/libr2" "$DDIR/libs/$ABI/libr2" libsupc++.a libgnustl_shared.so copy_file_list "$SDIR/libr6" "$DDIR/libs/$ABI/libr6" libsupc++.a libgnustl_shared.so cp "$SDIR/lib/libgnustl_shared.a" "$DDIR/libs/$ABI/lib/libgnustl_static.a" cp "$SDIR/libr2/libgnustl_shared.a" "$DDIR/libs/$ABI/libr2/libgnustl_static.a" cp "$SDIR/libr6/libgnustl_shared.a" "$DDIR/libs/$ABI/libr6/libgnustl_static.a" ;; esac if [ -d "$SDIR/thumb" ] ; then copy_file_list "$SDIR/thumb/$LDIR" "$DDIR/libs/$ABI/thumb" libsupc++.a libgnustl_shared.so cp "$SDIR/thumb/$LDIR/libgnustl_shared.a" "$DDIR/libs/$ABI/thumb/libgnustl_static.a" fi } GCC_VERSION_LIST=$(commas_to_spaces $GCC_VERSION_LIST) for ABI in $ABIS; do ARCH=$(convert_abi_to_arch $ABI) FIRST_GCC_VERSION=$(get_first_gcc_version_for_arch $ARCH) for VERSION in $GCC_VERSION_LIST; do # Only build for this GCC version if it on or after FIRST_GCC_VERSION if [ -z "$EXPLICIT_COMPILER_VERSION" ] && ! version_is_at_least "${VERSION%%l}" "$FIRST_GCC_VERSION"; then continue fi build_gnustl_for_abi $ABI "$BUILD_DIR" static $VERSION build_gnustl_for_abi $ABI "$BUILD_DIR" shared $VERSION # build thumb version of libraries for 32-bit arm if [ "$ABI" != "${ABI%%arm*}" -a "$ABI" = "${ABI%%64*}" ] ; then build_gnustl_for_abi $ABI "$BUILD_DIR" static $VERSION thumb build_gnustl_for_abi $ABI "$BUILD_DIR" shared $VERSION thumb fi copy_gnustl_libs $ABI "$BUILD_DIR" $VERSION done done # If needed, package files into tarballs if [ -n "$PACKAGE_DIR" ] ; then for VERSION in $GCC_VERSION_LIST; do FILES="$GNUSTL_DIR/Android.mk $GNUSTL_DIR/include" for ABI in $ABIS; do if [ ! -d "$NDK_DIR/$GNUSTL_SUBDIR/libs/$ABI" ]; then continue fi case "$ABI" in x86_64) MULTILIB="include/32/bits include/x32/bits lib/libsupc++.a lib/libgnustl_static.a lib/libgnustl_shared.so libx32/libsupc++.a libx32/libgnustl_static.a libx32/libgnustl_shared.so lib64/libsupc++.a lib64/libgnustl_static.a lib64/libgnustl_shared.so" ;; mips64) MULTILIB="include/32/mips-r1/bits include/32/mips-r2/bits include/32/mips-r6/bits include/bits lib/libsupc++.a lib/libgnustl_static.a lib/libgnustl_shared.so libr2/libsupc++.a libr2/libgnustl_static.a libr2/libgnustl_shared.so libr6/libsupc++.a libr6/libgnustl_static.a libr6/libgnustl_shared.so lib64/libsupc++.a lib64/libgnustl_static.a lib64/libgnustl_shared.so" ;; mips|mips32r6) MULTILIB="include/mips-r2/bits include/mips-r6/bits include/bits lib/libsupc++.a lib/libgnustl_static.a lib/libgnustl_shared.so libr2/libsupc++.a libr2/libgnustl_static.a libr2/libgnustl_shared.so libr6/libsupc++.a libr6/libgnustl_static.a libr6/libgnustl_shared.so" ;; *) MULTILIB= ;; esac for LIB in include/bits $MULTILIB libsupc++.a libgnustl_static.a libgnustl_shared.so; do FILES="$FILES $GNUSTL_DIR/libs/$ABI/$LIB" THUMB_FILE="$GNUSTL_DIR/libs/$ABI/thumb/$LIB" if [ -f "$NDK_DIR/sources/cxx-stl/$THUMB_FILE" ]; then FILES="$FILES $THUMB_FILE" fi done done make_repo_prop "$NDK_DIR/$STL_DIR/$GNUSTL_DIR" FILES="$FILES $GNUSTL_DIR/repo.prop" cp "$ANDROID_BUILD_TOP/toolchain/gcc/gcc-4.9/COPYING" \ "$NDK_DIR/$STL_DIR/$GNUSTL_DIR/NOTICE" FILES="$FILES $GNUSTL_DIR/NOTICE" PACKAGE="$PACKAGE_DIR/gnustl-${VERSION}.zip" dump "Packaging: $PACKAGE" pack_archive "$PACKAGE" "$NDK_DIR/$STL_DIR" "$FILES" fail_panic "Could not package GNU libstdc++ binaries!" done fi if [ -z "$OPTION_BUILD_DIR" ]; then log "Cleaning up..." rm -rf $BUILD_DIR else log "Don't forget to cleanup: $BUILD_DIR" fi log "Done!"