Home | History | Annotate | Download | only in ndk
      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 # Also normalize NDK_HOST_32BIT and NDK_ANALYZE to 1 or 0
     54 if [ -z "$NDK_LOG" ]; then
     55   NDK_LOG=0
     56 fi
     57 
     58 if [ -z "$NDK_HOST_32BIT" ]; then
     59   NDK_HOST_32BIT=0
     60 fi
     61 
     62 if [ -z "$NDK_ANALYZE" ]; then
     63   NDK_ANALYZE=0
     64 fi
     65 
     66 PROJECT_PATH=
     67 PROJECT_PATH_NEXT=
     68 for opt; do
     69     if [ -z "$PROJECT_PATH" -a "$PROJECT_PATH_NEXT" = "yes" ] ; then
     70         PROJECT_PATH=$opt
     71         PROJECT_PATH_NEXT=
     72     else
     73         case $opt in
     74           NDK_LOG=1|NDK_LOG=true)
     75             NDK_LOG=1
     76             ;;
     77           NDK_LOG=*)
     78             NDK_LOG=0
     79             ;;
     80           NDK_HOST_32BIT=1|NDK_HOST_32BIT=true)
     81             NDK_HOST_32BIT=1
     82             ;;
     83           NDK_HOST_32BIT=*)
     84             NDK_HOST_32BIT=0
     85             ;;
     86           NDK_ANALYZE=1|NDK_ANALYZE=true)
     87             NDK_ANALYZE=1
     88             ;;
     89           NDK_ANALYZE=*)
     90             NDK_ANALYZE=0
     91             ;;
     92           NDK_TOOLCHAIN_VERSION=*)
     93             NDK_TOOLCHAIN_VERSION=${opt#NDK_TOOLCHAIN_VERSION=}
     94             ;;
     95           APP_ABI=*)
     96             APP_ABI=${opt#APP_ABI=}
     97             ;;
     98           -C)
     99             PROJECT_PATH_NEXT="yes"
    100             ;;
    101         esac
    102     fi
    103 done
    104 
    105 if [ "$NDK_LOG" = "true" ]; then
    106   NDK_LOG=1
    107 fi
    108 
    109 if [ "$NDK_HOST_32BIT" = "true" ]; then
    110   NDK_HOST_32BIT=1
    111 fi
    112 
    113 if [ "$NDK_ANALYZE" = "true" ]; then
    114   NDK_ANALYZE=1
    115 fi
    116 
    117 if [ "$NDK_LOG" = "1" ]; then
    118   log () {
    119     echo "$@"
    120   }
    121 else
    122   log () {
    123     : # nothing
    124   }
    125 fi
    126 
    127 # Detect host operating system and architecture
    128 # The 64-bit / 32-bit distinction gets tricky on Linux and Darwin because
    129 # uname -m returns the kernel's bit size, and it's possible to run with
    130 # a 64-bit kernel and a 32-bit userland.
    131 #
    132 HOST_OS=$(uname -s)
    133 case $HOST_OS in
    134   Darwin) HOST_OS=darwin;;
    135   Linux) HOST_OS=linux;;
    136   FreeBsd) HOST_OS=freebsd;;
    137   CYGWIN*|*_NT-*) HOST_OS=cygwin;;
    138   *) echo "ERROR: Unknown host operating system: $HOST_OS"
    139      exit 1
    140 esac
    141 log "HOST_OS=$HOST_OS"
    142 
    143 HOST_ARCH=$(uname -m)
    144 case $HOST_ARCH in
    145     i?86) HOST_ARCH=x86;;
    146     x86_64|amd64) HOST_ARCH=x86_64;;
    147     *) echo "ERROR: Unknown host CPU architecture: $HOST_ARCH"
    148        exit 1
    149 esac
    150 log "HOST_ARCH=$HOST_ARCH"
    151 
    152 # Detect 32-bit userland on 64-bit kernels
    153 HOST_TAG="$HOST_OS-$HOST_ARCH"
    154 case $HOST_TAG in
    155   linux-x86_64|darwin-x86_64)
    156     # we look for x86_64 or x86-64 in the output of 'file' for our shell
    157     # the -L flag is used to dereference symlinks, just in case.
    158     file -L "$SHELL" | grep -q "x86[_-]64"
    159     if [ $? != 0 ]; then
    160       HOST_ARCH=x86
    161       log "HOST_ARCH=$HOST_ARCH (32-bit userland detected)"
    162     fi
    163     ;;
    164 esac
    165 
    166 # Check that we have 64-bit binaries on 64-bit system, otherwise fallback
    167 # on 32-bit ones. This gives us more freedom in packaging the NDK.
    168 LOG_MESSAGE=
    169 if [ $HOST_ARCH = x86_64 ]; then
    170   if [ ! -d $PROGDIR/prebuilt/$HOST_TAG ]; then
    171     HOST_ARCH=x86
    172     LOG_MESSAGE="(no 64-bit prebuilt binaries detected)"
    173   fi
    174 
    175   if [ "$NDK_HOST_32BIT" = "1" ]; then
    176     HOST_ARCH=x86
    177     LOG_MESSAGE="(force 32-bit host toolchain)"
    178   fi
    179 fi
    180 
    181 HOST_TAG=$HOST_OS-$HOST_ARCH
    182 # Special case windows-x86 -> windows
    183 if [ $HOST_TAG = windows-x86 ]; then
    184   HOST_TAG=windows
    185 fi
    186 log "HOST_TAG=$HOST_TAG $LOG_MESSAGE"
    187 
    188 # If GNUMAKE is defined, check that it points to a valid file
    189 if [ -n "$GNUMAKE" ] ; then
    190     ABS_GNUMAKE=`which $GNUMAKE 2> /dev/null`
    191     if [ $? != 0 ] ; then
    192         echo "ERROR: Your GNUMAKE variable is defined to an invalid name: $GNUMAKE"
    193         echo "Please fix it to point to a valid make executable (e.g. /usr/bin/make)"
    194         exit 1
    195     fi
    196     GNUMAKE="$ABS_GNUMAKE"
    197     log "GNUMAKE=$GNUMAKE (from environment variable)"
    198 else
    199     # Otherwise use the prebuilt version for our host tag, if it exists
    200     # Note: we intentionally do not provide prebuilt make binaries for Cygwin
    201     # or MSys.
    202     GNUMAKE=$PROGDIR/prebuilt/$HOST_TAG/bin/make
    203     if [ ! -f "$GNUMAKE" ]; then
    204         # Otherwise, use 'make' and check that it is available
    205         GNUMAKE=`which make 2> /dev/null`
    206         if [ $? != 0 ] ; then
    207             echo "ERROR: Cannot find 'make' program. Please install Cygwin make package"
    208             echo "or define the GNUMAKE variable to point to it."
    209             exit 1
    210         fi
    211         log "GNUMAKE=$GNUMAKE (system path)"
    212     else
    213         log "GNUMAKE=$GNUMAKE (NDK prebuilt)"
    214     fi
    215 fi
    216 
    217 # On Windows, when running under cygwin, check that we are
    218 # invoking a cygwin-compatible GNU Make binary. It is unfortunately
    219 # common for app developers to have another non cygwin-compatible
    220 # 'make' program in their PATH.
    221 #
    222 if [ "$OSTYPE" = "cygwin" ] ; then
    223     GNUMAKE=`cygpath -u $GNUMAKE`
    224     PROGDIR_MIXED=`cygpath -m $PROGDIR`
    225     CYGWIN_GNUMAKE=`$GNUMAKE -f "$PROGDIR_MIXED/build/core/check-cygwin-make.mk" 2>&1`
    226     if [ $? != 0 ] ; then
    227         echo "ERROR: You are using a non-Cygwin compatible Make program."
    228         echo "Currently using: `cygpath -m $GNUMAKE`"
    229         echo ""
    230         echo "To solve the issue, follow these steps:"
    231         echo ""
    232         echo "1. Ensure that the Cygwin 'make' package is installed."
    233         echo "   NOTE: You will need GNU Make 3.81 or later!"
    234         echo ""
    235         echo "2. Define the GNUMAKE environment variable to point to it, as in:"
    236         echo ""
    237         echo "     export GNUMAKE=/usr/bin/make"
    238         echo ""
    239         echo "3. Call 'ndk-build' again."
    240         echo ""
    241         exit 1
    242     fi
    243     log "Cygwin-compatible GNU make detected"
    244 fi
    245 
    246 if [ "$NDK_ANALYZE" = 1 ]; then
    247     . $PROGDIR/build/tools/dev-defaults.sh  # for DEFAULT_LLVM_VERSION
    248 
    249     # Find perl.  If HOST_PERL is defined, check that it points to a valid file
    250     HOST_PERL_LIB=
    251     if [ -n "$HOST_PERL" ] ; then
    252         ABS_PERL=`which $HOST_PERL 2> /dev/null`
    253         if [ $? != 0 ] ; then
    254             echo "ERROR: Your HOST_PERL variable is defined to an invalid name: $HOST_PERL"
    255             echo "Please fix it to point to a valid perl executable (e.g. /usr/bin/perl)"
    256             exit 1
    257         fi
    258         HOST_PERL="$ABS_PERL"
    259         log "HOST_PERL=$HOST_PERL (from environment variable)"
    260     else
    261         # Otherwise use the prebuilt version for our host tag
    262         HOST_PERL="$PROGDIR/prebuilt/$HOST_TAG/bin/perl"
    263         if [ ! -f "$HOST_PERL" ]; then
    264             # Otherwise, use 'perl' and check that it is available
    265             HOST_PERL=`which perl 2> /dev/null`
    266             if [ $? != 0 ] ; then
    267                 echo "ERROR: Cannot find 'perl' program. Please install perl package"
    268                 echo "or define the HOST_PERL variable to point to it."
    269                 exit 1
    270             fi
    271             log "HOST_PERL=$HOST_PERL (system path)"
    272         else
    273             HOST_PERL_LIB="$PROGDIR/prebuilt/$HOST_TAG/lib/perl5"
    274             log "HOST_PERL=$HOST_PERL (NDK prebuilt)"
    275         fi
    276     fi
    277 
    278     # Return flags send in env. or command line which are enough to retrive APP_ABI and TOOLCHAIN_PREFIX later
    279     gen_flags ()
    280     {
    281         local FLAGS=
    282 
    283         if [ -n "$PROJECT_PATH" ] ; then
    284             FLAGS=$FLAGS" -C $PROJECT_PATH"
    285         fi
    286         if [ -n "$APP_ABI" ] ; then
    287             FLAGS=$FLAGS" APP_ABI=$APP_ABI"
    288         fi
    289         if [ -n "$NDK_HOST_32BIT" ] ; then
    290             FLAGS=$FLAGS" NDK_HOST_32BIT=$NDK_HOST_32BIT"
    291         fi
    292         if [ -n "$NDK_TOOLCHAIN_VERSION" ] ; then
    293             FLAGS=$FLAGS" NDK_TOOLCHAIN_VERSION=$NDK_TOOLCHAIN_VERSION"
    294         fi
    295         echo "$FLAGS"
    296     }
    297 
    298     get_build_var ()
    299     {
    300         local VAR=$1
    301         local FLAGS=`gen_flags`
    302         $GNUMAKE --no-print-dir -f $PROGDIR/build/core/build-local.mk $FLAGS DUMP_${VAR} | tail -1
    303     }
    304 
    305     get_build_var_for_abi ()
    306     {
    307         local VAR=$1
    308         local ABI=$2
    309         local FLAGS=`gen_flags`
    310         $GNUMAKE --no-print-dir -f $PROGDIR/build/core/build-local.mk $FLAGS DUMP_${VAR} APP_ABI=${ABI} | tail -1
    311     }
    312 
    313     APP_ABIS=`get_build_var APP_ABI`
    314     for ABI in $APP_ABIS; do
    315         TOOLCHAIN_PREFIX=`get_build_var_for_abi TOOLCHAIN_PREFIX $ABI`
    316         PERL5LIB="$HOST_PERL_LIB" "$HOST_PERL" $PROGDIR/prebuilt/common/scan-build/scan-build \
    317             --use-analyzer $PROGDIR/toolchains/llvm-${DEFAULT_LLVM_VERSION}/prebuilt/$HOST_TAG/bin/${ABI}/analyzer \
    318             --use-cc ${TOOLCHAIN_PREFIX}gcc \
    319             --use-c++ ${TOOLCHAIN_PREFIX}g++ \
    320             --status-bugs \
    321             $GNUMAKE -f $PROGDIR/build/core/build-local.mk "$@" APP_ABI=$ABI
    322     done
    323 else
    324     $GNUMAKE -f $PROGDIR/build/core/build-local.mk "$@"
    325 fi
    326 
    327