• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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