1# Copyright (C) 2008 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# This file is included by other shell scripts; do not execute it directly.
16# It contains common definitions.
17#
18PROGNAME=`basename $0`
19
20## Logging support
21##
22VERBOSE=yes
23VERBOSE2=no
24
25log ()
26{
27    if [ "$VERBOSE" = "yes" ] ; then
28        echo "$1"
29    fi
30}
31
32log2 ()
33{
34    if [ "$VERBOSE2" = "yes" ] ; then
35        echo "$1"
36    fi
37}
38
39## Utilities
40##
41
42# return the value of a given named variable
43# $1: variable name
44#
45var_value ()
46{
47    # find a better way to do that ?
48    local result
49    eval result="$`echo $1`"
50    echo $result
51}
52
53# convert to uppercase
54to_uppercase ()
55{
56    echo $1 | tr "[:lower:]" "[:upper:]"
57}
58
59## Normalize OS and CPU
60##
61
62CPU=`uname -m`
63case "$CPU" in
64    i?86) CPU=x86
65    ;;
66    amd64) CPU=x86_64
67    ;;
68    powerpc) CPU=ppc
69    ;;
70esac
71
72log2 "CPU=$CPU"
73
74# at this point, the supported values for CPU are:
75#   x86
76#   x86_64
77#   ppc
78#
79# other values may be possible but haven't been tested
80#
81
82EXE=""
83OS=`uname -s`
84case "$OS" in
85    Darwin)
86        OS=darwin-$CPU
87        ;;
88    Linux)
89        # note that building  32-bit binaries on x86_64 is handled later
90        OS=linux-$CPU
91	;;
92    FreeBSD)
93        OS=freebsd-$CPU
94        ;;
95    CYGWIN*|*_NT-*)
96        OS=windows
97        EXE=.exe
98        if [ "x$OSTYPE" = xcygwin ] ; then
99            OS=cygwin
100            HOST_CFLAGS="$CFLAGS -mno-cygwin"
101            HOST_LDFLAGS="$LDFLAGS -mno-cygwin"
102        fi
103        ;;
104esac
105
106log2 "OS=$OS"
107log2 "EXE=$EXE"
108
109# at this point, the value of OS should be one of the following:
110#   linux-x86
111#   linux-x86_64
112#   darwin-x86
113#   darwin-ppc
114#   windows  (MSys)
115#   cygwin
116#
117# Note that cygwin is treated as a special case because it behaves very differently
118# for a few things
119#
120# other values may be possible but have not been tested
121
122# define HOST_OS as $OS without any cpu-specific suffix
123#
124case $OS in
125    linux-*) HOST_OS=linux
126    ;;
127    darwin-*) HOST_OS=darwin
128    ;;
129    freebsd-*) HOST_OS=freebsd
130    ;;
131    *) HOST_OS=$OS
132esac
133
134# define HOST_ARCH as the $CPU
135HOST_ARCH=$CPU
136
137#### Toolchain support
138####
139
140# Various probes are going to need to run a small C program
141TMPC=/tmp/android-$$-test.c
142TMPO=/tmp/android-$$-test.o
143TMPE=/tmp/android-$$-test$EXE
144TMPL=/tmp/android-$$-test.log
145
146# cleanup temporary files
147clean_temp ()
148{
149    rm -f $TMPC $TMPO $TMPL $TMPE
150}
151
152# cleanup temp files then exit with an error
153clean_exit ()
154{
155    clean_temp
156    exit 1
157}
158
159# this function should be called to enforce the build of 32-bit binaries on 64-bit systems
160# that support it.
161FORCE_32BIT=no
162force_32bit_binaries ()
163{
164    if [ $CPU = x86_64 ] ; then
165        FORCE_32BIT=yes
166        case $OS in
167            linux-x86_64) OS=linux-x86 ;;
168            darwin-x86_64) OS=darwin-x86 ;;
169	    freebsd-x86_64) OS=freebsd-x86 ;;
170        esac
171        HOST_ARCH=x86
172        CPU=x86
173        log "Check32Bits: Forcing generation of 32-bit binaries (--try-64 to disable)"
174    fi
175}
176
177# Cygwin is normally not supported, unless you call this function
178#
179enable_cygwin ()
180{
181    if [ $OS = cygwin ] ; then
182        CFLAGS="$CFLAGS -mno-cygwin"
183        LDFLAGS="$LDFLAGS -mno-cygwin"
184        OS=windows
185        HOST_OS=windows
186    fi
187}
188
189# this function will setup the compiler and linker and check that they work as advertized
190# note that you should call 'force_32bit_binaries' before this one if you want it to work
191# as advertized.
192#
193setup_toolchain ()
194{
195    if [ "$OS" = cygwin ] ; then
196        echo "Do not compile this program or library with Cygwin, use MSYS instead !!"
197        echo "As an experimental feature, you can try to --try-cygwin option to override this"
198        exit 2
199    fi
200
201    if [ -z "$CC" ] ; then
202        CC=gcc
203        if [ $CPU = "powerpc" ] ; then
204            CC=gcc-3.3
205        fi
206    fi
207
208    # check that we can compile a trivial C program with this compiler
209    cat > $TMPC <<EOF
210int main(void) {}
211EOF
212
213    if [ $FORCE_32BIT = yes ] ; then
214        CFLAGS="$CFLAGS -m32"
215        LDFLAGS="$LDFLAGS -m32"
216        compile
217        if [ $? != 0 ] ; then
218            # sometimes, we need to also tell the assembler to generate 32-bit binaries
219            # this is highly dependent on your GCC installation (and no, we can't set
220            # this flag all the time)
221            CFLAGS="$CFLAGS -Wa,--32"
222            compile
223        fi
224    fi
225
226    compile
227    if [ $? != 0 ] ; then
228        echo "your C compiler doesn't seem to work:"
229        cat $TMPL
230        clean_exit
231    fi
232    log "CC         : compiler check ok ($CC)"
233
234    # check that we can link the trivial program into an executable
235    if [ -z "$LD" ] ; then
236        LD=$CC
237    fi
238    link
239    if [ $? != 0 ] ; then
240        OLD_LD=$LD
241        LD=gcc
242        compile
243        link
244        if [ $? != 0 ] ; then
245            LD=$OLD_LD
246            echo "your linker doesn't seem to work:"
247            cat $TMPL
248            clean_exit
249        fi
250    fi
251    log "LD         : linker check ok ($LD)"
252}
253
254# try to compile the current source file in $TMPC into an object
255# stores the error log into $TMPL
256#
257compile ()
258{
259    log2 "Object     : $CC -o $TMPO -c $CFLAGS $TMPC"
260    $CC -o $TMPO -c $CFLAGS $TMPC 2> $TMPL
261}
262
263# try to link the recently built file into an executable. error log in $TMPL
264#
265link()
266{
267    log2 "Link      : $LD -o $TMPE $TMPO $LDFLAGS"
268    $LD -o $TMPE $TMPO $LDFLAGS 2> $TMPL
269}
270
271# run a command
272#
273execute()
274{
275    log2 "Running: $*"
276    $*
277}
278
279# perform a simple compile / link / run of the source file in $TMPC
280compile_exec_run()
281{
282    log2 "RunExec    : $CC -o $TMPE $CFLAGS $TMPC"
283    compile
284    if [ $? != 0 ] ; then
285        echo "Failure to compile test program"
286        cat $TMPC
287        cat $TMPL
288        clean_exit
289    fi
290    link
291    if [ $? != 0 ] ; then
292        echo "Failure to link test program"
293        cat $TMPC
294        echo "------"
295        cat $TMPL
296        clean_exit
297    fi
298    $TMPE
299}
300
301## Feature test support
302##
303
304# Each feature test allows us to check against a single target-specific feature
305# We run the feature checks in a Makefile in order to be able to do them in
306# parallel, and we also have some cached values in our output directory, just
307# in case.
308#
309# check that a given C program in $TMPC can be compiled on the host system
310# $1: variable name which will be set to "yes" or "no" depending on result
311# you can define EXTRA_CFLAGS for extra C compiler flags
312# for convenience, this variable will be unset by the function
313#
314feature_check_compile ()
315{
316    local result_cc=yes
317    local OLD_CFLAGS
318    OLD_CFLAGS="$CFLAGS"
319    CFLAGS="$CFLAGS $EXTRA_CFLAGS"
320    compile
321    if [ $? != 0 ] ; then
322        result_cc=no
323    fi
324    eval $1=$result_cc
325    EXTRA_CFLAGS=
326    CFLAGS=$OLD_CFLAGS
327}
328
329# check that a given C program $TMPC can be linked on the host system
330# $1: variable name which will be set to "yes" or "no" depending on result
331# you can define EXTRA_CFLAGS for extra C compiler flags
332# you can define EXTRA_LDFLAGS for extra linker flags
333# for convenience, these variables will be unset by the function
334#
335feature_check_link ()
336{
337    local result_cl=yes
338    local OLD_CFLAGS OLD_LDFLAGS
339    OLD_CFLAGS=$CFLAGS
340    OLD_LDFLAGS=$LDFLAGS
341    CFLAGS="$CFLAGS $EXTRA_CFLAGS"
342    LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS"
343    compile
344    if [ $? != 0 ] ; then
345        result_cl=no
346    else
347        link
348        if [ $? != 0 ] ; then
349            result_cl=no
350        fi
351    fi
352    CFLAGS=$OLD_CFLAGS
353    LDFLAGS=$OLD_LDFLAGS
354    eval $1=$result_cl
355}
356
357# check that a given C header file exists on the host system
358# $1: variable name which will be set to "yes" or "no" depending on result
359# $2: header name
360#
361# you can define EXTRA_CFLAGS for extra C compiler flags
362# for convenience, this variable will be unset by the function.
363#
364feature_check_header ()
365{
366    local result_ch
367    log2 "HeaderChk  : $2"
368    echo "#include $2" > $TMPC
369    cat >> $TMPC <<EOF
370        int main(void) { return 0; }
371EOF
372    feature_check_compile result_ch
373    eval $1=$result_ch
374    #eval result=$`echo $1`
375    #log  "Host       : $1=$result_ch"
376}
377
378# run the test program that is in $TMPC and set its exit status
379# in the $1 variable.
380# you can define EXTRA_CFLAGS and EXTRA_LDFLAGS
381#
382feature_run_exec ()
383{
384    local run_exec_result
385    local OLD_CFLAGS="$CFLAGS"
386    local OLD_LDFLAGS="$LDFLAGS"
387    CFLAGS="$CFLAGS $EXTRA_CFLAGS"
388    LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS"
389    compile_exec_run
390    run_exec_result=$?
391    CFLAGS="$OLD_CFLAGS"
392    LDFLAGS="$OLD_LDFLAGS"
393    eval $1=$run_exec_result
394    log "Host       : $1=$run_exec_result"
395}
396
397## Android build system auto-detection
398##
399
400# check whether we're running within the Android build system
401# sets the variable IN_ANDROID_BUILD to either "yes" or "no"
402#
403# in case of success, defines ANDROID_TOP to point to the top
404# of the Android source tree.
405#
406check_android_build ()
407{
408    unset ANDROID_TOP
409    IN_ANDROID_BUILD=no
410
411    if [ -z "$ANDROID_PRODUCT_OUT" ] ; then
412        return ;
413    fi
414
415    ANDROID_TOP=`cd $ANDROID_PRODUCT_OUT/../../../.. && pwd`
416    log "ANDROID_TOP found at $ANDROID_TOP"
417    # $ANDROID_TOP/config/envsetup.make is for the old tree layout
418    # $ANDROID_TOP/build/envsetup.sh is for the new one
419    ANDROID_CONFIG_MK=$ANDROID_TOP/build/core/config.mk
420    if [ ! -f $ANDROID_CONFIG_MK ] ; then
421        ANDROID_CONFIG_MK=$ANDROID_TOP/config/envsetup.make
422    fi
423    if [ ! -f $ANDROID_CONFIG_MK ] ; then
424        echo "Weird: Cannot find build system root defaulting to non-Android build"
425        unset ANDROID_TOP
426        return
427    fi
428    # normalize ANDROID_TOP, we don't want a trailing /
429    ANDROID_TOPDIR=`dirname $ANDROID_TOP`
430    if [ "$ANDROID_TOPDIR" != "." ] ; then
431        ANDROID_TOP=$ANDROID_TOPDIR/`basename $ANDROID_TOP`
432    fi
433    IN_ANDROID_BUILD=yes
434}
435
436# Get the value of an Android build variable as an absolute path.
437# you should only call this if IN_ANDROID_BUILD is "yes"
438#
439get_android_abs_build_var ()
440{
441   (cd $ANDROID_TOP && CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core make -f $ANDROID_CONFIG_MK dumpvar-abs-$1)
442}
443
444# Locate the Android prebuilt directory for your os
445# you should only call this if IN_ANDROID_BUILD is "yes"
446#
447# This will set ANDROID_PREBUILT_HOST_TAG and ANDROID_PREBUILT
448#
449locate_android_prebuilt ()
450{
451    # locate prebuilt directory
452    ANDROID_PREBUILT_HOST_TAG=$OS
453    ANDROID_PREBUILT=$ANDROID_TOP/prebuilt/$ANDROID_PREBUILT_HOST_TAG
454    if [ ! -d $ANDROID_PREBUILT ] ; then
455        # this can happen when building on x86_64
456        case $OS in
457            linux-x86_64)
458                ANDROID_PREBUILT_HOST_TAG=linux-x86
459                ANDROID_PREBUILT=$ANDROID_TOP/prebuilt/$ANDROID_PREBUILT_HOST_TAG
460                log "Forcing usage of 32-bit prebuilts"
461                force_32bit_binaries
462                ;;
463            *)
464        esac
465        if [ ! -d $ANDROID_PREBUILT ] ; then
466            echo "Can't find the prebuilt directory $ANDROID_PREBUILT in Android build"
467            exit 1
468        fi
469    fi
470    log "Prebuilt   : ANDROID_PREBUILT=$ANDROID_PREBUILT"
471}
472
473## Build configuration file support
474## you must define $config_mk before calling this function
475##
476create_config_mk ()
477{
478    # create the directory if needed
479    local  config_dir
480    config_mk=${config_mk:-objs/config.make}
481    config_dir=`dirname $config_mk`
482    mkdir -p $config_dir 2> $TMPL
483    if [ $? != 0 ] ; then
484        echo "Can't create directory for build config file: $config_dir"
485        cat $TMPL
486        clean_exit
487    fi
488    
489    # re-create the start of the configuration file
490    log "Generate   : $config_mk"
491
492    echo "# This file was autogenerated by $PROGNAME. Do not edit !" > $config_mk
493    echo "OS          := $OS" >> $config_mk
494    echo "HOST_OS     := $HOST_OS" >> $config_mk
495    echo "HOST_ARCH   := $HOST_ARCH" >> $config_mk
496    echo "CC          := $CC" >> $config_mk
497    echo "HOST_CC     := $CC" >> $config_mk
498    echo "LD          := $LD" >> $config_mk
499    echo "CFLAGS      := $CFLAGS" >> $config_mk
500    echo "LDFLAGS     := $LDFLAGS" >> $config_mk
501}
502
503add_android_config_mk ()
504{
505    echo "" >> $config_mk
506    echo "TARGET_ARCH       := arm" >> $config_mk
507    echo "HOST_PREBUILT_TAG := $ANDROID_PREBUILT_HOST_TAG" >> $config_mk
508    echo "PREBUILT          := $ANDROID_PREBUILT" >> $config_mk
509}
510