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