Home | History | Annotate | Download | only in build
      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 #  This shell script is a wrapper to launch the NDK build from the
     18 #  command-line inside an application project path.
     19 #
     20 #  Typical usage is:
     21 #
     22 #     cd $PROJECT_PATH
     23 #     ndk-build
     24 #
     25 #  Assuming that the Android NDK root path is in your PATH. However,
     26 #  you can also invoke it directly as:
     27 #
     28 #     $NDK_ROOT/ndk-build
     29 #
     30 #  This really is a tiny wrapper around GNU Make.
     31 #
     32 
     33 # Ensure we get the full path of this script's directory
     34 # this is needed if the caller uses the -C <path> GNU Make
     35 # option, as in:
     36 #
     37 #    cd ndk
     38 #    ./ndk-build -C <project-path>
     39 #
     40 PROGDIR=`dirname $0`
     41 PROGDIR=`cd $PROGDIR && pwd -P`
     42 
     43 # Check if absolute NDK path contain space
     44 #
     45 case $PROGDIR in
     46     *\ *) echo "ERROR: NDK path cannot contain space"
     47           exit 1
     48         ;;
     49 esac
     50 
     51 # If NDK_LOG is set to 1 or true in the environment, or the command-line
     52 # then enable log messages below
     53 if [ -z "$NDK_LOG" ]; then
     54   NDK_LOG=0
     55 fi
     56 
     57 if [ -z "$NDK_ANALYZE" ]; then
     58   NDK_ANALYZE=0
     59 fi
     60 
     61 PROJECT_PATH=
     62 PROJECT_PATH_NEXT=
     63 for opt; do
     64     if [ -z "$PROJECT_PATH" -a "$PROJECT_PATH_NEXT" = "yes" ] ; then
     65         PROJECT_PATH=$opt
     66         PROJECT_PATH_NEXT=
     67     else
     68         case $opt in
     69           NDK_LOG=1|NDK_LOG=true)
     70             NDK_LOG=1
     71             ;;
     72           NDK_LOG=*)
     73             NDK_LOG=0
     74             ;;
     75           NDK_ANALYZE=1|NDK_ANALYZE=true)
     76             NDK_ANALYZE=1
     77             ;;
     78           NDK_ANALYZE=*)
     79             NDK_ANALYZE=0
     80             ;;
     81           NDK_TOOLCHAIN_VERSION=*)
     82             NDK_TOOLCHAIN_VERSION=${opt#NDK_TOOLCHAIN_VERSION=}
     83             ;;
     84           APP_ABI=*)
     85             APP_ABI=${opt#APP_ABI=}
     86             ;;
     87           -C)
     88             PROJECT_PATH_NEXT="yes"
     89             ;;
     90         esac
     91     fi
     92 done
     93 
     94 if [ "$NDK_LOG" = "true" ]; then
     95   NDK_LOG=1
     96 fi
     97 
     98 if [ "$NDK_ANALYZE" = "true" ]; then
     99   NDK_ANALYZE=1
    100 fi
    101 
    102 if [ "$NDK_LOG" = "1" ]; then
    103   log () {
    104     echo "$@"
    105   }
    106 else
    107   log () {
    108     : # nothing
    109   }
    110 fi
    111 
    112 # Detect host operating system and architecture
    113 # The 64-bit / 32-bit distinction gets tricky on Linux and Darwin because
    114 # uname -m returns the kernel's bit size, and it's possible to run with
    115 # a 64-bit kernel and a 32-bit userland.
    116 #
    117 HOST_OS=$(uname -s)
    118 case $HOST_OS in
    119   Darwin) HOST_OS=darwin;;
    120   Linux) HOST_OS=linux;;
    121   FreeBsd) HOST_OS=freebsd;;
    122   CYGWIN*|*_NT-*) HOST_OS=cygwin;;
    123   *) echo "ERROR: Unknown host operating system: $HOST_OS"
    124      exit 1
    125 esac
    126 log "HOST_OS=$HOST_OS"
    127 
    128 HOST_ARCH=$(uname -m)
    129 case $HOST_ARCH in
    130     i?86) HOST_ARCH=x86;;
    131     x86_64|amd64) HOST_ARCH=x86_64;;
    132     *) echo "ERROR: Unknown host CPU architecture: $HOST_ARCH"
    133        exit 1
    134 esac
    135 log "HOST_ARCH=$HOST_ARCH"
    136 
    137 # Detect 32-bit userland on 64-bit kernels
    138 HOST_TAG="$HOST_OS-$HOST_ARCH"
    139 case $HOST_TAG in
    140   linux-x86_64|darwin-x86_64)
    141     # we look for x86_64 or x86-64 in the output of 'file' for our shell
    142     # the -L flag is used to dereference symlinks, just in case.
    143     file -L "$SHELL" | grep -q "x86[_-]64"
    144     if [ $? != 0 ]; then
    145       HOST_ARCH=x86
    146       log "HOST_ARCH=$HOST_ARCH (32-bit userland detected)"
    147     fi
    148     ;;
    149 esac
    150 
    151 # Check that we have 64-bit binaries on 64-bit system, otherwise fallback
    152 # on 32-bit ones. This gives us more freedom in packaging the NDK.
    153 LOG_MESSAGE=
    154 if [ $HOST_ARCH = x86_64 ]; then
    155   if [ ! -d $PROGDIR/prebuilt/$HOST_TAG ]; then
    156     HOST_ARCH=x86
    157     LOG_MESSAGE="(no 64-bit prebuilt binaries detected)"
    158   fi
    159 fi
    160 
    161 HOST_TAG=$HOST_OS-$HOST_ARCH
    162 # Special case windows-x86 -> windows
    163 if [ $HOST_TAG = windows-x86 ]; then
    164   HOST_TAG=windows
    165 fi
    166 log "HOST_TAG=$HOST_TAG $LOG_MESSAGE"
    167 
    168 # If GNUMAKE is defined, check that it points to a valid file
    169 if [ -n "$GNUMAKE" ] ; then
    170     ABS_GNUMAKE=`which $GNUMAKE 2> /dev/null`
    171     if [ $? != 0 ] ; then
    172         echo "ERROR: Your GNUMAKE variable is defined to an invalid name: $GNUMAKE"
    173         echo "Please fix it to point to a valid make executable (e.g. /usr/bin/make)"
    174         exit 1
    175     fi
    176     GNUMAKE="$ABS_GNUMAKE"
    177     log "GNUMAKE=$GNUMAKE (from environment variable)"
    178 else
    179     # Otherwise use the prebuilt version for our host tag, if it exists
    180     # Note: we intentionally do not provide prebuilt make binaries for Cygwin
    181     # or MSys.
    182     GNUMAKE=$PROGDIR/prebuilt/$HOST_TAG/bin/make
    183     if [ ! -f "$GNUMAKE" ]; then
    184         # Otherwise, use 'make' and check that it is available
    185         GNUMAKE=`which make 2> /dev/null`
    186         if [ $? != 0 ] ; then
    187             echo "ERROR: Cannot find 'make' program. Please install Cygwin make package"
    188             echo "or define the GNUMAKE variable to point to it."
    189             exit 1
    190         fi
    191         log "GNUMAKE=$GNUMAKE (system path)"
    192     else
    193         log "GNUMAKE=$GNUMAKE (NDK prebuilt)"
    194     fi
    195 fi
    196 
    197 # On Windows, when running under cygwin, check that we are
    198 # invoking a cygwin-compatible GNU Make binary. It is unfortunately
    199 # common for app developers to have another non cygwin-compatible
    200 # 'make' program in their PATH.
    201 #
    202 if [ "$OSTYPE" = "cygwin" ] ; then
    203     GNUMAKE=`cygpath -u $GNUMAKE`
    204     PROGDIR_MIXED=`cygpath -m $PROGDIR`
    205     CYGWIN_GNUMAKE=`$GNUMAKE -f "$PROGDIR_MIXED/core/check-cygwin-make.mk" 2>&1`
    206     if [ $? != 0 ] ; then
    207         echo "ERROR: You are using a non-Cygwin compatible Make program."
    208         echo "Currently using: `cygpath -m $GNUMAKE`"
    209         echo ""
    210         echo "To solve the issue, follow these steps:"
    211         echo ""
    212         echo "1. Ensure that the Cygwin 'make' package is installed."
    213         echo "   NOTE: You will need GNU Make 3.81 or later!"
    214         echo ""
    215         echo "2. Define the GNUMAKE environment variable to point to it, as in:"
    216         echo ""
    217         echo "     export GNUMAKE=/usr/bin/make"
    218         echo ""
    219         echo "3. Call 'ndk-build' again."
    220         echo ""
    221         exit 1
    222     fi
    223     log "Cygwin-compatible GNU make detected"
    224 fi
    225 
    226 if [ "$NDK_ANALYZE" = 1 ]; then
    227     . $PROGDIR/build/tools/dev-defaults.sh  # for DEFAULT_LLVM_VERSION
    228 
    229     # Return flags send in env. or command line which are enough to retrive APP_ABI and TOOLCHAIN_PREFIX later
    230     gen_flags ()
    231     {
    232         local FLAGS=
    233 
    234         if [ -n "$PROJECT_PATH" ] ; then
    235             FLAGS=$FLAGS" -C $PROJECT_PATH"
    236         fi
    237         if [ -n "$APP_ABI" ] ; then
    238             FLAGS=$FLAGS" APP_ABI=$APP_ABI"
    239         fi
    240         if [ -n "$NDK_TOOLCHAIN_VERSION" ] ; then
    241             FLAGS=$FLAGS" NDK_TOOLCHAIN_VERSION=$NDK_TOOLCHAIN_VERSION"
    242         fi
    243         echo "$FLAGS"
    244     }
    245 
    246     get_build_var ()
    247     {
    248         local VAR=$1
    249         local FLAGS=`gen_flags`
    250         $GNUMAKE --no-print-dir -f $PROGDIR/core/build-local.mk $FLAGS DUMP_${VAR} | tail -1
    251     }
    252 
    253     get_build_var_for_abi ()
    254     {
    255         local VAR=$1
    256         local ABI=$2
    257         local FLAGS=`gen_flags`
    258         $GNUMAKE --no-print-dir -f $PROGDIR/core/build-local.mk $FLAGS DUMP_${VAR} APP_ABI=${ABI} | tail -1
    259     }
    260 
    261     APP_ABIS=`get_build_var APP_ABI`
    262     for ABI in $APP_ABIS; do
    263         TOOLCHAIN_PREFIX=`get_build_var_for_abi TOOLCHAIN_PREFIX $ABI`
    264         LLVM_PATH=$PROGDIR/toolchains/llvm-${DEFAULT_LLVM_VERSION}/prebuilt
    265         perl $LLVM_PATH/tools/scan-build/scan-build \
    266             --use-analyzer $LLVM_PATH/bin/${ABI}/analyzer \
    267             --use-cc ${TOOLCHAIN_PREFIX}gcc \
    268             --use-c++ ${TOOLCHAIN_PREFIX}g++ \
    269             --status-bugs \
    270             $GNUMAKE -f $PROGDIR/core/build-local.mk "$@" APP_ABI=$ABI
    271     done
    272 else
    273     $GNUMAKE -f $PROGDIR/core/build-local.mk "$@"
    274 fi
    275 
    276