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 # gen-platforms.sh
     18 #
     19 # This tool is used when packaging a new release, or when developing
     20 # the NDK itself. It will populate DST ($NDK/platforms by default)
     21 # with the content of SRC ($NDK/../development/ndk/platforms/ by default).
     22 #
     23 # The idea is that the content of $SRC/android-N/ only contains stuff
     24 # that is relevant to API level N, and not contain anything that is already
     25 # provided by API level N-1, N-2, etc..
     26 #
     27 # More precisely, for each architecture A:
     28 #  $SRC/android-N/include        --> $DST/android-N/arch-A/usr/include
     29 #  $SRC/android-N/arch-A/include --> $DST/android-N/arch-A/usr/include
     30 #  $SRC/android-N/arch-A/lib     --> $DST/android-N/arch-A/usr/lib
     31 #
     32 # Also, we generate on-the-fly shared dynamic libraries from list of symbols:
     33 #
     34 #  $SRC/android-N/arch-A/symbols --> $DST/android-N/arch-A/usr/lib
     35 #
     36 # Repeat after that for N+1, N+2, etc..
     37 #
     38 
     39 PROGDIR=$(dirname "$0")
     40 . "$PROGDIR/prebuilt-common.sh"
     41 
     42 # Return the list of platform supported from $1/platforms
     43 # as a single space-separated sorted list of levels. (e.g. "3 4 5 8 9 14")
     44 # $1: source directory
     45 extract_platforms_from ()
     46 {
     47     if [ -d "$1" ] ; then
     48         (cd "$1/platforms" && ls -d android-*) | sed -e "s!android-!!" | sort -g | tr '\n' ' '
     49     else
     50         echo ""
     51     fi
     52 }
     53 
     54 SRCDIR="../development/ndk"
     55 DSTDIR="$ANDROID_NDK_ROOT"
     56 
     57 ARCHS=$(find_ndk_unknown_archs)
     58 ARCHS="$DEFAULT_ARCHS $ARCHS"
     59 PLATFORMS=`extract_platforms_from "$SRCDIR"`
     60 NDK_DIR=$ANDROID_NDK_ROOT
     61 
     62 OPTION_HELP=no
     63 OPTION_PLATFORMS=
     64 OPTION_SRCDIR=
     65 OPTION_DSTDIR=
     66 OPTION_SAMPLES=
     67 OPTION_FAST_COPY=
     68 OPTION_MINIMAL=
     69 OPTION_ARCH=
     70 OPTION_ABI=
     71 OPTION_DEBUG_LIBS=
     72 OPTION_OVERLAY=
     73 OPTION_GCC_VERSION=
     74 OPTION_LLVM_VERSION=$DEFAULT_LLVM_VERSION
     75 PACKAGE_DIR=
     76 
     77 VERBOSE=no
     78 VERBOSE2=no
     79 
     80 for opt do
     81   optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
     82   case "$opt" in
     83   --help|-h|-\?) OPTION_HELP=yes
     84   ;;
     85   --verbose)
     86     if [ "$VERBOSE" = "yes" ] ; then
     87         VERBOSE2=yes
     88     else
     89         VERBOSE=yes
     90     fi
     91     ;;
     92   --src-dir=*)
     93     OPTION_SRCDIR="$optarg"
     94     ;;
     95   --dst-dir=*)
     96     OPTION_DSTDIR="$optarg"
     97     ;;
     98   --ndk-dir=*)
     99     NDK_DIR=$optarg
    100     ;;
    101   --platform=*)
    102     OPTION_PLATFORM=$optarg
    103     ;;
    104   --arch=*)
    105     OPTION_ARCH=$optarg
    106     ;;
    107   --abi=*)  # We still support this for backwards-compatibility
    108     OPTION_ABI=$optarg
    109     ;;
    110   --samples)
    111     OPTION_SAMPLES=yes
    112     ;;
    113   --fast-copy)
    114     OPTION_FAST_COPY=yes
    115     ;;
    116   --minimal)
    117     OPTION_MINIMAL=yes
    118     ;;
    119   --package-dir=*)
    120     PACKAGE_DIR=$optarg
    121     ;;
    122   --debug-libs)
    123     OPTION_DEBUG_LIBS=true
    124     ;;
    125   --overlay)
    126     OPTION_OVERLAY=true
    127     ;;
    128   --gcc-version=*)
    129     OPTION_GCC_VERSION=$optarg
    130     ;;
    131   --llvm-version=*)
    132     OPTION_LLVM_VERSION=$optarg
    133     ;;
    134   *)
    135     echo "unknown option '$opt', use --help"
    136     exit 1
    137   esac
    138 done
    139 
    140 if [ $OPTION_HELP = "yes" ] ; then
    141     echo "Collect files from an Android NDK development tree and assemble"
    142     echo "the platform files appropriately into a final release structure."
    143     echo ""
    144     echo "options:"
    145     echo ""
    146     echo "  --help                Print this message"
    147     echo "  --verbose             Enable verbose messages"
    148     echo "  --src-dir=<path>      Source directory for development platform files [$SRCDIR]"
    149     echo "  --dst-dir=<path>      Destination directory [$DSTDIR]"
    150     echo "  --ndk-dir=<path>      Use toolchains from this NDK directory [$NDK_DIR]"
    151     echo "  --platform=<list>     List of API levels [$PLATFORMS]"
    152     echo "  --arch=<list>         List of CPU architectures [$ARCHS]"
    153     echo "  --minimal             Ignore samples, symlinks and generated shared libs."
    154     echo "  --fast-copy           Don't create symlinks, copy files instead"
    155     echo "  --samples             Also generate samples directories."
    156     echo "  --package-dir=<path>  Package platforms archive in specific path."
    157     echo "  --debug-libs          Also generate C source file for generated libraries."
    158     echo ""
    159     echo "Use the --minimal flag if you want to generate minimal sysroot directories"
    160     echo "that will be used to generate prebuilt toolchains. Otherwise, the script"
    161     echo "will require these toolchains to be pre-installed and will use them to"
    162     echo "generate shared system shared libraries from the symbol list files."
    163     exit 0
    164 fi
    165 
    166 if [ -n "$OPTION_SRCDIR" ] ; then
    167     SRCDIR="$OPTION_SRCDIR";
    168     if [ ! -d "$SRCDIR" ] ; then
    169         echo "ERROR: Source directory $SRCDIR does not exist !"
    170         exit 1
    171     fi
    172     if [ ! -d "$SRCDIR/platforms/android-3" ] ; then
    173         echo "ERROR: Invalid source directory: $SRCDIR"
    174         echo "Please make sure it contains platforms/android-3 etc..."
    175         exit 1
    176     fi
    177 else
    178     SRCDIR=`dirname $ANDROID_NDK_ROOT`/development/ndk
    179     log "Using source directory: $SRCDIR"
    180 fi
    181 
    182 if [ -n "$OPTION_PLATFORM" ] ; then
    183     PLATFORMS=$(commas_to_spaces $OPTION_PLATFORM)
    184 else
    185     # Build the list from the content of SRCDIR
    186     PLATFORMS=`extract_platforms_from "$SRCDIR"`
    187     # hack to place non-numeric level 'L' (lmp-preview) at the very end
    188     if [ "$PLATFORMS" != "${PLATFORMS%%L*}" ] ; then
    189         PLATFORMS=`echo $PLATFORMS | tr -d 'L'`
    190         PLATFORMS="$PLATFORMS L"
    191     fi
    192     log "Using platforms: $PLATFORMS"
    193 fi
    194 
    195 # Remove the android- prefix of any platform name
    196 PLATFORMS=$(echo $PLATFORMS | tr ' ' '\n' | sed -e 's!^android-!!g' | tr '\n' ' ')
    197 
    198 if [ -n "$OPTION_DSTDIR" ] ; then
    199     DSTDIR="$OPTION_DSTDIR"
    200 else
    201     log "Using destination directory: $DSTDIR"
    202 fi
    203 
    204 # Handle architecture list
    205 #
    206 # We support both --arch and --abi for backwards compatibility reasons
    207 # --arch is the new hotness, --abi is deprecated.
    208 #
    209 if [ -n "$OPTION_ARCH" ]; then
    210     OPTION_ARCH=$(commas_to_spaces $OPTION_ARCH)
    211 fi
    212 
    213 if [ -n "$OPTION_ABI" ] ; then
    214     echo "WARNING: --abi=<names> is deprecated. Use --arch=<names> instead!"
    215     OPTION_ABI=$(commas_to_spaces $OPTION_ABI)
    216     if [ -n "$OPTION_ARCH" -a "$OPTION_ARCH" != "$OPTION_ABI" ]; then
    217         echo "ERROR: You can't use both --abi and --arch with different values!"
    218         exit 1
    219     fi
    220     OPTION_ARCH=$OPTION_ABI
    221 fi
    222 
    223 if [ -n "$OPTION_ARCH" ] ; then
    224     ARCHS="$OPTION_ARCH"
    225 fi
    226 log "Using architectures: $(commas_to_spaces $ARCHS)"
    227 
    228 log "Checking source platforms."
    229 for PLATFORM in $PLATFORMS; do
    230     DIR="$SRCDIR/platforms/android-$PLATFORM"
    231     if [ ! -d $DIR ] ; then
    232         echo "ERROR: Directory missing: $DIR"
    233         echo "Please check your --platform=<list> option and try again."
    234         exit 2
    235     else
    236         log "  $DIR"
    237     fi
    238 done
    239 
    240 log "Checking source platform architectures."
    241 BAD_ARCHS=
    242 for ARCH in $ARCHS; do
    243     eval CHECK_$ARCH=no
    244 done
    245 for PLATFORM in $PLATFORMS; do
    246     for ARCH in $ARCHS; do
    247         DIR="$SRCDIR/platforms/android-$PLATFORM/arch-$ARCH"
    248         if [ -d $DIR ] ; then
    249             log "  $DIR"
    250             eval CHECK_$ARCH=yes
    251         fi
    252     done
    253 done
    254 
    255 if [ "$OPTION_MINIMAL" ]; then
    256     OPTION_SAMPLES=
    257     OPTION_FAST_COPY=yes
    258 fi
    259 
    260 BAD_ARCHS=
    261 for ARCH in $ARCHS; do
    262     CHECK=`var_value CHECK_$ARCH`
    263     log "  $ARCH check: $CHECK"
    264     if [ "$CHECK" = no ] ; then
    265         if [ -z "$BAD_ARCHS" ] ; then
    266             BAD_ARCHS=$ARCH
    267         else
    268             BAD_ARCHS="$BAD_ARCHS $ARCH"
    269         fi
    270     fi
    271 done
    272 
    273 if [ -n "$BAD_ARCHS" ] ; then
    274     echo "ERROR: Source directory doesn't support these ARCHs: $BAD_ARCHS"
    275     exit 3
    276 fi
    277 
    278 # $1: source directory (relative to $SRCDIR)
    279 # $2: destination directory (relative to $DSTDIR)
    280 # $3: description of directory contents (e.g. "sysroot" or "samples")
    281 copy_src_directory ()
    282 {
    283     local SDIR="$SRCDIR/$1"
    284     local DDIR="$DSTDIR/$2"
    285     if [ -d "$SDIR" ] ; then
    286         log "Copying $3 from \$SRC/$1 to \$DST/$2."
    287         mkdir -p "$DDIR" && (cd "$SDIR" && 2>/dev/null tar chf - *) | (tar xf - -C "$DDIR")
    288         if [ $? != 0 ] ; then
    289             echo "ERROR: Could not copy $3 directory $SDIR into $DDIR !"
    290             exit 5
    291         fi
    292     fi
    293 }
    294 
    295 # $1: source dir
    296 # $2: destination dir
    297 # $3: reverse path
    298 #
    299 symlink_src_directory_inner ()
    300 {
    301     local files file subdir rev
    302     mkdir -p "$DSTDIR/$2"
    303     rev=$3
    304     files=$(cd $DSTDIR/$1 && ls -1p)
    305     for file in $files; do
    306         if [ "$file" = "${file%%/}" ]; then
    307             log2 "Link \$DST/$2/$file --> $rev/$1/$file"
    308             ln -s $rev/$1/$file $DSTDIR/$2/$file
    309         else
    310             file=${file%%/}
    311             symlink_src_directory_inner "$1/$file" "$2/$file" "$rev/.."
    312         fi
    313     done
    314 }
    315 # Create a symlink-copy of directory $1 into $2
    316 # This function is recursive.
    317 #
    318 # $1: source directory (relative to $SRCDIR)
    319 # $2: destination directory (relative to $DSTDIR)
    320 symlink_src_directory ()
    321 {
    322     symlink_src_directory_inner "$1" "$2" "$(reverse_path $1)"
    323 }
    324 
    325 # Remove unwanted symbols
    326 # $1: symbol file (one symbol per line)
    327 # $2+: Input symbol list
    328 # Out: Input symbol file, without any unwanted symbol listed by $1
    329 remove_unwanted_symbols_from ()
    330 {
    331   local SYMBOL_FILE="$1"
    332   shift
    333   if [ -f "$SYMBOL_FILE" ]; then
    334     echo "$@" | tr ' ' '\n' | grep -v -F -x -f $SYMBOL_FILE | tr '\n' ' '
    335   else
    336     echo "$@"
    337   fi
    338 }
    339 
    340 # Remove unwanted symbols from a library's functions list.
    341 # $1: Architecture name
    342 # $2: Library name (e.g. libc.so)
    343 # $3+: Input symbol list
    344 # Out: Input symbol list without any unwanted symbols.
    345 remove_unwanted_function_symbols ()
    346 {
    347   local ARCH LIBRARY SYMBOL_FILE
    348   ARCH=$1
    349   LIBRARY=$2
    350   shift; shift
    351   SYMBOL_FILE=$PROGDIR/unwanted-symbols/$ARCH/$LIBRARY.functions.txt
    352   remove_unwanted_symbols_from $SYMBOL_FILE "$@"
    353 }
    354 
    355 # Same as remove_unwanted_functions_symbols, but for variable names.
    356 #
    357 remove_unwanted_variable_symbols ()
    358 {
    359   local ARCH LIBRARY SYMBOL_FILE
    360   ARCH=$1
    361   LIBRARY=$2
    362   shift; shift
    363   SYMBOL_FILE=$PROGDIR/unwanted-symbols/$ARCH/$LIBRARY.variables.txt
    364   remove_unwanted_symbols_from $SYMBOL_FILE "$@"
    365 }
    366 
    367 # $1: Architecture
    368 # Out: compiler command
    369 get_default_compiler_for_arch()
    370 {
    371     local ARCH=$1
    372     local TOOLCHAIN_PREFIX EXTRA_CFLAGS CC GCC_VERSION
    373 
    374     if [ "$ARCH" = "${ARCH%%64*}" -a "$(arch_in_unknown_archs $ARCH)" = "yes" ]; then
    375         for TAG in $HOST_TAG $HOST_TAG32; do
    376             TOOLCHAIN_PREFIX="$NDK_DIR/$(get_llvm_toolchain_binprefix $OPTION_LLVM_VERSION $TAG)"
    377             CC="$TOOLCHAIN_PREFIX/clang"
    378             if [ -f "$CC" ]; then
    379                 break;
    380             fi
    381         done
    382         EXTRA_CFLAGS="-emit-llvm"
    383     else
    384         if [ -n "$OPTION_GCC_VERSION" ]; then
    385             GCC_VERSION=$OPTION_GCC_VERSION
    386         else
    387             GCC_VERSION=$(get_default_gcc_version_for_arch $ARCH)
    388         fi
    389         for TAG in $HOST_TAG $HOST_TAG32; do
    390             TOOLCHAIN_PREFIX="$NDK_DIR/$(get_toolchain_binprefix_for_arch $ARCH $GCC_VERSION $TAG)"
    391             TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX%-}
    392             CC="$TOOLCHAIN_PREFIX-gcc"
    393             if [ -f "$CC" ]; then
    394                 break;
    395             fi
    396         done
    397         EXTRA_CFLAGS=
    398     fi
    399 
    400     if [ ! -f "$CC" ]; then
    401         dump "ERROR: $ARCH toolchain not installed: $CC"
    402         dump "Important: Use the --minimal flag to use this script without generated system shared libraries."
    403         dump "This is generally useful when you want to generate the host cross-toolchain programs."
    404         exit 1
    405     fi
    406     echo "$CC $EXTRA_CFLAGS"
    407 }
    408 
    409 # $1: library name
    410 # $2: functions list
    411 # $3: variables list
    412 # $4: destination file
    413 # $5: compiler command
    414 gen_shared_lib ()
    415 {
    416     local LIBRARY=$1
    417     local FUNCS="$2"
    418     local VARS="$3"
    419     local DSTFILE="$4"
    420     local CC="$5"
    421 
    422     # Now generate a small C source file that contains similarly-named stubs
    423     echo "/* Auto-generated file, do not edit */" > $TMPC
    424     local func var
    425     for func in $FUNCS; do
    426         echo "void $func(void) {}" >> $TMPC
    427     done
    428     for var in $VARS; do
    429         echo "int $var = 0;" >> $TMPC
    430     done
    431 
    432     # Build it with our cross-compiler. It will complain about conflicting
    433     # types for built-in functions, so just shut it up.
    434     COMMAND="$CC -Wl,-shared,-Bsymbolic -Wl,-soname,$LIBRARY -nostdlib -o $TMPO $TMPC"
    435     echo "## COMMAND: $COMMAND" > $TMPL
    436     $COMMAND 1>>$TMPL 2>&1
    437     if [ $? != 0 ] ; then
    438         dump "ERROR: Can't generate shared library for: $LIBNAME"
    439         dump "See the content of $TMPC and $TMPL for details."
    440         cat $TMPL | tail -10
    441         exit 1
    442     fi
    443 
    444     # Copy to our destination now
    445     local libdir=$(dirname "$DSTFILE")
    446     mkdir -p "$libdir" && rm -f "$DSTFILE" && cp -f $TMPO "$DSTFILE"
    447     if [ $? != 0 ] ; then
    448         dump "ERROR: Can't copy shared library for: $LIBNAME"
    449         dump "target location is: $DSTFILE"
    450         exit 1
    451     fi
    452 
    453     if [ "$OPTION_DEBUG_LIBS" ]; then
    454       cp $TMPC $DSTFILE.c
    455       echo "$FUNCS" > $DSTFILE.functions.txt
    456       echo "$VARS" > $DSTFILE.variables.txt
    457     fi
    458 }
    459 
    460 # $1: Architecture
    461 # $2: symbol source directory (relative to $SRCDIR)
    462 # $3: destination directory for generated libs (relative to $DSTDIR)
    463 # $4: compiler flags (optional)
    464 gen_shared_libraries ()
    465 {
    466     local ARCH=$1
    467     local SYMDIR="$SRCDIR/$2"
    468     local DSTDIR="$DSTDIR/$3"
    469     local FLAGS="$4"
    470     local CC funcs vars numfuncs numvars
    471 
    472     # Let's locate the toolchain we're going to use
    473     CC=$(get_default_compiler_for_arch $ARCH)" $FLAGS"
    474 
    475     # In certain cases, the symbols directory doesn't exist,
    476     # e.g. on x86 for PLATFORM < 9
    477     if [ ! -d "$SYMDIR" ]; then
    478         return
    479     fi
    480 
    481     # Let's list the libraries we're going to generate
    482     LIBS=$( (cd $SYMDIR && 2>/dev/null ls *.functions.txt) | sort -u | sed -e 's!\.functions\.txt$!!g')
    483 
    484     for LIB in $LIBS; do
    485         funcs=$(cat "$SYMDIR/$LIB.functions.txt" 2>/dev/null)
    486         vars=$(cat "$SYMDIR/$LIB.variables.txt" 2>/dev/null)
    487         funcs=$(remove_unwanted_function_symbols $ARCH libgcc.a $funcs)
    488         funcs=$(remove_unwanted_function_symbols $ARCH $LIB $funcs)
    489         vars=$(remove_unwanted_variable_symbols $ARCH $LIB $vars)
    490         numfuncs=$(echo $funcs | wc -w)
    491         numvars=$(echo $vars | wc -w)
    492         log "Generating $ARCH shared library for $LIB ($numfuncs functions + $numvars variables)"
    493 
    494         gen_shared_lib $LIB "$funcs" "$vars" "$DSTDIR/$LIB" "$CC"
    495     done
    496 }
    497 
    498 # $1: platform number
    499 # $2: architecture name
    500 # $3: common source directory (for crtbrand.c, etc)
    501 # $4: source directory (for *.S files)
    502 # $5: destination directory
    503 # $6: flags for compiler (optional)
    504 gen_crt_objects ()
    505 {
    506     local API=$1
    507     local ARCH=$2
    508     local COMMON_SRC_DIR="$SRCDIR/$3"
    509     local SRC_DIR="$SRCDIR/$4"
    510     local DST_DIR="$DSTDIR/$5"
    511     local FLAGS="$6"
    512     local SRC_FILE DST_FILE
    513     local CC
    514 
    515     if [ ! -d "$SRC_DIR" ]; then
    516         return
    517     fi
    518 
    519     # Let's locate the toolchain we're going to use
    520     CC=$(get_default_compiler_for_arch $ARCH)" $FLAGS"
    521 
    522     CRTBRAND_S=$DST_DIR/crtbrand.s
    523     log "Generating platform $API crtbrand assembly code: $CRTBRAND_S"
    524     (cd "$COMMON_SRC_DIR" && mkdir -p `dirname $CRTBRAND_S` && $CC -DPLATFORM_SDK_VERSION=$API -fpic -S -o - crtbrand.c | \
    525         sed -e '/\.note\.ABI-tag/s/progbits/note/' > "$CRTBRAND_S") 1>>$TMPL 2>&1
    526     if [ $? != 0 ]; then
    527         dump "ERROR: Could not generate $CRTBRAND_S from $COMMON_SRC_DIR/crtbrand.c"
    528         dump "Please see the content of $TMPL for details!"
    529         cat $TMPL | tail -10
    530         exit 1
    531     fi
    532 
    533     for SRC_FILE in $(cd "$SRC_DIR" && ls crt*.[cS]); do
    534         DST_FILE=${SRC_FILE%%.c}
    535         DST_FILE=${DST_FILE%%.S}.o
    536 
    537         case "$DST_FILE" in
    538             "crtend.o")
    539                 # Special case: crtend.S must be compiled as crtend_android.o
    540                 # This is for long historical reasons, i.e. to avoid name conflicts
    541                 # in the past with other crtend.o files. This is hard-coded in the
    542                 # Android toolchain configuration, so switch the name here.
    543                 DST_FILE=crtend_android.o
    544                 ;;
    545             "crtbegin_dynamic.o"|"crtbegin_static.o")
    546                 # Add .note.ABI-tag section
    547                 SRC_FILE=$SRC_FILE" $CRTBRAND_S"
    548                 ;;
    549             "crtbegin.o")
    550                 # If we have a single source for both crtbegin_static.o and
    551                 # crtbegin_dynamic.o we generate one and make a copy later.
    552                 DST_FILE=crtbegin_dynamic.o
    553                 # Add .note.ABI-tag section
    554                 SRC_FILE=$SRC_FILE" $CRTBRAND_S"
    555                 ;;
    556         esac
    557 
    558         log "Generating $ARCH C runtime object: $DST_FILE"
    559         (cd "$SRC_DIR" && $CC \
    560                  -I$SRCDIR/../../bionic/libc/include \
    561                  -I$SRCDIR/../../bionic/libc/arch-common/bionic \
    562                  -I$SRCDIR/../../bionic/libc/arch-$ARCH/include \
    563                  -DPLATFORM_SDK_VERSION=$API \
    564                  -O2 -fpic -Wl,-r -nostdlib -o "$DST_DIR/$DST_FILE" $SRC_FILE) 1>>$TMPL 2>&1
    565         if [ $? != 0 ]; then
    566             dump "ERROR: Could not generate $DST_FILE from $SRC_DIR/$SRC_FILE"
    567             dump "Please see the content of $TMPL for details!"
    568             cat $TMPL | tail -10
    569             exit 1
    570         fi
    571         if [ ! -s "$DST_DIR/crtbegin_static.o" ]; then
    572             cp "$DST_DIR/crtbegin_dynamic.o" "$DST_DIR/crtbegin_static.o"
    573         fi
    574     done
    575     rm -f "$CRTBRAND_S"
    576 }
    577 
    578 # $1: platform number
    579 # $2: architecture
    580 # $3: target NDK directory
    581 generate_api_level ()
    582 {
    583     local API=$1
    584     local ARCH=$2
    585     local HEADER="platforms/android-$API/arch-$ARCH/usr/include/android/api-level.h"
    586     log "Generating: $HEADER"
    587     rm -f "$3/$HEADER"  # Remove symlink if any.
    588 
    589     # hack to replace 'L' with large number
    590     if [ "$API" = "L" ]; then
    591         API="9999 /*'L'*/"
    592     fi
    593 
    594     cat > "$3/$HEADER" <<EOF
    595 /*
    596  * Copyright (C) 2008 The Android Open Source Project
    597  * All rights reserved.
    598  *
    599  * Redistribution and use in source and binary forms, with or without
    600  * modification, are permitted provided that the following conditions
    601  * are met:
    602  *  * Redistributions of source code must retain the above copyright
    603  *    notice, this list of conditions and the following disclaimer.
    604  *  * Redistributions in binary form must reproduce the above copyright
    605  *    notice, this list of conditions and the following disclaimer in
    606  *    the documentation and/or other materials provided with the
    607  *    distribution.
    608  *
    609  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    610  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    611  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
    612  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
    613  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
    614  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
    615  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
    616  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
    617  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    618  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    619  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    620  * SUCH DAMAGE.
    621  */
    622 #ifndef ANDROID_API_LEVEL_H
    623 #define ANDROID_API_LEVEL_H
    624 
    625 #define __ANDROID_API__ $API
    626 
    627 #endif /* ANDROID_API_LEVEL_H */
    628 EOF
    629 }
    630 
    631 # Copy platform sysroot and samples into your destination
    632 #
    633 
    634 # if $SRC/android-$PLATFORM/arch-$ARCH exists
    635 #   $SRC/android-$PLATFORM/include --> $DST/android-$PLATFORM/arch-$ARCH/usr/include
    636 #   $SRC/android-$PLATFORM/arch-$ARCH/include --> $DST/android-$PLATFORM/arch-$ARCH/usr/include
    637 #   $SRC/android-$PLATFORM/arch-$ARCH/lib --> $DST/android-$PLATFORM/arch-$ARCH/usr/lib
    638 #
    639 if [ -z "$OPTION_OVERLAY" ]; then
    640     rm -rf $DSTDIR/platforms && mkdir -p $DSTDIR/platforms
    641 fi
    642 for ARCH in $ARCHS; do
    643     # Find first platform for this arch
    644     PREV_SYSROOT_DST=
    645     PREV_PLATFORM_SRC_ARCH=
    646     LIBDIR=$(get_default_libdir_for_arch $ARCH)
    647 
    648     for PLATFORM in $PLATFORMS; do
    649         PLATFORM_DST=platforms/android-$PLATFORM   # Relative to $DSTDIR
    650         PLATFORM_SRC=$PLATFORM_DST                 # Relative to $SRCDIR
    651         SYSROOT_DST=$PLATFORM_DST/arch-$ARCH/usr
    652         # Skip over if there is no arch-specific file for this platform
    653         # and no destination platform directory was created. This is needed
    654         # because x86 and MIPS don't have files for API levels 3-8.
    655         if [ -z "$PREV_SYSROOT_DST" -a \
    656            ! -d "$SRCDIR/$PLATFORM_SRC/arch-$ARCH" ]; then
    657             log "Skipping: \$SRC/$PLATFORM_SRC/arch-$ARCH"
    658             continue
    659         fi
    660 
    661         log "Populating \$DST/platforms/android-$PLATFORM/arch-$ARCH"
    662 
    663         # If this is not the first destination directory, copy over, or
    664         # symlink the files from the previous one now.
    665         if [ "$PREV_SYSROOT_DST" ]; then
    666             if [ "$OPTION_FAST_COPY" ]; then
    667                 log "Copying \$DST/$PREV_SYSROOT_DST to \$DST/$SYSROOT_DST"
    668                 copy_directory "$DSTDIR/$PREV_SYSROOT_DST" "$DSTDIR/$SYSROOT_DST"
    669             else
    670                 log "Symlink-copying \$DST/$PREV_SYSROOT_DST to \$DST/$SYSROOT_DST"
    671                 symlink_src_directory $PREV_SYSROOT_DST $SYSROOT_DST
    672             fi
    673         fi
    674 
    675         # If this is the first destination directory, copy the common
    676         # files from previous platform directories into this one.
    677         # This helps copy the common headers from android-3 to android-8
    678         # into the x86 and mips android-9 directories.
    679         if [ -z "$PREV_SYSROOT_DST" ]; then
    680             for OLD_PLATFORM in $PLATFORMS; do
    681                 if [ "$OLD_PLATFORM" = "$PLATFORM" ]; then
    682                     break
    683                 fi
    684                 copy_src_directory platforms/android-$OLD_PLATFORM/include \
    685                                    $SYSROOT_DST/include \
    686                                    "common android-$OLD_PLATFORM headers"
    687             done
    688         fi
    689 
    690         # There are two set of bionic headers: the original ones haven't been updated since
    691         # gingerbread except for bug fixing, and the new ones in android-$FIRST_API64_LEVEL
    692         # with 64-bit support.  Before the old bionic headers are deprecated/removed, we need
    693         # to remove stale old headers when createing platform = $FIRST_API64_LEVEL
    694         if [ "$PLATFORM" = "$FIRST_API64_LEVEL" ]; then
    695             log "Removing stale bionic headers in \$DST/$SYSROOT_DST/include"
    696             nonbionic_files="android EGL GLES GLES2 GLES3 KHR media OMXAL SLES jni.h thread_db.h zconf.h zlib.h"
    697             if [ -d "$DSTDIR/$SYSROOT_DST/include/" ]; then
    698                 files=$(cd "$DSTDIR/$SYSROOT_DST/include/" && ls)
    699                 for file in $files; do
    700                     if [ "$nonbionic_files" = "${nonbionic_files%%${file}*}" ]; then
    701                         rm -rf "$DSTDIR/$SYSROOT_DST/include/$file"
    702                     fi
    703                 done
    704             fi
    705         fi
    706 
    707         # Now copy over all non-arch specific include files
    708         copy_src_directory $PLATFORM_SRC/include $SYSROOT_DST/include "common system headers"
    709         copy_src_directory $PLATFORM_SRC/arch-$ARCH/include $SYSROOT_DST/include "$ARCH system headers"
    710 
    711         generate_api_level "$PLATFORM" "$ARCH" "$DSTDIR"
    712 
    713         # If --minimal is not used, copy or generate binary files.
    714         if [ -z "$OPTION_MINIMAL" ]; then
    715             # Copy the prebuilt static libraries.  We need full set for multilib compiler for some arch
    716             case "$ARCH" in
    717                 x86_64)
    718                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib $SYSROOT_DST/lib "x86 sysroot libs"
    719                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib64 $SYSROOT_DST/lib64 "x86_64 sysroot libs"
    720                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/libx32 $SYSROOT_DST/libx32 "x32 sysroot libs"
    721                     ;;
    722                 mips64)
    723                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib $SYSROOT_DST/lib "mips -mabi=32 sysroot libs"
    724                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib64 $SYSROOT_DST/lib64 "mips -mabi=64 sysroot libs"
    725                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib32 $SYSROOT_DST/lib32 "mips -mabi=n32 sysroot libs"
    726                     ;;
    727                 *)
    728                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/$LIBDIR $SYSROOT_DST/$LIBDIR "$ARCH sysroot libs"
    729                     ;;
    730             esac
    731 
    732             # Generate C runtime object files when available
    733             PLATFORM_SRC_ARCH=$PLATFORM_SRC/arch-$ARCH/src
    734             if [ ! -d "$SRCDIR/$PLATFORM_SRC_ARCH" ]; then
    735                 PLATFORM_SRC_ARCH=$PREV_PLATFORM_SRC_ARCH
    736             else
    737                 PREV_PLATFORM_SRC_ARCH=$PLATFORM_SRC_ARCH
    738             fi
    739 
    740             # Genreate crt objects for known archs
    741             if [ "$(arch_in_unknown_archs $ARCH)" != "yes" ]; then
    742                 case "$ARCH" in
    743                     x86_64)
    744                         gen_crt_objects $PLATFORM $ARCH platforms/common/src $PLATFORM_SRC_ARCH $SYSROOT_DST/lib "-m32"
    745                         gen_crt_objects $PLATFORM $ARCH platforms/common/src $PLATFORM_SRC_ARCH $SYSROOT_DST/lib64 "-m64"
    746                         gen_crt_objects $PLATFORM $ARCH platforms/common/src $PLATFORM_SRC_ARCH $SYSROOT_DST/libx32 "-mx32"
    747                         ;;
    748                     mips64)
    749                         gen_crt_objects $PLATFORM $ARCH platforms/common/src $PLATFORM_SRC_ARCH $SYSROOT_DST/lib "-mabi=32"
    750                         gen_crt_objects $PLATFORM $ARCH platforms/common/src $PLATFORM_SRC_ARCH $SYSROOT_DST/lib64 "-mabi=64"
    751                         gen_crt_objects $PLATFORM $ARCH platforms/common/src $PLATFORM_SRC_ARCH $SYSROOT_DST/lib32 "-mabi=n32"
    752                         ;;
    753                     *)
    754                         gen_crt_objects $PLATFORM $ARCH platforms/common/src $PLATFORM_SRC_ARCH $SYSROOT_DST/$LIBDIR
    755                         ;;
    756                esac
    757             fi
    758 
    759             # Generate shared libraries from symbol files
    760             if [ "$(arch_in_unknown_archs $ARCH)" = "yes" ]; then
    761                 gen_shared_libraries $ARCH $PLATFORM_SRC/arch-$ARCH/symbols $SYSROOT_DST/lib "-target le32-none-ndk"
    762                 gen_shared_libraries $ARCH $PLATFORM_SRC/arch-$ARCH/symbols $SYSROOT_DST/lib64 "-target le64-none-ndk"
    763             else
    764                 case "$ARCH" in
    765                     x86_64)
    766                         gen_shared_libraries $ARCH $PLATFORM_SRC/arch-$ARCH/symbols $SYSROOT_DST/lib "-m32"
    767                         gen_shared_libraries $ARCH $PLATFORM_SRC/arch-$ARCH/symbols $SYSROOT_DST/lib64 "-m64"
    768                         gen_shared_libraries $ARCH $PLATFORM_SRC/arch-$ARCH/symbols $SYSROOT_DST/libx32 "-mx32"
    769                         ;;
    770                     mips64)
    771                         gen_shared_libraries $ARCH $PLATFORM_SRC/arch-$ARCH/symbols $SYSROOT_DST/lib "-mabi=32"
    772                         gen_shared_libraries $ARCH $PLATFORM_SRC/arch-$ARCH/symbols $SYSROOT_DST/lib64 "-mabi=64"
    773                         gen_shared_libraries $ARCH $PLATFORM_SRC/arch-$ARCH/symbols $SYSROOT_DST/lib32 "-mabi=n32"
    774                         ;;
    775                     *)
    776                         gen_shared_libraries $ARCH $PLATFORM_SRC/arch-$ARCH/symbols $SYSROOT_DST/$LIBDIR
    777                         ;;
    778                 esac
    779             fi
    780         else
    781             # Copy the prebuilt binaries to bootstrap GCC
    782             case "$ARCH" in
    783                 x86_64)
    784                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib-bootstrap/lib $SYSROOT_DST/lib "x86 sysroot libs (boostrap)"
    785                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib-bootstrap/lib64 $SYSROOT_DST/lib64 "x86_64 sysroot libs (boostrap)"
    786                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib-bootstrap/libx32 $SYSROOT_DST/libx32 "x32 sysroot libs (boostrap)"
    787                     ;;
    788                 mips64)
    789                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib-bootstrap/lib $SYSROOT_DST/lib "mips -mabi=32 sysroot libs (boostrap)"
    790                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib-bootstrap/lib64 $SYSROOT_DST/lib64 "mips -mabi=64 sysroot libs (boostrap)"
    791                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib-bootstrap/lib32 $SYSROOT_DST/lib32 "mips -mabi=n32 sysroot libs (boostrap)"
    792                     ;;
    793                 *)
    794                     copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib-bootstrap $SYSROOT_DST/$LIBDIR "$ARCH sysroot libs (boostrap)"
    795                     ;;
    796             esac
    797         fi
    798         PREV_SYSROOT_DST=$SYSROOT_DST
    799     done
    800 done
    801 
    802 #
    803 # $SRC/android-$PLATFORM/samples --> $DST/samples
    804 #
    805 if [ "$OPTION_SAMPLES" ] ; then
    806     # Copy platform samples and generic samples into your destination
    807     #
    808     # $SRC/samples/ --> $DST/samples/
    809     # $SRC/android-$PLATFORM/samples/ --> $DST/samples
    810     #
    811     dump "Copying generic samples"
    812     if [ -z "$OPTION_OVERLAY" ]; then
    813         rm -rf $DSTDIR/samples && mkdir -p $DSTDIR/samples
    814     fi
    815     copy_src_directory  samples samples samples
    816 
    817     for PLATFORM in $PLATFORMS; do
    818         dump "Copy android-$PLATFORM samples"
    819         # $SRC/platform-$PLATFORM/samples --> $DST/samples
    820         copy_src_directory platforms/android-$PLATFORM/samples samples samples
    821     done
    822 
    823     # Cleanup generated files in samples
    824     rm -rf "$DSTDIR/samples/*/obj"
    825     rm -rf "$DSTDIR/samples/*/libs"
    826 fi
    827 
    828 if [ "$PACKAGE_DIR" ]; then
    829     mkdir -p "$PACKAGE_DIR"
    830     fail_panic "Could not create package directory: $PACKAGE_DIR"
    831     ARCHIVE=platforms.tar.bz2
    832     dump "Packaging $ARCHIVE"
    833     pack_archive "$PACKAGE_DIR/$ARCHIVE" "$DSTDIR" "platforms"
    834     fail_panic "Could not package platforms"
    835     if [ "$OPTION_SAMPLES" ]; then
    836         ARCHIVE=samples.tar.bz2
    837         dump "Packaging $ARCHIVE"
    838         pack_archive "$PACKAGE_DIR/$ARCHIVE" "$DSTDIR" "samples"
    839         fail_panic "Could not package samples"
    840     fi
    841 fi
    842 
    843 log "Done !"
    844