#!/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!"