common.sh revision 80dd1261df980abf963b7f4a73f43c1102848706
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# define HOST_TAG
138# special case: windows-x86 => windows
139compute_host_tag ()
140{
141    case $HOST_OS-$HOST_ARCH in
142        cygwin-x86|windows-x86)
143            HOST_TAG=windows
144            ;;
145        *)
146            HOST_TAG=$HOST_OS-$HOST_ARCH
147            ;;
148    esac
149}
150compute_host_tag
151
152#### Toolchain support
153####
154
155# Various probes are going to need to run a small C program
156TMPC=/tmp/android-$$-test.c
157TMPO=/tmp/android-$$-test.o
158TMPE=/tmp/android-$$-test$EXE
159TMPL=/tmp/android-$$-test.log
160
161# cleanup temporary files
162clean_temp ()
163{
164    rm -f $TMPC $TMPO $TMPL $TMPE
165}
166
167# cleanup temp files then exit with an error
168clean_exit ()
169{
170    clean_temp
171    exit 1
172}
173
174# this function should be called to enforce the build of 32-bit binaries on 64-bit systems
175# that support it.
176FORCE_32BIT=no
177force_32bit_binaries ()
178{
179    if [ $CPU = x86_64 ] ; then
180        FORCE_32BIT=yes
181        case $OS in
182            linux-x86_64) OS=linux-x86 ;;
183            darwin-x86_64) OS=darwin-x86 ;;
184	    freebsd-x86_64) OS=freebsd-x86 ;;
185        esac
186        HOST_ARCH=x86
187        CPU=x86
188        compute_host_tag
189        log "Check32Bits: Forcing generation of 32-bit binaries (--try-64 to disable)"
190    fi
191}
192
193# Enable linux-mingw32 compilation. This allows you to build
194# windows executables on a Linux machine, which is considerably
195# faster than using Cygwin / MSys to do the same job.
196#
197enable_linux_mingw ()
198{
199    # Are we on Linux ?
200    log "Mingw      : Checking for Linux host"
201    if [ "$HOST_OS" != "linux" ] ; then
202        echo "Sorry, but mingw compilation is only supported on Linux !"
203        exit 1
204    fi
205    # Do we have the binaries installed
206    log "Mingw      : Checking for mingw32 installation"
207    MINGW32_PREFIX=i586-mingw32msvc
208    find_program MINGW32_CC $MINGW32_PREFIX-gcc
209    if [ -z "$MINGW32_CC" ] ; then
210        echo "ERROR: It looks like $MINGW32_PREFIX-gcc is not in your path"
211        echo "Please install the mingw32 package !"
212        exit 1
213    fi
214    log2 "Mingw      : Found $MINGW32_CC"
215    CC=$MINGW32_CC
216    LD=$MINGW32_CC
217    AR=$MINGW32_PREFIX-ar
218    FORCE_32BIT=no
219}
220
221# Cygwin is normally not supported, unless you call this function
222#
223enable_cygwin ()
224{
225    if [ $OS = cygwin ] ; then
226        CFLAGS="$CFLAGS -mno-cygwin"
227        LDFLAGS="$LDFLAGS -mno-cygwin"
228        OS=windows
229        HOST_OS=windows
230    fi
231}
232
233# this function will setup the compiler and linker and check that they work as advertized
234# note that you should call 'force_32bit_binaries' before this one if you want it to work
235# as advertized.
236#
237setup_toolchain ()
238{
239    if [ "$OS" = cygwin ] ; then
240        echo "Do not compile this program or library with Cygwin, use MSYS instead !!"
241        echo "As an experimental feature, you can try to --try-cygwin option to override this"
242        exit 2
243    fi
244
245    if [ -z "$CC" ] ; then
246        CC=gcc
247        if [ $CPU = "powerpc" ] ; then
248            CC=gcc-3.3
249        fi
250    fi
251
252    # check that we can compile a trivial C program with this compiler
253    cat > $TMPC <<EOF
254int main(void) {}
255EOF
256
257    if [ $FORCE_32BIT = yes ] ; then
258        CFLAGS="$CFLAGS -m32"
259        LDFLAGS="$LDFLAGS -m32"
260        compile
261        if [ $? != 0 ] ; then
262            # sometimes, we need to also tell the assembler to generate 32-bit binaries
263            # this is highly dependent on your GCC installation (and no, we can't set
264            # this flag all the time)
265            CFLAGS="$CFLAGS -Wa,--32"
266            compile
267        fi
268    fi
269
270    compile
271    if [ $? != 0 ] ; then
272        echo "your C compiler doesn't seem to work:"
273        cat $TMPL
274        clean_exit
275    fi
276    log "CC         : compiler check ok ($CC)"
277
278    # check that we can link the trivial program into an executable
279    if [ -z "$LD" ] ; then
280        LD=$CC
281    fi
282    link
283    if [ $? != 0 ] ; then
284        OLD_LD=$LD
285        LD=gcc
286        compile
287        link
288        if [ $? != 0 ] ; then
289            LD=$OLD_LD
290            echo "your linker doesn't seem to work:"
291            cat $TMPL
292            clean_exit
293        fi
294    fi
295    log "LD         : linker check ok ($LD)"
296
297    if [ -z "$AR" ]; then
298        AR=ar
299    fi
300    log "AR         : archiver ($AR)"
301}
302
303# try to compile the current source file in $TMPC into an object
304# stores the error log into $TMPL
305#
306compile ()
307{
308    log2 "Object     : $CC -o $TMPO -c $CFLAGS $TMPC"
309    $CC -o $TMPO -c $CFLAGS $TMPC 2> $TMPL
310}
311
312# try to link the recently built file into an executable. error log in $TMPL
313#
314link()
315{
316    log2 "Link      : $LD -o $TMPE $TMPO $LDFLAGS"
317    $LD -o $TMPE $TMPO $LDFLAGS 2> $TMPL
318}
319
320# run a command
321#
322execute()
323{
324    log2 "Running: $*"
325    $*
326}
327
328# perform a simple compile / link / run of the source file in $TMPC
329compile_exec_run()
330{
331    log2 "RunExec    : $CC -o $TMPE $CFLAGS $TMPC"
332    compile
333    if [ $? != 0 ] ; then
334        echo "Failure to compile test program"
335        cat $TMPC
336        cat $TMPL
337        clean_exit
338    fi
339    link
340    if [ $? != 0 ] ; then
341        echo "Failure to link test program"
342        cat $TMPC
343        echo "------"
344        cat $TMPL
345        clean_exit
346    fi
347    $TMPE
348}
349
350## Feature test support
351##
352
353# Each feature test allows us to check against a single target-specific feature
354# We run the feature checks in a Makefile in order to be able to do them in
355# parallel, and we also have some cached values in our output directory, just
356# in case.
357#
358# check that a given C program in $TMPC can be compiled on the host system
359# $1: variable name which will be set to "yes" or "no" depending on result
360# you can define EXTRA_CFLAGS for extra C compiler flags
361# for convenience, this variable will be unset by the function
362#
363feature_check_compile ()
364{
365    local result_cc=yes
366    local OLD_CFLAGS
367    OLD_CFLAGS="$CFLAGS"
368    CFLAGS="$CFLAGS $EXTRA_CFLAGS"
369    compile
370    if [ $? != 0 ] ; then
371        result_cc=no
372    fi
373    eval $1=$result_cc
374    EXTRA_CFLAGS=
375    CFLAGS=$OLD_CFLAGS
376}
377
378# check that a given C program $TMPC can be linked on the host system
379# $1: variable name which will be set to "yes" or "no" depending on result
380# you can define EXTRA_CFLAGS for extra C compiler flags
381# you can define EXTRA_LDFLAGS for extra linker flags
382# for convenience, these variables will be unset by the function
383#
384feature_check_link ()
385{
386    local result_cl=yes
387    local OLD_CFLAGS OLD_LDFLAGS
388    OLD_CFLAGS=$CFLAGS
389    OLD_LDFLAGS=$LDFLAGS
390    CFLAGS="$CFLAGS $EXTRA_CFLAGS"
391    LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS"
392    compile
393    if [ $? != 0 ] ; then
394        result_cl=no
395    else
396        link
397        if [ $? != 0 ] ; then
398            result_cl=no
399        fi
400    fi
401    CFLAGS=$OLD_CFLAGS
402    LDFLAGS=$OLD_LDFLAGS
403    eval $1=$result_cl
404}
405
406# check that a given C header file exists on the host system
407# $1: variable name which will be set to "yes" or "no" depending on result
408# $2: header name
409#
410# you can define EXTRA_CFLAGS for extra C compiler flags
411# for convenience, this variable will be unset by the function.
412#
413feature_check_header ()
414{
415    local result_ch
416    log "HeaderCheck: $2"
417    echo "#include $2" > $TMPC
418    cat >> $TMPC <<EOF
419        int main(void) { return 0; }
420EOF
421    feature_check_compile result_ch
422    eval $1=$result_ch
423    #eval result=$`echo $1`
424    #log  "Host       : $1=$result_ch"
425}
426
427# run the test program that is in $TMPC and set its exit status
428# in the $1 variable.
429# you can define EXTRA_CFLAGS and EXTRA_LDFLAGS
430#
431feature_run_exec ()
432{
433    local run_exec_result
434    local OLD_CFLAGS="$CFLAGS"
435    local OLD_LDFLAGS="$LDFLAGS"
436    CFLAGS="$CFLAGS $EXTRA_CFLAGS"
437    LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS"
438    compile_exec_run
439    run_exec_result=$?
440    CFLAGS="$OLD_CFLAGS"
441    LDFLAGS="$OLD_LDFLAGS"
442    eval $1=$run_exec_result
443    log "Host       : $1=$run_exec_result"
444}
445
446## Android build system auto-detection
447##
448
449# check whether we're running within the Android build system
450# sets the variable IN_ANDROID_BUILD to either "yes" or "no"
451#
452# in case of success, defines ANDROID_TOP to point to the top
453# of the Android source tree.
454#
455check_android_build ()
456{
457    unset ANDROID_TOP
458    IN_ANDROID_BUILD=no
459
460    if [ -z "$ANDROID_PRODUCT_OUT" ] ; then
461        return ;
462    fi
463
464    ANDROID_TOP=`cd $ANDROID_PRODUCT_OUT/../../../.. && pwd`
465    log "ANDROID_TOP found at $ANDROID_TOP"
466    # $ANDROID_TOP/config/envsetup.make is for the old tree layout
467    # $ANDROID_TOP/build/envsetup.sh is for the new one
468    ANDROID_CONFIG_MK=$ANDROID_TOP/build/core/config.mk
469    if [ ! -f $ANDROID_CONFIG_MK ] ; then
470        ANDROID_CONFIG_MK=$ANDROID_TOP/config/envsetup.make
471    fi
472    if [ ! -f $ANDROID_CONFIG_MK ] ; then
473        echo "Weird: Cannot find build system root defaulting to non-Android build"
474        unset ANDROID_TOP
475        return
476    fi
477    # normalize ANDROID_TOP, we don't want a trailing /
478    ANDROID_TOPDIR=`dirname $ANDROID_TOP`
479    if [ "$ANDROID_TOPDIR" != "." ] ; then
480        ANDROID_TOP=$ANDROID_TOPDIR/`basename $ANDROID_TOP`
481    fi
482    IN_ANDROID_BUILD=yes
483}
484
485# Get the value of an Android build variable as an absolute path.
486# you should only call this if IN_ANDROID_BUILD is "yes"
487#
488get_android_abs_build_var ()
489{
490   (cd $ANDROID_TOP && CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core make -f $ANDROID_CONFIG_MK dumpvar-abs-$1)
491}
492
493# Locate the Android prebuilt directory for your os
494# you should only call this if IN_ANDROID_BUILD is "yes"
495#
496# This will set ANDROID_PREBUILT_HOST_TAG and ANDROID_PREBUILT
497#
498locate_android_prebuilt ()
499{
500    # locate prebuilt directory
501    ANDROID_PREBUILT_HOST_TAG=$OS
502    ANDROID_PREBUILT=$ANDROID_TOP/prebuilt/$ANDROID_PREBUILT_HOST_TAG
503    if [ ! -d $ANDROID_PREBUILT ] ; then
504        # this can happen when building on x86_64
505        case $OS in
506            linux-x86_64)
507                ANDROID_PREBUILT_HOST_TAG=linux-x86
508                ANDROID_PREBUILT=$ANDROID_TOP/prebuilt/$ANDROID_PREBUILT_HOST_TAG
509                log "Forcing usage of 32-bit prebuilts"
510                force_32bit_binaries
511                ;;
512            *)
513        esac
514        if [ ! -d $ANDROID_PREBUILT ] ; then
515            echo "Can't find the prebuilt directory $ANDROID_PREBUILT in Android build"
516            exit 1
517        fi
518    fi
519    log "Prebuilt   : ANDROID_PREBUILT=$ANDROID_PREBUILT"
520}
521
522## Build configuration file support
523## you must define $config_mk before calling this function
524##
525create_config_mk ()
526{
527    # create the directory if needed
528    local  config_dir
529    config_mk=${config_mk:-objs/config.make}
530    config_dir=`dirname $config_mk`
531    mkdir -p $config_dir 2> $TMPL
532    if [ $? != 0 ] ; then
533        echo "Can't create directory for build config file: $config_dir"
534        cat $TMPL
535        clean_exit
536    fi
537    
538    # re-create the start of the configuration file
539    log "Generate   : $config_mk"
540
541    echo "# This file was autogenerated by $PROGNAME. Do not edit !" > $config_mk
542    echo "OS          := $OS" >> $config_mk
543    echo "HOST_OS     := $HOST_OS" >> $config_mk
544    echo "HOST_ARCH   := $HOST_ARCH" >> $config_mk
545    echo "CC          := $CC" >> $config_mk
546    echo "HOST_CC     := $CC" >> $config_mk
547    echo "LD          := $LD" >> $config_mk
548    echo "AR          := $AR" >> $config_mk
549    echo "CFLAGS      := $CFLAGS" >> $config_mk
550    echo "LDFLAGS     := $LDFLAGS" >> $config_mk
551}
552
553add_android_config_mk ()
554{
555    echo "" >> $config_mk
556    echo "TARGET_ARCH       := arm" >> $config_mk
557    echo "HOST_PREBUILT_TAG := $HOST_TAG" >> $config_mk
558    echo "PREBUILT          := $ANDROID_PREBUILT" >> $config_mk
559}
560
561# Find pattern $1 in string $2
562# This is to be used in if statements as in:
563#
564#    if pattern_match <pattern> <string>; then
565#       ...
566#    fi
567#
568pattern_match ()
569{
570    echo "$2" | grep -q -E -e "$1"
571}
572
573# Find if a given shell program is available.
574# We need to take care of the fact that the 'which <foo>' command
575# may return either an empty string (Linux) or something like
576# "no <foo> in ..." (Darwin). Also, we need to redirect stderr
577# to /dev/null for Cygwin
578#
579# $1: variable name
580# $2: program name
581#
582# Result: set $1 to the full path of the corresponding command
583#         or to the empty/undefined string if not available
584#
585find_program ()
586{
587    local PROG
588    PROG=`which $2 2>/dev/null`
589    if [ -n "$PROG" ] ; then
590        if pattern_match '^no ' "$PROG"; then
591            PROG=
592        fi
593    fi
594    eval $1="$PROG"
595}
596