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