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