| #!/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. |
| # |
| # This shell script is a wrapper to launch the NDK build from the |
| # command-line inside an application project path. |
| # |
| # Typical usage is: |
| # |
| # cd $PROJECT_PATH |
| # ndk-build |
| # |
| # Assuming that the Android NDK root path is in your PATH. However, |
| # you can also invoke it directly as: |
| # |
| # $NDK_ROOT/ndk-build |
| # |
| # This really is a tiny wrapper around GNU Make. |
| # |
| |
| # Ensure we get the full path of this script's directory |
| # this is needed if the caller uses the -C <path> GNU Make |
| # option, as in: |
| # |
| # cd ndk |
| # ./ndk-build -C <project-path> |
| # |
| PROGDIR=`dirname $0` |
| PROGDIR=`cd $PROGDIR && pwd` |
| |
| # Check if absolute NDK path contain space |
| # |
| case $PROGDIR in |
| *\ *) echo "ERROR: NDK path cannot contain space" |
| exit 1 |
| ;; |
| esac |
| |
| # If NDK_LOG is set to 1 or true in the environment, or the command-line |
| # then enable log messages below |
| # Also normalize NDK_HOST_32BIT and NDK_ANALYZE to 1 or 0 |
| if [ -z "$NDK_LOG" ]; then |
| NDK_LOG=0 |
| fi |
| |
| if [ -z "$NDK_HOST_32BIT" ]; then |
| NDK_HOST_32BIT=0 |
| fi |
| |
| if [ -z "$NDK_ANALYZE" ]; then |
| NDK_ANALYZE=0 |
| fi |
| |
| PROJECT_PATH= |
| PROJECT_PATH_NEXT= |
| for opt; do |
| if [ -z "$PROJECT_PATH" -a "$PROJECT_PATH_NEXT" = "yes" ] ; then |
| PROJECT_PATH=$opt |
| PROJECT_PATH_NEXT= |
| else |
| case $opt in |
| NDK_LOG=1|NDK_LOG=true) |
| NDK_LOG=1 |
| ;; |
| NDK_LOG=*) |
| NDK_LOG=0 |
| ;; |
| NDK_HOST_32BIT=1|NDK_HOST_32BIT=true) |
| NDK_HOST_32BIT=1 |
| ;; |
| NDK_HOST_32BIT=*) |
| NDK_HOST_32BIT=0 |
| ;; |
| NDK_ANALYZE=1|NDK_ANALYZE=true) |
| NDK_ANALYZE=1 |
| ;; |
| NDK_ANALYZE=*) |
| NDK_ANALYZE=0 |
| ;; |
| NDK_TOOLCHAIN_VERSION=*) |
| NDK_TOOLCHAIN_VERSION=${opt#NDK_TOOLCHAIN_VERSION=} |
| ;; |
| APP_ABI=*) |
| APP_ABI=${opt#APP_ABI=} |
| ;; |
| -C) |
| PROJECT_PATH_NEXT="yes" |
| ;; |
| esac |
| fi |
| done |
| |
| if [ "$NDK_LOG" = "true" ]; then |
| NDK_LOG=1 |
| fi |
| |
| if [ "$NDK_HOST_32BIT" = "true" ]; then |
| NDK_HOST_32BIT=1 |
| fi |
| |
| if [ "$NDK_ANALYZE" = "true" ]; then |
| NDK_ANALYZE=1 |
| fi |
| |
| if [ "$NDK_LOG" = "1" ]; then |
| log () { |
| echo "$@" |
| } |
| else |
| log () { |
| : # nothing |
| } |
| fi |
| |
| # Detect host operating system and architecture |
| # The 64-bit / 32-bit distinction gets tricky on Linux and Darwin because |
| # uname -m returns the kernel's bit size, and it's possible to run with |
| # a 64-bit kernel and a 32-bit userland. |
| # |
| HOST_OS=$(uname -s) |
| case $HOST_OS in |
| Darwin) HOST_OS=darwin;; |
| Linux) HOST_OS=linux;; |
| FreeBsd) HOST_OS=freebsd;; |
| CYGWIN*|*_NT-*) HOST_OS=cygwin;; |
| *) echo "ERROR: Unknown host operating system: $HOST_OS" |
| exit 1 |
| esac |
| log "HOST_OS=$HOST_OS" |
| |
| HOST_ARCH=$(uname -m) |
| case $HOST_ARCH in |
| i?86) HOST_ARCH=x86;; |
| x86_64|amd64) HOST_ARCH=x86_64;; |
| *) echo "ERROR: Unknown host CPU architecture: $HOST_ARCH" |
| exit 1 |
| esac |
| log "HOST_ARCH=$HOST_ARCH" |
| |
| # Detect 32-bit userland on 64-bit kernels |
| HOST_TAG="$HOST_OS-$HOST_ARCH" |
| case $HOST_TAG in |
| linux-x86_64|darwin-x86_64) |
| # we look for x86_64 or x86-64 in the output of 'file' for our shell |
| # the -L flag is used to dereference symlinks, just in case. |
| file -L "$SHELL" | grep -q "x86[_-]64" |
| if [ $? != 0 ]; then |
| HOST_ARCH=x86 |
| log "HOST_ARCH=$HOST_ARCH (32-bit userland detected)" |
| fi |
| ;; |
| esac |
| |
| # Check that we have 64-bit binaries on 64-bit system, otherwise fallback |
| # on 32-bit ones. This gives us more freedom in packaging the NDK. |
| LOG_MESSAGE= |
| if [ $HOST_ARCH = x86_64 ]; then |
| if [ ! -d $PROGDIR/prebuilt/$HOST_TAG ]; then |
| HOST_ARCH=x86 |
| LOG_MESSAGE="(no 64-bit prebuilt binaries detected)" |
| fi |
| |
| if [ "$NDK_HOST_32BIT" = "1" ]; then |
| HOST_ARCH=x86 |
| LOG_MESSAGE="(force 32-bit host toolchain)" |
| fi |
| fi |
| |
| HOST_TAG=$HOST_OS-$HOST_ARCH |
| # Special case windows-x86 -> windows |
| if [ $HOST_TAG = windows-x86 ]; then |
| HOST_TAG=windows |
| fi |
| log "HOST_TAG=$HOST_TAG $LOG_MESSAGE" |
| |
| # If GNUMAKE is defined, check that it points to a valid file |
| if [ -n "$GNUMAKE" ] ; then |
| ABS_GNUMAKE=`which $GNUMAKE 2> /dev/null` |
| if [ $? != 0 ] ; then |
| echo "ERROR: Your GNUMAKE variable is defined to an invalid name: $GNUMAKE" |
| echo "Please fix it to point to a valid make executable (e.g. /usr/bin/make)" |
| exit 1 |
| fi |
| GNUMAKE="$ABS_GNUMAKE" |
| log "GNUMAKE=$GNUMAKE (from environment variable)" |
| else |
| # Otherwise use the prebuilt version for our host tag, if it exists |
| # Note: we intentionally do not provide prebuilt make binaries for Cygwin |
| # or MSys. |
| GNUMAKE=$PROGDIR/prebuilt/$HOST_TAG/bin/make |
| if [ ! -f "$GNUMAKE" ]; then |
| # Otherwise, use 'make' and check that it is available |
| GNUMAKE=`which make 2> /dev/null` |
| if [ $? != 0 ] ; then |
| echo "ERROR: Cannot find 'make' program. Please install Cygwin make package" |
| echo "or define the GNUMAKE variable to point to it." |
| exit 1 |
| fi |
| log "GNUMAKE=$GNUMAKE (system path)" |
| else |
| log "GNUMAKE=$GNUMAKE (NDK prebuilt)" |
| fi |
| fi |
| |
| # On Windows, when running under cygwin, check that we are |
| # invoking a cygwin-compatible GNU Make binary. It is unfortunately |
| # common for app developers to have another non cygwin-compatible |
| # 'make' program in their PATH. |
| # |
| if [ "$OSTYPE" = "cygwin" ] ; then |
| GNUMAKE=`cygpath -u $GNUMAKE` |
| PROGDIR_MIXED=`cygpath -m $PROGDIR` |
| CYGWIN_GNUMAKE=`$GNUMAKE -f "$PROGDIR_MIXED/build/core/check-cygwin-make.mk" 2>&1` |
| if [ $? != 0 ] ; then |
| echo "ERROR: You are using a non-Cygwin compatible Make program." |
| echo "Currently using: `cygpath -m $GNUMAKE`" |
| echo "" |
| echo "To solve the issue, follow these steps:" |
| echo "" |
| echo "1. Ensure that the Cygwin 'make' package is installed." |
| echo " NOTE: You will need GNU Make 3.81 or later!" |
| echo "" |
| echo "2. Define the GNUMAKE environment variable to point to it, as in:" |
| echo "" |
| echo " export GNUMAKE=/usr/bin/make" |
| echo "" |
| echo "3. Call 'ndk-build' again." |
| echo "" |
| exit 1 |
| fi |
| log "Cygwin-compatible GNU make detected" |
| fi |
| |
| if [ "$NDK_ANALYZE" = 1 ]; then |
| . $PROGDIR/build/tools/dev-defaults.sh # for DEFAULT_LLVM_VERSION |
| |
| # Find perl. If HOST_PERL is defined, check that it points to a valid file |
| HOST_PERL_LIB= |
| if [ -n "$HOST_PERL" ] ; then |
| ABS_PERL=`which $HOST_PERL 2> /dev/null` |
| if [ $? != 0 ] ; then |
| echo "ERROR: Your HOST_PERL variable is defined to an invalid name: $HOST_PERL" |
| echo "Please fix it to point to a valid perl executable (e.g. /usr/bin/perl)" |
| exit 1 |
| fi |
| HOST_PERL="$ABS_PERL" |
| log "HOST_PERL=$HOST_PERL (from environment variable)" |
| else |
| # Otherwise use the prebuilt version for our host tag |
| HOST_PERL="$PROGDIR/prebuilt/$HOST_TAG/bin/perl" |
| if [ ! -f "$HOST_PERL" ]; then |
| # Otherwise, use 'perl' and check that it is available |
| HOST_PERL=`which perl 2> /dev/null` |
| if [ $? != 0 ] ; then |
| echo "ERROR: Cannot find 'perl' program. Please install perl package" |
| echo "or define the HOST_PERL variable to point to it." |
| exit 1 |
| fi |
| log "HOST_PERL=$HOST_PERL (system path)" |
| else |
| HOST_PERL_LIB="$PROGDIR/prebuilt/$HOST_TAG/lib/perl5" |
| log "HOST_PERL=$HOST_PERL (NDK prebuilt)" |
| fi |
| fi |
| |
| # Return flags send in env. or command line which are enough to retrive APP_ABI and TOOLCHAIN_PREFIX later |
| gen_flags () |
| { |
| local FLAGS= |
| |
| if [ -n "$PROJECT_PATH" ] ; then |
| FLAGS=$FLAGS" -C $PROJECT_PATH" |
| fi |
| if [ -n "$APP_ABI" ] ; then |
| FLAGS=$FLAGS" APP_ABI=$APP_ABI" |
| fi |
| if [ -n "$NDK_HOST_32BIT" ] ; then |
| FLAGS=$FLAGS" NDK_HOST_32BIT=$NDK_HOST_32BIT" |
| fi |
| if [ -n "$NDK_TOOLCHAIN_VERSION" ] ; then |
| FLAGS=$FLAGS" NDK_TOOLCHAIN_VERSION=$NDK_TOOLCHAIN_VERSION" |
| fi |
| echo "$FLAGS" |
| } |
| |
| get_build_var () |
| { |
| local VAR=$1 |
| local FLAGS=`gen_flags` |
| $GNUMAKE --no-print-dir -f $PROGDIR/build/core/build-local.mk $FLAGS DUMP_${VAR} | tail -1 |
| } |
| |
| get_build_var_for_abi () |
| { |
| local VAR=$1 |
| local ABI=$2 |
| local FLAGS=`gen_flags` |
| $GNUMAKE --no-print-dir -f $PROGDIR/build/core/build-local.mk $FLAGS DUMP_${VAR} APP_ABI=${ABI} | tail -1 |
| } |
| |
| APP_ABIS=`get_build_var APP_ABI` |
| for ABI in $APP_ABIS; do |
| TOOLCHAIN_PREFIX=`get_build_var_for_abi TOOLCHAIN_PREFIX $ABI` |
| PERL5LIB="$HOST_PERL_LIB" "$HOST_PERL" $PROGDIR/prebuilt/common/scan-build/scan-build \ |
| --use-analyzer $PROGDIR/toolchains/llvm-${DEFAULT_LLVM_VERSION}/prebuilt/$HOST_TAG/bin/${ABI}/analyzer \ |
| --use-cc ${TOOLCHAIN_PREFIX}gcc \ |
| --use-c++ ${TOOLCHAIN_PREFIX}g++ \ |
| --status-bugs \ |
| $GNUMAKE -f $PROGDIR/build/core/build-local.mk "$@" APP_ABI=$ABI |
| done |
| else |
| $GNUMAKE -f $PROGDIR/build/core/build-local.mk "$@" |
| fi |
| |