1# Copyright (C) 2009 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# 15 16# A collection of shell function definitions used by various build scripts 17# in the Android NDK (Native Development Kit) 18# 19 20# Get current script name into PROGNAME 21PROGNAME=`basename $0` 22 23# Put location of Android NDK into ANDROID_NDK_ROOT and 24# perform a tiny amount of sanity check 25# 26if [ -z "$ANDROID_NDK_ROOT" ] ; then 27 # Try to auto-detect the NDK root by walking up the directory 28 # path to the current script. 29 PROGDIR=`dirname $0` 30 while [ -n "1" ] ; do 31 if [ -d $PROGDIR/build/core ] ; then 32 break 33 fi 34 if [ -z $PROGDIR -o $PROGDIR = '.' ] ; then 35 echo "Please define ANDROID_NDK_ROOT to point to the root of your" 36 echo "Android NDK installation." 37 exit 1 38 fi 39 PROGDIR=`dirname $PROGDIR` 40 done 41 ANDROID_NDK_ROOT=`cd $PROGDIR && pwd` 42fi 43 44if [ ! -d $ANDROID_NDK_ROOT ] ; then 45 echo "ERROR: Your ANDROID_NDK_ROOT variable does not point to a directory." 46 exit 1 47fi 48 49if [ ! -f $ANDROID_NDK_ROOT/build/core/ndk-common.sh ] ; then 50 echo "ERROR: Your ANDROID_NDK_ROOT variable does not point to a valid directory." 51 exit 1 52fi 53 54## Logging support 55## 56VERBOSE=${VERBOSE-yes} 57VERBOSE2=${VERBOSE2-no} 58 59log () 60{ 61 if [ "$VERBOSE" = "yes" ] ; then 62 echo "$1" 63 fi 64} 65 66log2 () 67{ 68 if [ "$VERBOSE2" = "yes" ] ; then 69 echo "$1" 70 fi 71} 72 73## Utilities 74## 75 76# return the value of a given named variable 77# $1: variable name 78# 79# example: 80# FOO=BAR 81# BAR=ZOO 82# echo `var_value $FOO` 83# will print 'ZOO' 84# 85var_value () 86{ 87 # find a better way to do that ? 88 eval echo "$`echo $1`" 89} 90 91# convert to uppercase 92# assumes tr is installed on the platform ? 93# 94to_uppercase () 95{ 96 echo $1 | tr "[:lower:]" "[:upper:]" 97} 98 99## Normalize OS and CPU 100## 101HOST_ARCH=`uname -m` 102case "$HOST_ARCH" in 103 i?86) HOST_ARCH=x86 104 ;; 105 amd64) HOST_ARCH=x86_64 106 ;; 107 powerpc) HOST_ARCH=ppc 108 ;; 109esac 110 111log2 "HOST_ARCH=$HOST_ARCH" 112 113# at this point, the supported values for CPU are: 114# x86 115# x86_64 116# ppc 117# 118# other values may be possible but haven't been tested 119# 120HOST_EXE="" 121HOST_OS=`uname -s` 122case "$HOST_OS" in 123 Darwin) 124 HOST_OS=darwin 125 ;; 126 Linux) 127 # note that building 32-bit binaries on x86_64 is handled later 128 HOST_OS=linux 129 ;; 130 FreeBsd) # note: this is not tested 131 HOST_OS=freebsd 132 ;; 133 CYGWIN*|*_NT-*) 134 HOST_OS=windows 135 HOST_EXE=.exe 136 if [ "x$OSTYPE" = xcygwin ] ; then 137 HOST_OS=cygwin 138 HOST_CFLAGS="$CFLAGS -mno-cygwin" 139 HOST_LDFLAGS="$LDFLAGS -mno-cygwin" 140 fi 141 ;; 142esac 143 144log2 "HOST_OS=$HOST_OS" 145log2 "HOST_EXE=$HOST_EXE" 146 147# at this point, the value of HOST_OS should be one of the following: 148# linux 149# darwin 150# windows (MSys) 151# cygwin 152# 153# Note that cygwin is treated as a special case because it behaves very differently 154# for a few things. Other values may be possible but have not been tested 155# 156 157# define HOST_TAG as a unique tag used to identify both the host OS and CPU 158# supported values are: 159# 160# linux-x86 161# linux-x86_64 162# darwin-x86 163# darwin-ppc 164# windows 165# 166# other values are possible but were not tested. 167# 168compute_host_tag () 169{ 170 case "$HOST_OS" in 171 windows|cygwin) 172 HOST_TAG="windows" 173 ;; 174 *) HOST_TAG="${HOST_OS}-${HOST_ARCH}" 175 esac 176 log2 "HOST_TAG=$HOST_TAG" 177} 178 179compute_host_tag 180 181# Compute the number of host CPU cores an HOST_NUM_CPUS 182# 183case "$HOST_OS" in 184 linux) 185 HOST_NUM_CPUS=`cat /proc/cpuinfo | grep processor | wc -l` 186 ;; 187 darwin|freebsd) 188 HOST_NUM_CPUS=`sysctl -n hw.ncpu` 189 ;; 190 windows|cygwin) 191 HOST_NUM_CPUS=$NUMBER_OF_PROCESSORS 192 ;; 193 *) # let's play safe here 194 HOST_NUM_CPUS=1 195esac 196 197log2 "HOST_NUM_CPUS=$HOST_NUM_CPUS" 198 199# If BUILD_NUM_CPUS is not already defined in your environment, 200# define it as the double of HOST_NUM_CPUS. This is used to 201# run Make commends in parralles, as in 'make -j$BUILD_NUM_CPUS' 202# 203if [ -z "$BUILD_NUM_CPUS" ] ; then 204 BUILD_NUM_CPUS=`expr $HOST_NUM_CPUS \* 2` 205fi 206 207log2 "BUILD_NUM_CPUS=$BUILD_NUM_CPUS" 208 209 210## HOST TOOLCHAIN SUPPORT 211## 212 213# force the generation of 32-bit binaries on 64-bit systems 214# 215FORCE_32BIT=no 216force_32bit_binaries () 217{ 218 if [ "$HOST_ARCH" = x86_64 ] ; then 219 log2 "Forcing generation of 32-bit host binaries on $HOST_ARCH" 220 FORCE_32BIT=yes 221 HOST_ARCH=x86 222 log2 "HOST_ARCH=$HOST_ARCH" 223 compute_host_tag 224 fi 225} 226 227# On Windows, cygwin binaries will be generated by default, but 228# you can force mingw ones that do not link to cygwin.dll if you 229# call this function. 230# 231disable_cygwin () 232{ 233 if [ $OS = cygwin ] ; then 234 log2 "Disabling cygwin binaries generation" 235 CFLAGS="$CFLAGS -mno-cygwin" 236 LDFLAGS="$LDFLAGS -mno-cygwin" 237 OS=windows 238 HOST_OS=windows 239 compute_host_tag 240 fi 241} 242 243# Various probes are going to need to run a small C program 244TMPC=/tmp/android-$$-test.c 245TMPO=/tmp/android-$$-test.o 246TMPE=/tmp/android-$$-test$EXE 247TMPL=/tmp/android-$$-test.log 248 249# cleanup temporary files 250clean_temp () 251{ 252 rm -f $TMPC $TMPO $TMPL $TMPE 253} 254 255# cleanup temp files then exit with an error 256clean_exit () 257{ 258 clean_temp 259 exit 1 260} 261 262# this function will setup the compiler and linker and check that they work as advertised 263# note that you should call 'force_32bit_binaries' before this one if you want it to 264# generate 32-bit binaries on 64-bit systems (that support it). 265# 266setup_toolchain () 267{ 268 if [ -z "$CC" ] ; then 269 CC=gcc 270 fi 271 272 log2 "Using '$CC' as the C compiler" 273 274 # check that we can compile a trivial C program with this compiler 275 cat > $TMPC <<EOF 276int main(void) {} 277EOF 278 279 if [ "$FORCE_32BIT" = yes ] ; then 280 CFLAGS="$CFLAGS -m32" 281 LDFLAGS="$LDFLAGS -m32" 282 compile 283 if [ $? != 0 ] ; then 284 # sometimes, we need to also tell the assembler to generate 32-bit binaries 285 # this is highly dependent on your GCC installation (and no, we can't set 286 # this flag all the time) 287 CFLAGS="$CFLAGS -Wa,--32" 288 compile 289 fi 290 fi 291 292 compile 293 if [ $? != 0 ] ; then 294 echo "your C compiler doesn't seem to work:" 295 cat $TMPL 296 clean_exit 297 fi 298 log "CC : compiler check ok ($CC)" 299 300 # check that we can link the trivial program into an executable 301 if [ -z "$LD" ] ; then 302 LD=$CC 303 fi 304 link 305 if [ $? != 0 ] ; then 306 OLD_LD=$LD 307 LD=gcc 308 compile 309 link 310 if [ $? != 0 ] ; then 311 LD=$OLD_LD 312 echo "your linker doesn't seem to work:" 313 cat $TMPL 314 clean_exit 315 fi 316 fi 317 log2 "Using '$LD' as the linker" 318 log "LD : linker check ok ($LD)" 319 320 # check the C++ compiler 321 if [ -z "$CXX" ] ; then 322 CXX=g++ 323 fi 324 if [ -z "$CXXFLAGS" ] ; then 325 CXXFLAGS=$CFLAGS 326 fi 327 328 log2 "Using '$CXX' as the C++ compiler" 329 330 cat > $TMPC <<EOF 331#include <iostream> 332using namespace std; 333int main() 334{ 335 cout << "Hello World!" << endl; 336 return 0; 337} 338EOF 339 340 compile_cpp 341 if [ $? != 0 ] ; then 342 echo "your C++ compiler doesn't seem to work" 343 cat $TMPL 344 clean_exit 345 fi 346 347 log "CXX : C++ compiler check ok ($CXX)" 348 349 # XXX: TODO perform AR checks 350 AR=ar 351 ARFLAGS= 352} 353 354# try to compile the current source file in $TMPC into an object 355# stores the error log into $TMPL 356# 357compile () 358{ 359 log2 "Object : $CC -o $TMPO -c $CFLAGS $TMPC" 360 $CC -o $TMPO -c $CFLAGS $TMPC 2> $TMPL 361} 362 363compile_cpp () 364{ 365 log2 "Object : $CXX -o $TMPO -c $CXXFLAGS $TMPC" 366 $CXX -o $TMPO -c $CXXFLAGS $TMPC 2> $TMPL 367} 368 369# try to link the recently built file into an executable. error log in $TMPL 370# 371link() 372{ 373 log2 "Link : $LD -o $TMPE $TMPO $LDFLAGS" 374 $LD -o $TMPE $TMPO $LDFLAGS 2> $TMPL 375} 376 377# run a command 378# 379execute() 380{ 381 log2 "Running: $*" 382 $* 383} 384 385# perform a simple compile / link / run of the source file in $TMPC 386compile_exec_run() 387{ 388 log2 "RunExec : $CC -o $TMPE $CFLAGS $TMPC" 389 compile 390 if [ $? != 0 ] ; then 391 echo "Failure to compile test program" 392 cat $TMPC 393 cat $TMPL 394 clean_exit 395 fi 396 link 397 if [ $? != 0 ] ; then 398 echo "Failure to link test program" 399 cat $TMPC 400 echo "------" 401 cat $TMPL 402 clean_exit 403 fi 404 $TMPE 405} 406