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