• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 shell 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
39PROGDIR=$(dirname "$0")
40. "$PROGDIR/prebuilt-common.sh"
41
42# Return the list of platform supported from $1/platforms
43# as a single space-separated list of levels. (e.g. "3 4 5 8 9")
44# $1: source directory
45extract_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
54SRCDIR="../development/ndk"
55DSTDIR="$ANDROID_NDK_ROOT"
56
57ARCHS="$DEFAULT_ARCHS"
58PLATFORMS=`extract_platforms_from "$SRCDIR"`
59NDK_DIR=$ANDROID_NDK_ROOT
60
61OPTION_HELP=no
62OPTION_PLATFORMS=
63OPTION_SRCDIR=
64OPTION_DSTDIR=
65OPTION_SAMPLES=
66OPTION_FAST_COPY=
67OPTION_MINIMAL=
68OPTION_ARCH=
69OPTION_ABI=
70PACKAGE_DIR=
71
72VERBOSE=no
73VERBOSE2=no
74
75for opt do
76  optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
77  case "$opt" in
78  --help|-h|-\?) OPTION_HELP=yes
79  ;;
80  --verbose)
81    if [ "$VERBOSE" = "yes" ] ; then
82        VERBOSE2=yes
83    else
84        VERBOSE=yes
85    fi
86    ;;
87  --src-dir=*)
88    OPTION_SRCDIR="$optarg"
89    ;;
90  --dst-dir=*)
91    OPTION_DSTDIR="$optarg"
92    ;;
93  --ndk-dir=*)
94    NDK_DIR=$optarg
95    ;;
96  --platform=*)
97    OPTION_PLATFORM=$optarg
98    ;;
99  --arch=*)
100    OPTION_ARCH=$optarg
101    ;;
102  --abi=*)  # We still support this for backwards-compatibility
103    OPTION_ABI=$optarg
104    ;;
105  --samples)
106    OPTION_SAMPLES=yes
107    ;;
108  --fast-copy)
109    OPTION_FAST_COPY=yes
110    ;;
111  --minimal)
112    OPTION_MINIMAL=yes
113    ;;
114  --package-dir=*)
115    PACKAGE_DIR=$optarg
116    ;;
117  *)
118    echo "unknown option '$opt', use --help"
119    exit 1
120  esac
121done
122
123if [ $OPTION_HELP = "yes" ] ; then
124    echo "Collect files from an Android NDK development tree and assemble"
125    echo "the platform files appropriately into a final release structure."
126    echo ""
127    echo "options:"
128    echo ""
129    echo "  --help                Print this message"
130    echo "  --verbose             Enable verbose messages"
131    echo "  --src-dir=<path>      Source directory for development platform files [$SRCDIR]"
132    echo "  --dst-dir=<path>      Destination directory [$DSTDIR]"
133    echo "  --ndk-dir=<path>      Use toolchains from this NDK directory [$NDK_DIR]"
134    echo "  --platform=<list>     List of API levels [$PLATFORMS]"
135    echo "  --arch=<list>         List of CPU architectures [$ARCHS]"
136    echo "  --minimal             Ignore samples, symlinks and generated shared libs."
137    echo "  --fast-copy           Don't create symlinks, copy files instead"
138    echo "  --samples             Also generate samples directories."
139    echo "  --package-dir=<path>  Package platforms archive in specific path."
140    echo ""
141    echo "Use the --minimal flag if you want to generate minimal sysroot directories"
142    echo "that will be used to generate prebuilt toolchains. Otherwise, the script"
143    echo "will require these toolchains to be pre-installed and will use them to"
144    echo "generate shell system shared libraries from the symbol list files."
145    exit 0
146fi
147
148if [ -n "$OPTION_SRCDIR" ] ; then
149    SRCDIR="$OPTION_SRCDIR";
150    if [ ! -d "$SRCDIR" ] ; then
151        echo "ERROR: Source directory $SRCDIR does not exist !"
152        exit 1
153    fi
154    if [ ! -d "$SRCDIR/platforms/android-3" ] ; then
155        echo "ERROR: Invalid source directory: $SRCDIR"
156        echo "Please make sure it contains platforms/android-3 etc..."
157        exit 1
158    fi
159else
160    SRCDIR=`dirname $ANDROID_NDK_ROOT`/development/ndk
161    log "Using source directory: $SRCDIR"
162fi
163
164if [ -n "$OPTION_PLATFORM" ] ; then
165    PLATFORMS=$(commas_to_spaces $OPTION_PLATFORM)
166else
167    # Build the list from the content of SRCDIR
168    PLATFORMS=`extract_platforms_from "$SRCDIR"`
169    log "Using platforms: $PLATFORMS"
170fi
171
172# Remove the android- prefix of any platform name
173PLATFORMS=$(echo $PLATFORMS | tr ' ' '\n' | sed -e 's!^android-!!g' | tr '\n' ' ')
174
175if [ -n "$OPTION_DSTDIR" ] ; then
176    DSTDIR="$OPTION_DSTDIR"
177else
178    log "Using destination directory: $DSTDIR"
179fi
180
181# Handle architecture list
182#
183# We support both --arch and --abi for backwards compatibility reasons
184# --arch is the new hotness, --abi is deprecated.
185#
186if [ -n "$OPTION_ARCH" ]; then
187    OPTION_ARCH=$(commas_to_spaces $OPTION_ARCH)
188fi
189
190if [ -n "$OPTION_ABI" ] ; then
191    echo "WARNING: --abi=<names> is deprecated. Use --arch=<names> instead!"
192    OPTION_ABI=$(commas_to_spaces $OPTION_ABI)
193    if [ -n "$OPTION_ARCH" -a "$OPTION_ARCH" != "$OPTION_ABI" ]; then
194        echo "ERROR: You can't use both --abi and --arch with different values!"
195        exit 1
196    fi
197    OPTION_ARCH=$OPTION_ABI
198fi
199
200if [ -n "$OPTION_ARCH" ] ; then
201    ARCHS="$OPTION_ARCH"
202fi
203log "Using architectures: $(commas_to_spaces $ARCHS)"
204
205log "Checking source platforms."
206for PLATFORM in $PLATFORMS; do
207    DIR="$SRCDIR/platforms/android-$PLATFORM"
208    if [ ! -d $DIR ] ; then
209        echo "ERROR: Directory missing: $DIR"
210        echo "Please check your --platform=<list> option and try again."
211        exit 2
212    else
213        log "  $DIR"
214    fi
215done
216
217log "Checking source platform architectures."
218BAD_ARCHS=
219for ARCH in $ARCHS; do
220    eval CHECK_$ARCH=no
221done
222for PLATFORM in $PLATFORMS; do
223    for ARCH in $ARCHS; do
224        DIR="$SRCDIR/platforms/android-$PLATFORM/arch-$ARCH"
225        if [ -d $DIR ] ; then
226            log "  $DIR"
227            eval CHECK_$ARCH=yes
228        fi
229    done
230done
231
232if [ "$OPTION_MINIMAL" ]; then
233    OPTION_SAMPLES=
234    OPTION_FAST_COPY=yes
235fi
236
237BAD_ARCHS=
238for ARCH in $ARCHS; do
239    CHECK=`var_value CHECK_$ARCH`
240    log "  $ARCH check: $CHECK"
241    if [ "$CHECK" = no ] ; then
242        if [ -z "$BAD_ARCHS" ] ; then
243            BAD_ARCHS=$ARCH
244        else
245            BAD_ARCHS="$BAD_ARCHS $ARCH"
246        fi
247    fi
248done
249
250if [ -n "$BAD_ARCHS" ] ; then
251    echo "ERROR: Source directory doesn't support these ARCHs: $BAD_ARCHS"
252    exit 3
253fi
254
255# $1: source directory (relative to $SRCDIR)
256# $2: destination directory (relative to $DSTDIR)
257# $3: description of directory contents (e.g. "sysroot" or "samples")
258copy_src_directory ()
259{
260    local SDIR="$SRCDIR/$1"
261    local DDIR="$DSTDIR/$2"
262    if [ -d "$SDIR" ] ; then
263        log "Copying $3 from \$SRC/$1 to \$DST/$2."
264        mkdir -p "$DDIR" && (cd "$SDIR" && 2>/dev/null tar chf - *) | (tar xf - -C "$DDIR")
265        if [ $? != 0 ] ; then
266            echo "ERROR: Could not copy $3 directory $SDIR into $DDIR !"
267            exit 5
268        fi
269    fi
270}
271
272# $1: source dir
273# $2: destination dir
274# $3: reverse path
275#
276symlink_src_directory_inner ()
277{
278    local files file subdir rev
279    mkdir -p "$DSTDIR/$2"
280    rev=$3
281    files=$(cd $DSTDIR/$1 && ls -1p)
282    for file in $files; do
283        if [ "$file" = "${file%%/}" ]; then
284            log "Link \$DST/$2/$file --> $rev/$1/$file"
285            ln -s $rev/$1/$file $DSTDIR/$2/$file
286        else
287            file=${file%%/}
288            symlink_src_directory_inner "$1/$file" "$2/$file" "$rev/.."
289        fi
290    done
291}
292# Create a symlink-copy of directory $1 into $2
293# This function is recursive.
294#
295# $1: source directory (relative to $SRCDIR)
296# $2: destination directory (relative to $DSTDIR)
297symlink_src_directory ()
298{
299    symlink_src_directory_inner "$1" "$2" "$(reverse_path $1)"
300}
301
302# $1: Architecture name
303# $2+: List of symbols
304# out: Input list, without any libgcc symbol
305remove_libgcc_symbols ()
306{
307    local ARCH=$1
308    shift
309    echo "$@" | tr ' ' '\n' | grep -v -F -f $PROGDIR/toolchain-symbols/$ARCH/libgcc.a.functions.txt
310}
311
312# $1: library name
313# $2: functions list
314# $3: variables list
315# $4: destination file
316# $5: toolchain binprefix
317gen_shell_lib ()
318{
319    # Now generate a small C source file that contains similarly-named stubs
320    echo "/* Auto-generated file, do not edit */" > $TMPC
321    local func var
322    for func in $2; do
323        echo "void $func(void) {}" >> $TMPC
324    done
325    for var in $3; do
326        echo "int $var = 0;" >> $TMPC
327    done
328
329    # Build it with our cross-compiler. It will complain about conflicting
330    # types for built-in functions, so just shut it up.
331    $5-gcc -Wl,-shared,-Bsymbolic -nostdlib -o $TMPO $TMPC 1>/dev/null 2>&1
332    if [ $? != 0 ] ; then
333        dump "ERROR: Can't generate shell library for: $1"
334        dump "See the content of $TMPC for details."
335        exit 1
336    fi
337
338    # Copy to our destination now
339    local libdir=$(dirname "$4")
340    mkdir -p "$libdir" && cp -f $TMPO "$4"
341    if [ $? != 0 ] ; then
342        dump "ERROR: Can't copy shell library for: $1"
343        dump "target location is: $4"
344        exit 1
345    fi
346}
347
348# $1: Architecture
349# $2: symbol source directory (relative to $SRCDIR)
350# $3: destination directory for generated libs (relative to $DSTDIR)
351gen_shell_libraries ()
352{
353    local ARCH=$1
354    local SYMDIR="$SRCDIR/$2"
355    local DSTDIR="$DSTDIR/$3"
356    local TOOLCHAIN_PREFIX funcs vars numfuncs numvars
357
358    # Let's locate the toolchain we're going to use
359    local TOOLCHAIN_PREFIX="$NDK_DIR/$(get_default_toolchain_binprefix_for_arch $1)"
360    TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX%-}
361    if [ ! -f "$TOOLCHAIN_PREFIX-readelf" ]; then
362        dump "ERROR: $ARCH toolchain not installed: $TOOLCHAIN_PREFIX-gcc"
363        dump "Important: Use the --minimal flag to use this script without generated system shared libraries."
364        dump "This is generally useful when you want to generate the host cross-toolchain programs."
365        exit 1
366    fi
367
368    # In certain cases, the symbols directory doesn't exist,
369    # e.g. on x86 for PLATFORM < 9
370    if [ ! -d "$SYMDIR" ]; then
371        return
372    fi
373
374    # Let's list the libraries we're going to generate
375    LIBS=$( (cd $SYMDIR && 2>/dev/null ls *.functions.txt) | sort -u | sed -e 's!\.functions\.txt$!!g')
376
377    for LIB in $LIBS; do
378        funcs=$(cat "$SYMDIR/$LIB.functions.txt")
379        vars=
380        if [ -f "$SYMDIR/$LIB.variables.txt" ]; then
381            vars=$(cat "$SYMDIR/$LIB.variables.txt")
382        fi
383        funcs=$(remove_libgcc_symbols $ARCH $funcs)
384        numfuncs=$(echo $funcs | wc -w)
385        numvars=$(echo $vars | wc -w)
386        log "Generating shell library for $LIB ($numfuncs functions + $numvars variables)"
387
388        gen_shell_lib $LIB "$funcs" "$vars" "$DSTDIR/$LIB" "$TOOLCHAIN_PREFIX"
389    done
390}
391
392# $1: platform number
393# $2: architecture
394# $3: target NDK directory
395generate_api_level ()
396{
397    local API=$1
398    local ARCH=$2
399    local HEADER="platforms/android-$API/arch-$ARCH/usr/include/android/api-level.h"
400    log dump "Generating: $HEADER"
401    cat > "$3/$HEADER" <<EOF
402/*
403 * Copyright (C) 2008 The Android Open Source Project
404 * All rights reserved.
405 *
406 * Redistribution and use in source and binary forms, with or without
407 * modification, are permitted provided that the following conditions
408 * are met:
409 *  * Redistributions of source code must retain the above copyright
410 *    notice, this list of conditions and the following disclaimer.
411 *  * Redistributions in binary form must reproduce the above copyright
412 *    notice, this list of conditions and the following disclaimer in
413 *    the documentation and/or other materials provided with the
414 *    distribution.
415 *
416 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
417 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
418 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
419 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
420 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
421 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
422 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
423 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
424 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
425 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
426 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
427 * SUCH DAMAGE.
428 */
429#ifndef ANDROID_API_LEVEL_H
430#define ANDROID_API_LEVEL_H
431
432#define __ANDROID_API__ $API
433
434#endif /* ANDROID_API_LEVEL_H */
435EOF
436}
437
438# Copy platform sysroot and samples into your destination
439#
440
441# $SRC/android-$PLATFORM/include --> $DST/platforms/android-$PLATFORM/arch-$ARCH/usr/include
442# $SRC/android-$PLATFORM/arch-$ARCH/include --> $DST/platforms/android-$PLATFORM/arch-$ARCH/usr/include
443# for compatibility:
444# $SRC/android-$PLATFORM/arch-$ARCH/usr/include --> $DST/platforms/android-$PLATFORM/arch-$ARCH/usr/include
445
446
447
448# $SRC/android-$PLATFORM/arch-$ARCH/usr --> $DST/platforms/android-$PLATFORM/arch-$ARCH/usr
449# $SRC/android-$PLATFORM/samples       --> $DST/samples
450#
451rm -rf $DSTDIR/platforms && mkdir -p $DSTDIR/platforms
452PREV_PLATFORM_DST=
453for PLATFORM in $PLATFORMS; do
454    NEW_PLATFORM=platforms/android-$PLATFORM
455    PLATFORM_SRC=$NEW_PLATFORM
456    PLATFORM_DST=$NEW_PLATFORM
457    dump "Copying android-$PLATFORM platform files"
458    if [ -n "$PREV_PLATFORM_DST" ] ; then
459        if [ "$OPTION_FAST_COPY" ] ; then
460            log "Copying \$DST/$PREV_PLATFORM_DST to \$DST/$PLATFORM_DST"
461            #cp -r $DSTDIR/$PREV_PLATFORM_DST $DSTDIR/$PLATFORM_DST
462            copy_directory "$DSTDIR/$PREV_PLATFORM_DST" "$DSTDIR/$PLATFORM_DST"
463        else
464            log "Symlink-copying \$DST/$PREV_PLATFORM_DST to \$DST/$PLATFORM_DST"
465            symlink_src_directory $PREV_PLATFORM_DST $PLATFORM_DST
466        fi
467        if [ $? != 0 ] ; then
468            echo "ERROR: Could not copy previous sysroot to $DSTDIR/$NEW_PLATFORM"
469            exit 4
470        fi
471    fi
472    for ARCH in $ARCHS; do
473        SYSROOT=arch-$ARCH/usr
474        log "Copy $ARCH sysroot files from \$SRC/android-$PLATFORM over \$DST/android-$PLATFORM/arch-$ARCH"
475        copy_src_directory $PLATFORM_SRC/include           $PLATFORM_DST/$SYSROOT/include "sysroot headers"
476        copy_src_directory $PLATFORM_SRC/arch-$ARCH/include $PLATFORM_DST/$SYSROOT/include "sysroot headers"
477        copy_src_directory $PLATFORM_SRC/arch-$ARCH/lib     $PLATFORM_DST/$SYSROOT/lib "sysroot libs"
478        copy_src_directory $PLATFORM_SRC/$SYSROOT          $PLATFORM_DST/$SYSROOT "sysroot"
479
480        generate_api_level "$PLATFORM" "$ARCH" "$DSTDIR"
481
482        if [ -z "$OPTION_MINIMAL" ]; then
483            # Generate shell libraries from symbol files
484            gen_shell_libraries $ARCH $PLATFORM_SRC/arch-$ARCH/symbols $PLATFORM_DST/$SYSROOT/lib
485        fi
486    done
487    PREV_PLATFORM_DST=$PLATFORM_DST
488done
489
490if [ "$OPTION_SAMPLES" ] ; then
491    # Copy platform samples and generic samples into your destination
492    #
493    # $SRC/samples/ --> $DST/samples/
494    # $SRC/android-$PLATFORM/samples/ --> $DST/samples
495    #
496    dump "Copying generic samples"
497    rm -rf $DSTDIR/samples && mkdir -p $DSTDIR/samples
498    copy_src_directory  samples samples samples
499
500    for PLATFORM in $PLATFORMS; do
501        dump "Copy android-$PLATFORM samples"
502        # $SRC/platform-$PLATFORM/samples --> $DST/samples
503        copy_src_directory platforms/android-$PLATFORM/samples samples samples
504    done
505
506    # Cleanup generated files in samples
507    rm -rf "$DSTDIR/samples/*/obj"
508    rm -rf "$DSTDIR/samples/*/libs"
509fi
510
511if [ "$PACKAGE_DIR" ]; then
512    mkdir -p "$PACKAGE_DIR"
513    fail_panic "Could not create package directory: $PACKAGE_DIR"
514    ARCHIVE=platforms.tar.bz2
515    dump "Packaging $ARCHIVE"
516    pack_archive "$PACKAGE_DIR/$ARCHIVE" "$DSTDIR" "platforms"
517    fail_panic "Could not package platforms"
518    if [ "$OPTION_SAMPLES" ]; then
519        ARCHIVE=samples.tar.bz2
520        dump "Packaging $ARCHIVE"
521        pack_archive "$PACKAGE_DIR/$ARCHIVE" "$DSTDIR" "samples"
522        fail_panic "Could not package samples"
523    fi
524fi
525
526log "Done !"
527