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` 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