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