#!/bin/sh # # Copyright (C) 2010 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # . `dirname $0`/prebuilt-common.sh PROGDIR=`dirname $0` PROGNAME=`basename $0` # This sets HOST_TAG to linux-x86 or darwin-x86 on 64-bit systems force_32bit_binaries PLATFORM= register_option "--platform=<name>" do_platform "Specify API level [autodetect]" do_platform () { PLATFORM=$1; } ARCH= register_option "--arch=<name>" do_arch "Specify architecture name [autodetect]" do_arch () { ARCH=$1; } OUT_DIR=/tmp/ndk-$USER/platforms-import register_var_option "--out-dir=<path>" OUT_DIR "Specify output directory" TOOLCHAIN_PREFIX= PROGRAM_PARAMETERS="<build-path>" PROGRAM_DESCRIPTION=\ "This script is used to import the NDK-exposed system libraries and headers from an existing platform build, and copy them to a temporary directory that will later be processed by another script (dev-platform-pack.sh) to archive them properly into the NDK directory structure (e.g. under development/ndk/platforms/). By default, the files will be copied to $OUT_DIR, but you can override this with the --out-dir=<path> option. The script also extracts the list of dynamic symbols exported by system libraries, filtering those that should not be exposed through the NDK. You can disable this with the --no-symbol-filtering option. The <build-path> parameter must point to the platform build output directory of a valid Android reference platform build. This is the value of the \$ANDROID_PRODUCT_OUT variable when doing a build configured with the 'lunch' utility. It usually looks like <top>/out/target/product/<name> where <top> is the top-level Android source tree, and <name> is the build product name (e.g. 'generic' or 'generic_x86' for emulator-specific builds). The API level is auto-detected from the content of <build-path>, but you can override it with --platform=<number>. This script is really in charge of the following tasks: 1/ Detect the platform build's API level by parsing the build.prop file. This can overriden with --platform=<number> 2/ Detect the platform build's target CPU architecture by parsing the build.prop file. This can be overriden with --arch=<name> 3/ Copy system headers from \$ANDROID/framework/base/ and other locations into \$OUT_DIR/android-\$API/include or \$OUT_DIR/android-\$API/arch-\$ARCH/include 4/ Locate system shared libraries from \$ANDROID_PRODUCT_OUT/system/lib and generate symbol files in \$OUT_DIR/android-\$API/arch-\$ARCH/symbols. 5/ Copy a few system static libraries (libc.a, libm.a, etc...) used to generate static executables. As well as a few key object files required by the C runtime (e.g. crtbegin_dynamic.o), when needed. " extract_parameters "$@" if [ -z "$PARAMETERS" ] ; then if [ -z "$ANDROID_PRODUCT_OUT" ]; then dump "ERROR: Missing path parameter to platform build, see --help for details" exit 1 fi # ANDROID_PRODUCT_OUT is defined, so use it log "Auto-config: using build path: $ANDROID_PRODUCT_OUT" else ANDROID_PRODUCT_OUT=$PARAMETERS fi # Sanity checks for the Android build path if [ ! -d "$ANDROID_PRODUCT_OUT" ]; then dump "ERROR: Not a directory: $ANDROID_PRODUCT_OUT" dump "Please point to a valid and complete Android build directory" exit 1 fi BUILD_PROP=$ANDROID_PRODUCT_OUT/system/build.prop if [ ! -f "$BUILD_PROP" ]; then dump "ERROR: Missing file: $BUILD_PROP" dump "Please point to a valid and complete Android build directory" exit 1 fi log "Extracting build properties from: $BUILD_PROP" # Try to get the architecture from build.prop if needed if [ -z "$ARCH" ]; then CPU_ABI=$(awk -F '=' '$1 == "ro.product.cpu.abi" { print $2; }' $BUILD_PROP) if [ $? != 0 ]; then dump "ERROR: Could not extract CPU ABI from $BUILD_PROP" dump "Please use --arch=<name> to override this. See --help" exit 1 fi log "Found target CPU ABI: $CPU_ABI" ARCH=$(convert_abi_to_arch $CPU_ABI) if [ -z "$ARCH" ]; then dump "ERROR: Can't translate $CPU_ABI ABI into CPU architecture!" exit 1 fi log "Auto-config: --arch=$ARCH" fi # Try to get the API level from build.prop if needed if [ -z "$PLATFORM" ]; then PLATFORM=$(awk -F '=' '$1 == "ro.build.version.sdk" { print $2; }' $BUILD_PROP) if [ $? != 0 ] ; then dump "WARNING: Could not extract default platform level from $BUILD_PROP!" dump "Please use --platform=<name> to override this. See --help" exit 1 fi if [ -z "$PLATFORM" ]; then dump "ERROR: Couldn't extract API level from: $BUILD_PROP" exit 1 fi log "Auto-config: --platform=$PLATFORM" fi # Normalize platform name, i.e. # 3 -> 3 # android-3 -> 3 # PLATFORM=${PLATFORM##android-} PLATFORM_ROOT=$OUT_DIR/android-$PLATFORM/arch-$ARCH log "Using platform destination path: $PLATFORM_ROOT" # Return the list of files under a given directory # $1: directory # $2: (optional) file patterns list_regular_files_in () { local DIR="$1" shift local PATTERNS="$@" if [ -z "$PATTERNS" ]; then PATTERNS="." fi cd "$DIR" && find $PATTERNS -type f | sed -e 's!^./!!g' } # Check that a given platform level was listed on the command line # $1: Platform numerical level (e.g. '3') # returns true if the platform is listed platform_check () { [ "$PLATFORM" -ge "$1" ] } # Determine Android build tree root ANDROID_ROOT=`cd $ANDROID_PRODUCT_OUT/../../../.. && pwd` log "Android build tree root: $ANDROID_ROOT" log "Android product out: $ANDROID_PRODUCT_OUT" if [ -z "$TOOLCHAIN_PREFIX" ]; then TOOLCHAIN_NAME=$(get_default_toolchain_name_for_arch $ARCH) TOOLCHAIN_PREFIX=$(get_default_toolchain_prefix_for_arch $ARCH) TOOLCHAIN_PREFIX=$(get_toolchain_install $ANDROID_NDK_ROOT $TOOLCHAIN_NAME)/bin/$TOOLCHAIN_PREFIX TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX%%-} if [ -z "$TOOLCHAIN_PREFIX" ]; then echo "ERROR: Unsupported architecture" exit 1 fi log "Auto-config: --toolchain-prefix=$TOOLCHAIN_PREFIX" fi if [ ! -d "$(dirname $TOOLCHAIN_PREFIX)" ]; then echo "ERROR: Toolchain not installed, missing directory: $(dirname $TOOLCHAIN_PREFIX)" exit 1 fi if [ ! -f "$TOOLCHAIN_PREFIX-readelf" ]; then echo "ERROR: Toolchain not installed, missing program: $TOOLCHAIN_PREFIX-readelf" exit 1 fi # 'Copy' a given system library. This really reads the shared library to # to generate a small shell version that will be installed at the destination # $1: Library name (e.g. libEGL.so) # copy_system_shared_library () { local src="$ANDROID_PRODUCT_OUT/system/lib/$1.so" if [ ! -f "$src" ] ; then dump "ERROR: Missing system library: $src" exit 1 fi local dst="$PLATFORM_ROOT/lib/$1.so" mkdir -p `dirname "$dst"` && cp "$src" "$dst" } copy_system_static_library () { local src="$ANDROID_PRODUCT_OUT/obj/STATIC_LIBRARIES/$1_intermediates/$1.a" if [ ! -f "$src" ] ; then dump "ERROR: Missing system static library: $src" exit 1 fi local dst="$PLATFORM_ROOT/lib/$1.a" log "Copying system static library: $1.a" mkdir -p `dirname "$dst"` && cp -f "$src" "$dst" } copy_system_object_file () { local src="$ANDROID_PRODUCT_OUT/obj/lib/$1.o" if [ ! -f "$src" ] ; then dump "ERROR: Missing system object file: $src" exit 1 fi local dst="$PLATFORM_ROOT/lib/$1.o" log "Copying system object file: $1.o" mkdir -p `dirname "$dst"` && cp -f "$src" "$dst" } # Copy the content of a given directory to $SYSROOT/usr/include # $1: Source directory # $2+: List of headers copy_system_headers () { local srcdir="$1" shift local header log "Copying system headers from: $srcdir" for header; do log " $header" local src="$srcdir/$header" local dst="$PLATFORM_ROOT/../include/$header" if [ ! -f "$srcdir/$header" ] ; then dump "ERROR: Missing system header: $srcdir/$header" exit 1 fi mkdir -p `dirname "$dst"` && cp -f "$src" "$dst" if [ $? != 0 ] ; then dump "ERROR: Could not copy system header: $src" dump "Target location: $dst" exit 1 fi done } # Copy all headers found under $1 # $1: source directory copy_system_headers_from () { local headers=$(list_regular_files_in "$1") copy_system_headers $1 $headers } # Same as copy_system_headers, but for arch-specific files # $1: Source directory # $2+: List of headers copy_arch_system_headers () { local srcdir="$1" shift local header for header; do log "Copying $arch system header: $header" local src="$srcdir/$header" local dst="$PLATFORM_ROOT/include/$header" if [ ! -f "$srcdir/$header" ] ; then dump "ERROR: Missing $ARCH system header: $srcdir/$header" exit 1 fi mkdir -p `dirname "$dst"` && cp -f "$src" "$dst" if [ $? != 0 ] ; then dump "ERROR: Could not copy $ARCH system header: $src" dump "Target location: $dst" exit 1 fi done } copy_arch_system_headers_from () { local headers=$(list_regular_files_in "$1") copy_arch_system_headers $1 $headers } copy_arch_kernel_headers_from () { local headers=$(list_regular_files_in "$1" asm) copy_arch_system_headers $1 $headers } # Probe for the location of the OpenSLES sources in the # platform tree. This used to be system/media/opensles but # was moved to system/media/wilhelm in Android 4.0 OPENSLES_SUBDIR=system/media/wilhelm if [ ! -d "$ANDROID_ROOT/$OPENSLES_SUBDIR" ]; then OPENSLES_SUBDIR=system/media/opensles fi # Now do the work # API level 3 if platform_check 3; then copy_system_shared_library libc copy_system_static_library libc copy_system_headers_from $ANDROID_ROOT/bionic/libc/include copy_arch_system_headers_from $ANDROID_ROOT/bionic/libc/arch-$ARCH/include copy_arch_kernel_headers_from $ANDROID_ROOT/bionic/libc/kernel/arch-$ARCH copy_system_object_file crtbegin_dynamic copy_system_object_file crtbegin_static copy_system_object_file crtend_android case $ARCH in x86) copy_system_object_file crtbegin_so copy_system_object_file crtend_so ;; esac copy_system_shared_library libm copy_system_static_library libm copy_system_headers $ANDROID_ROOT/bionic/libm/include math.h case "$ARCH" in x86 ) copy_arch_system_headers $ANDROID_ROOT/bionic/libm/include/i387 fenv.h ;; * ) copy_arch_system_headers $ANDROID_ROOT/bionic/libm/$ARCH fenv.h ;; esac # The <dlfcn.h> header was already copied from bionic/libc/include copy_system_shared_library libdl # There is no libdl.a at the moment, we might need one in # the future to build gdb-7.1.x though. copy_system_shared_library libz copy_system_static_library libz copy_system_headers $ANDROID_ROOT/external/zlib zconf.h zlib.h copy_system_shared_library liblog copy_system_headers $ANDROID_ROOT/system/core/include android/log.h # NOTE: We do not copy the C++ headers, they are part of the NDK # under $NDK/source/cxx-stl. They were separated from the rest # of the platform headers in order to make room for other STL # implementations (e.g. STLport or GNU Libstdc++-v3) # copy_system_shared_library libstdc++ copy_system_static_library libstdc++ copy_system_headers $ANDROID_ROOT/libnativehelper/include/nativehelper jni.h fi # API level 4 if platform_check 4; then copy_system_shared_library libGLESv1_CM copy_system_headers $ANDROID_ROOT/frameworks/base/opengl/include \ GLES/gl.h \ GLES/glext.h \ GLES/glplatform.h copy_system_headers $ANDROID_ROOT/frameworks/base/opengl/include \ KHR/khrplatform.h fi # API level 5 if platform_check 5; then copy_system_shared_library libGLESv2 copy_system_headers $ANDROID_ROOT/frameworks/base/opengl/include \ GLES2/gl2.h \ GLES2/gl2ext.h \ GLES2/gl2platform.h fi # API level 8 if platform_check 8; then copy_system_shared_library libandroid copy_system_shared_library libjnigraphics copy_system_headers $ANDROID_ROOT/frameworks/base/native/include \ android/bitmap.h fi # API level 9 if platform_check 9; then case $ARCH in arm) copy_system_object_file crtbegin_so copy_system_object_file crtend_so ;; esac copy_system_shared_library libandroid copy_system_headers $ANDROID_ROOT/frameworks/base/native/include \ android/asset_manager.h \ android/asset_manager_jni.h \ android/configuration.h \ android/input.h \ android/keycodes.h \ android/looper.h \ android/native_activity.h \ android/native_window.h \ android/native_window_jni.h \ android/obb.h \ android/rect.h \ android/sensor.h \ android/storage_manager.h \ android/window.h copy_system_shared_library libEGL copy_system_headers $ANDROID_ROOT/frameworks/base/opengl/include \ EGL/egl.h \ EGL/eglext.h \ EGL/eglplatform.h copy_system_shared_library libOpenSLES copy_system_headers $ANDROID_ROOT/$OPENSLES_SUBDIR/include \ SLES/OpenSLES.h \ SLES/OpenSLES_Android.h \ SLES/OpenSLES_AndroidConfiguration.h \ SLES/OpenSLES_Platform.h fi # API level 14 if platform_check 14; then copy_system_shared_library libOpenMAXAL copy_system_headers $ANDROID_ROOT/system/media/wilhelm/include \ OMXAL/OpenMAXAL.h \ OMXAL/OpenMAXAL_Android.h \ OMXAL/OpenMAXAL_Platform.h # This header is new in API level 14 copy_system_headers $ANDROID_ROOT/$OPENSLES_SUBDIR/include \ SLES/OpenSLES_AndroidMetadata.h fi # Now extract dynamic symbols from the copied shared libraries # Note that this script will also filter unwanted symbols log "Generating symbol files" $PROGDIR/gen-system-symbols.sh "$PLATFORM_ROOT/lib" "$PLATFORM_ROOT/symbols" # Remove copied shared libraries, we don't need them anymore # They will be replaced by auto-generated shells by gen-platforms.sh # log "Cleaning: $PLATFORM_ROOT/lib/lib*.so" rm -f "$PLATFORM_ROOT"/lib/lib*.so log "Done!"