1#!/bin/sh
2#
3# Copyright (C) 2010 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
18. `dirname $0`/prebuilt-common.sh
19PROGDIR=`dirname $0`
20PROGNAME=`basename $0`
21
22# This sets HOST_TAG to linux-x86 or darwin-x86 on 64-bit systems
23force_32bit_binaries
24
25PLATFORM=
26register_option "--platform=<name>" do_platform "Specify API level [autodetect]"
27do_platform () { PLATFORM=$1; }
28
29ARCH=
30register_option "--arch=<name>" do_arch "Specify architecture name [autodetect]"
31do_arch () { ARCH=$1; }
32
33OUT_DIR=$TMPDIR/platforms-import
34register_var_option "--out-dir=<path>" OUT_DIR "Specify output directory"
35
36TOOLCHAIN_PREFIX=
37
38PROGRAM_PARAMETERS="<build-path>"
39PROGRAM_DESCRIPTION=\
40"This script is used to import the NDK-exposed system libraries and headers from
41an existing platform build, and copy them to a temporary directory that will later
42be processed by another script (dev-platform-pack.sh) to archive them properly into
43the NDK directory structure (e.g. under development/ndk/platforms/).
44
45By default, the files will be copied to $OUT_DIR, but you can
46override this with the --out-dir=<path> option.
47
48The script also extracts the list of dynamic symbols exported by system libraries,
49filtering those that should not be exposed through the NDK. You can disable this
50with the --no-symbol-filtering option.
51
52The <build-path> parameter must point to the platform build output directory
53of a valid Android reference platform build. This is the value of the
54\$ANDROID_PRODUCT_OUT variable when doing a build configured with the 'lunch'
55utility. It usually looks like <top>/out/target/product/<name> where <top> is
56the top-level Android source tree, and <name> is the build product name
57(e.g. 'generic' or 'generic_x86' for emulator-specific builds).
58
59The API level is auto-detected from the content of <build-path>, but you
60can override it with --platform=<number>.
61
62This script is really in charge of the following tasks:
63
64  1/ Detect the platform build's API level by parsing the build.prop
65     file. This can overriden with --platform=<number>
66
67  2/ Detect the platform build's target CPU architecture by parsing
68     the build.prop file. This can be overriden with --arch=<name>
69
70  3/ Copy system headers from \$ANDROID/framework/base/ and other
71     locations into \$OUT_DIR/android-\$API/include or
72     \$OUT_DIR/android-\$API/arch-\$ARCH/include
73
74  4/ Locate system shared libraries from \$ANDROID_PRODUCT_OUT/system/lib
75     and generate symbol files in \$OUT_DIR/android-\$API/arch-\$ARCH/symbols.
76
77  5/ Copy a few system static libraries (libc.a, libm.a, etc...) used
78     to generate static executables. As well as a few key object files
79     required by the C runtime (e.g. crtbegin_dynamic.o), when needed.
80
81"
82
83
84extract_parameters "$@"
85
86if [ -z "$PARAMETERS" ] ; then
87    if [ -z "$ANDROID_PRODUCT_OUT" ]; then
88        dump "ERROR: Missing path parameter to platform build, see --help for details"
89        exit 1
90    fi
91    # ANDROID_PRODUCT_OUT is defined, so use it
92    log "Auto-config: using build path: $ANDROID_PRODUCT_OUT"
93else
94    ANDROID_PRODUCT_OUT=$PARAMETERS
95fi
96
97# Sanity checks for the Android build path
98if [ ! -d "$ANDROID_PRODUCT_OUT" ]; then
99    dump "ERROR: Not a directory: $ANDROID_PRODUCT_OUT"
100    dump "Please point to a valid and complete Android build directory"
101    exit 1
102fi
103
104BUILD_PROP=$ANDROID_PRODUCT_OUT/system/build.prop
105if [ ! -f "$BUILD_PROP" ]; then
106    dump "ERROR: Missing file: $BUILD_PROP"
107    dump "Please point to a valid and complete Android build directory"
108    exit 1
109fi
110log "Extracting build properties from: $BUILD_PROP"
111
112# Try to get the architecture from build.prop if needed
113if [ -z "$ARCH" ]; then
114    CPU_ABI=$(awk -F '=' '$1 == "ro.product.cpu.abi"  { print $2; }' $BUILD_PROP)
115    if [ $? != 0 ]; then
116        dump "ERROR: Could not extract CPU ABI from $BUILD_PROP"
117        dump "Please use --arch=<name> to override this. See --help"
118        exit 1
119    fi
120    log "Found target CPU ABI: $CPU_ABI"
121    ARCH=$(convert_abi_to_arch $CPU_ABI)
122    if [ -z "$ARCH" ]; then
123        dump "ERROR: Can't translate $CPU_ABI ABI into CPU architecture!"
124        exit 1
125    fi
126    log "Auto-config: --arch=$ARCH"
127fi
128
129# Try to get the API level from build.prop if needed
130if [ -z "$PLATFORM" ]; then
131    PLATFORM=$(awk -F '=' '$1 == "ro.build.version.sdk" { print $2; }' $BUILD_PROP)
132    if [ $? != 0 ] ; then
133        dump "WARNING: Could not extract default platform level from $BUILD_PROP!"
134        dump "Please use --platform=<name> to override this. See --help"
135        exit 1
136    fi
137    if [ -z "$PLATFORM" ]; then
138        dump "ERROR: Couldn't extract API level from: $BUILD_PROP"
139        exit 1
140    fi
141    log "Auto-config: --platform=$PLATFORM"
142fi
143
144# Normalize platform name, i.e.
145#  3         -> 3
146#  android-3 -> 3
147#
148PLATFORM=${PLATFORM##android-}
149
150PLATFORM_ROOT=$OUT_DIR/android-$PLATFORM/arch-$ARCH
151log "Using platform destination path: $PLATFORM_ROOT"
152
153# Return the list of files under a given directory
154# $1: directory
155# $2: (optional) file patterns
156list_regular_files_in ()
157{
158    local DIR="$1"
159    shift
160    local PATTERNS="$@"
161    if [ -z "$PATTERNS" ]; then
162        PATTERNS="."
163    fi
164    cd "$DIR" && find $PATTERNS -type f | sed -e 's!^./!!g'
165}
166
167# Check that a given platform level was listed on the command line
168# $1: Platform numerical level (e.g. '3')
169# returns true if the platform is listed
170platform_check ()
171{
172    [ "$PLATFORM" -ge "$1" ]
173}
174
175# Determine Android build tree root
176ANDROID_ROOT=`cd $ANDROID_PRODUCT_OUT/../../../.. && pwd`
177log "Android build tree root: $ANDROID_ROOT"
178log "Android product out: $ANDROID_PRODUCT_OUT"
179
180if [ -z "$TOOLCHAIN_PREFIX" ]; then
181    TOOLCHAIN_NAME=$(get_default_toolchain_name_for_arch $ARCH)
182    TOOLCHAIN_PREFIX=$(get_default_toolchain_prefix_for_arch $ARCH)
183    TOOLCHAIN_PREFIX=$(get_toolchain_install $ANDROID_NDK_ROOT $TOOLCHAIN_NAME)/bin/$TOOLCHAIN_PREFIX
184    TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX%%-}
185    if [ -z "$TOOLCHAIN_PREFIX" ]; then
186        echo "ERROR: Unsupported architecture"
187        exit 1
188    fi
189    log "Auto-config: --toolchain-prefix=$TOOLCHAIN_PREFIX"
190fi
191
192if [ ! -d "$(dirname $TOOLCHAIN_PREFIX)" ]; then
193    echo "ERROR: Toolchain not installed, missing directory: $(dirname $TOOLCHAIN_PREFIX)"
194    exit 1
195fi
196
197if [ ! -f "$TOOLCHAIN_PREFIX-readelf" ]; then
198    echo "ERROR: Toolchain not installed, missing program: $TOOLCHAIN_PREFIX-readelf"
199    exit 1
200fi
201
202
203# 'Copy' a given system library. This really reads the shared library to
204# to generate a small shell version that will be installed at the destination
205# $1: Library name (e.g. libEGL.so)
206#
207copy_system_shared_library ()
208{
209    local src="$ANDROID_PRODUCT_OUT/system/lib/$1.so"
210    if [ ! -f "$src" ] ; then
211        dump "ERROR: Missing system library: $src"
212        exit 1
213    fi
214    local dst="$PLATFORM_ROOT/lib/$1.so"
215    mkdir -p `dirname "$dst"` && cp "$src" "$dst"
216}
217
218copy_system_static_library ()
219{
220    local src="$ANDROID_PRODUCT_OUT/obj/STATIC_LIBRARIES/$1_intermediates/$1.a"
221    if [ ! -f "$src" ] ; then
222        dump "ERROR: Missing system static library: $src"
223        exit 1
224    fi
225    local dst="$PLATFORM_ROOT/lib/$1.a"
226    log "Copying system static library: $1.a"
227    mkdir -p `dirname "$dst"` && cp -f "$src" "$dst"
228}
229
230copy_system_object_file ()
231{
232    local src="$ANDROID_PRODUCT_OUT/obj/lib/$1.o"
233    if [ ! -f "$src" ] ; then
234        dump "ERROR: Missing system object file: $src"
235        exit 1
236    fi
237    local dst="$PLATFORM_ROOT/lib/$1.o"
238    log "Copying system object file: $1.o"
239    mkdir -p `dirname "$dst"` &&
240    cp -f "$src" "$dst"
241}
242
243# Copy the content of a given directory to $SYSROOT/usr/include
244# $1: Source directory
245# $2+: List of headers
246copy_system_headers ()
247{
248    local srcdir="$1"
249    shift
250    local header
251    log "Copying system headers from: $srcdir"
252    for header; do
253        log "  $header"
254        local src="$srcdir/$header"
255        local dst="$PLATFORM_ROOT/../include/$header"
256        if [ ! -f "$srcdir/$header" ] ; then
257            dump "ERROR: Missing system header: $srcdir/$header"
258            exit 1
259        fi
260        mkdir -p `dirname "$dst"` && cp -f "$src" "$dst"
261        if [ $? != 0 ] ; then
262            dump "ERROR: Could not copy system header: $src"
263            dump "Target location: $dst"
264            exit 1
265        fi
266    done
267}
268
269# Copy all headers found under $1
270# $1: source directory
271copy_system_headers_from ()
272{
273    local headers=$(list_regular_files_in "$1")
274    copy_system_headers $1 $headers
275}
276
277# Same as copy_system_headers, but for arch-specific files
278# $1: Source directory
279# $2+: List of headers
280copy_arch_system_headers ()
281{
282    local srcdir="$1"
283    shift
284    local header
285    for header; do
286        log "Copying $arch system header: $header"
287        local src="$srcdir/$header"
288        local dst="$PLATFORM_ROOT/include/$header"
289        if [ ! -f "$srcdir/$header" ] ; then
290            dump "ERROR: Missing $ARCH system header: $srcdir/$header"
291            exit 1
292        fi
293        mkdir -p `dirname "$dst"` && cp -f "$src" "$dst"
294        if [ $? != 0 ] ; then
295            dump "ERROR: Could not copy $ARCH system header: $src"
296            dump "Target location: $dst"
297            exit 1
298        fi
299    done
300}
301
302copy_arch_system_headers_from ()
303{
304    local headers=$(list_regular_files_in "$1")
305    copy_arch_system_headers $1 $headers
306}
307
308copy_arch_kernel_headers_from ()
309{
310    local headers=$(list_regular_files_in "$1" asm)
311    copy_arch_system_headers $1 $headers
312}
313
314# Probe for the location of the OpenSLES sources in the
315# platform tree. This used to be system/media/opensles but
316# was moved to system/media/wilhelm in Android 4.0
317OPENSLES_SUBDIR=system/media/wilhelm
318if [ ! -d "$ANDROID_ROOT/$OPENSLES_SUBDIR" ]; then
319    OPENSLES_SUBDIR=system/media/opensles
320fi
321
322# Now do the work
323
324# API level 3
325if platform_check 3; then
326    copy_system_shared_library libc
327    copy_system_static_library libc
328    copy_system_headers_from $ANDROID_ROOT/bionic/libc/include
329    copy_arch_system_headers_from $ANDROID_ROOT/bionic/libc/arch-$ARCH/include
330    copy_arch_kernel_headers_from $ANDROID_ROOT/bionic/libc/kernel/arch-$ARCH
331
332    copy_system_object_file crtbegin_dynamic
333    copy_system_object_file crtbegin_static
334    copy_system_object_file crtend_android
335    case $ARCH in
336    x86)
337        copy_system_object_file crtbegin_so
338        copy_system_object_file crtend_so
339        ;;
340    esac
341
342    copy_system_shared_library libm
343    copy_system_static_library libm
344    copy_system_headers $ANDROID_ROOT/bionic/libm/include math.h
345    case "$ARCH" in
346    x86 )
347        copy_arch_system_headers $ANDROID_ROOT/bionic/libm/include/i387 fenv.h
348        ;;
349    * )
350        copy_arch_system_headers $ANDROID_ROOT/bionic/libm/$ARCH fenv.h
351        ;;
352    esac
353
354    # The <dlfcn.h> header was already copied from bionic/libc/include
355    copy_system_shared_library libdl
356    # There is no libdl.a at the moment, we might need one in
357    # the future to build gdb-7.1.x though.
358
359    copy_system_shared_library libz
360    copy_system_static_library libz
361    copy_system_headers $ANDROID_ROOT/external/zlib zconf.h zlib.h
362
363    copy_system_shared_library liblog
364    copy_system_headers $ANDROID_ROOT/system/core/include android/log.h
365
366    # NOTE: We do not copy the C++ headers, they are part of the NDK
367    #        under $NDK/source/cxx-stl. They were separated from the rest
368    #        of the platform headers in order to make room for other STL
369    #        implementations (e.g. STLport or GNU Libstdc++-v3)
370    #
371    copy_system_shared_library libstdc++
372    copy_system_static_library libstdc++
373
374    copy_system_headers $ANDROID_ROOT/libnativehelper/include/nativehelper jni.h
375fi
376
377# API level 4
378if platform_check 4; then
379    copy_system_shared_library libGLESv1_CM
380    copy_system_headers $ANDROID_ROOT/frameworks/base/opengl/include \
381        GLES/gl.h \
382        GLES/glext.h \
383        GLES/glplatform.h
384
385    copy_system_headers $ANDROID_ROOT/frameworks/base/opengl/include \
386        KHR/khrplatform.h
387fi
388
389# API level 5
390if platform_check 5; then
391    copy_system_shared_library libGLESv2
392    copy_system_headers $ANDROID_ROOT/frameworks/base/opengl/include \
393        GLES2/gl2.h \
394        GLES2/gl2ext.h \
395        GLES2/gl2platform.h
396fi
397
398# API level 8
399if platform_check 8; then
400    copy_system_shared_library libandroid
401    copy_system_shared_library libjnigraphics
402    copy_system_headers $ANDROID_ROOT/frameworks/base/native/include \
403        android/bitmap.h
404fi
405
406# API level 9
407if platform_check 9; then
408    case $ARCH in
409    arm)
410        copy_system_object_file crtbegin_so
411        copy_system_object_file crtend_so
412        ;;
413    esac
414
415    copy_system_shared_library libandroid
416    copy_system_headers $ANDROID_ROOT/frameworks/base/native/include \
417        android/asset_manager.h \
418        android/asset_manager_jni.h \
419        android/configuration.h \
420        android/input.h \
421        android/keycodes.h \
422        android/looper.h \
423        android/native_activity.h \
424        android/native_window.h \
425        android/native_window_jni.h \
426        android/obb.h \
427        android/rect.h \
428        android/sensor.h \
429        android/storage_manager.h \
430        android/window.h
431
432    copy_system_shared_library libEGL
433    copy_system_headers $ANDROID_ROOT/frameworks/base/opengl/include \
434        EGL/egl.h \
435        EGL/eglext.h \
436        EGL/eglplatform.h
437
438    copy_system_shared_library libOpenSLES
439    copy_system_headers $ANDROID_ROOT/$OPENSLES_SUBDIR/include \
440        SLES/OpenSLES.h \
441        SLES/OpenSLES_Android.h \
442        SLES/OpenSLES_AndroidConfiguration.h \
443        SLES/OpenSLES_Platform.h
444fi
445
446# API level 14
447if platform_check 14; then
448    copy_system_shared_library libOpenMAXAL
449    copy_system_headers $ANDROID_ROOT/system/media/wilhelm/include \
450	OMXAL/OpenMAXAL.h \
451        OMXAL/OpenMAXAL_Android.h \
452        OMXAL/OpenMAXAL_Platform.h
453
454    # This header is new in API level 14
455    copy_system_headers $ANDROID_ROOT/$OPENSLES_SUBDIR/include \
456        SLES/OpenSLES_AndroidMetadata.h
457fi
458
459# Now extract dynamic symbols from the copied shared libraries
460# Note that this script will also filter unwanted symbols
461log "Generating symbol files"
462$PROGDIR/gen-system-symbols.sh "$PLATFORM_ROOT/lib" "$PLATFORM_ROOT/symbols"
463
464# Remove copied shared libraries, we don't need them anymore
465# They will be replaced by auto-generated shells by gen-platforms.sh
466#
467log "Cleaning: $PLATFORM_ROOT/lib/lib*.so"
468rm -f "$PLATFORM_ROOT"/lib/lib*.so
469
470log "Done!"
471