Home | History | Annotate | Download | only in build
      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 #
     18 PROGNAME=`basename $0`
     19 
     20 ## Logging support
     21 ##
     22 VERBOSE=yes
     23 VERBOSE2=no
     24 
     25 log ()
     26 {
     27     if [ "$VERBOSE" = "yes" ] ; then
     28         echo "$1"
     29     fi
     30 }
     31 
     32 log2 ()
     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 #
     45 var_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
     54 to_uppercase ()
     55 {
     56     echo $1 | tr "[:lower:]" "[:upper:]"
     57 }
     58 
     59 ## Normalize OS and CPU
     60 ##
     61 
     62 CPU=`uname -m`
     63 case "$CPU" in
     64     i?86) CPU=x86
     65     ;;
     66     amd64) CPU=x86_64
     67     ;;
     68     powerpc) CPU=ppc
     69     ;;
     70 esac
     71 
     72 log2 "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 
     82 EXE=""
     83 OS=`uname -s`
     84 case "$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         ;;
    104 esac
    105 
    106 log2 "OS=$OS"
    107 log2 "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 #
    125 case $OS in
    126     linux-*) HOST_OS=linux
    127     ;;
    128     darwin-*) HOST_OS=darwin
    129     ;;
    130     freebsd-*) HOST_OS=freebsd
    131     ;;
    132     *) HOST_OS=$OS
    133 esac
    134 
    135 # define HOST_ARCH as the $CPU
    136 HOST_ARCH=$CPU
    137 
    138 # define HOST_TAG
    139 # special case: windows-x86 => windows
    140 compute_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 }
    151 compute_host_tag
    152 
    153 #### Toolchain support
    154 ####
    155 
    156 # Various probes are going to need to run a small C program
    157 TMPC=/tmp/android-$$-test.c
    158 TMPO=/tmp/android-$$-test.o
    159 TMPE=/tmp/android-$$-test$EXE
    160 TMPL=/tmp/android-$$-test.log
    161 
    162 # cleanup temporary files
    163 clean_temp ()
    164 {
    165     rm -f $TMPC $TMPO $TMPL $TMPE
    166 }
    167 
    168 # cleanup temp files then exit with an error
    169 clean_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.
    177 FORCE_32BIT=no
    178 force_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 #
    198 enable_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 "Mingw64    : Checking for mingw64 installation"
    208     MINGW64_PREFIX=x86_64-w64-mingw32
    209     find_program MINGW64_CC $MINGW64_PREFIX-gcc
    210     if [ -n "$MINGW64_CC" ]; then
    211         MINGW_CC=$MINGW64_CC
    212         MINGW_PREFIX=$MINGW64_PREFIX
    213     else
    214     log "Mingw      : Checking for mingw32 installation"
    215     MINGW32_PREFIX=i586-mingw32msvc
    216     find_program MINGW32_CC $MINGW32_PREFIX-gcc
    217     if [ -z "$MINGW32_CC" ] ; then
    218             echo "ERROR: It looks like neither $MINGW64_PREFIX-cc nor $MINGW32_PREFIX-gcc"
    219             echo "are in your path. Please install the mingw32 package !"
    220         exit 1
    221         fi
    222         MINGW_CC=$MINGW32_CC
    223         MINGW_PREFIX=$MINGW32_PREFIX
    224         FORCE_32BIT=no
    225     fi
    226     log2 "Mingw      : Found $MINGW32_CC"
    227     CC=$MINGW_CC
    228     LD=$MINGW_CC
    229     AR=$MINGW_PREFIX-ar
    230 }
    231 
    232 # Cygwin is normally not supported, unless you call this function
    233 #
    234 enable_cygwin ()
    235 {
    236     if [ $OS = cygwin ] ; then
    237         CFLAGS="$CFLAGS -mno-cygwin"
    238         LDFLAGS="$LDFLAGS -mno-cygwin"
    239         OS=windows
    240         HOST_OS=windows
    241     fi
    242 }
    243 
    244 # this function will setup the compiler and linker and check that they work as advertized
    245 # note that you should call 'force_32bit_binaries' before this one if you want it to work
    246 # as advertized.
    247 #
    248 setup_toolchain ()
    249 {
    250     if [ "$OS" = cygwin ] ; then
    251         echo "Do not compile this program or library with Cygwin, use MSYS instead !!"
    252         echo "As an experimental feature, you can try to --try-cygwin option to override this"
    253         exit 2
    254     fi
    255 
    256     if [ -z "$CC" ] ; then
    257         CC=gcc
    258         if [ $CPU = "powerpc" ] ; then
    259             CC=gcc-3.3
    260         fi
    261     fi
    262 
    263     # check that we can compile a trivial C program with this compiler
    264     cat > $TMPC <<EOF
    265 int main(void) {}
    266 EOF
    267 
    268     if [ $FORCE_32BIT = yes ] ; then
    269         CFLAGS="$CFLAGS -m32"
    270         LDFLAGS="$LDFLAGS -m32"
    271         compile
    272         if [ $? != 0 ] ; then
    273             # sometimes, we need to also tell the assembler to generate 32-bit binaries
    274             # this is highly dependent on your GCC installation (and no, we can't set
    275             # this flag all the time)
    276             CFLAGS="$CFLAGS -Wa,--32"
    277         fi
    278     fi
    279 
    280     compile
    281     if [ $? != 0 ] ; then
    282         echo "your C compiler doesn't seem to work: $CC"
    283         cat $TMPL
    284         clean_exit
    285     fi
    286     log "CC         : compiler check ok ($CC)"
    287 
    288     # check that we can link the trivial program into an executable
    289     if [ -z "$LD" ] ; then
    290         LD=$CC
    291     fi
    292     link
    293     if [ $? != 0 ] ; then
    294         echo "your linker doesn't seem to work:"
    295         cat $TMPL
    296         clean_exit
    297     fi
    298     log "LD         : linker check ok ($LD)"
    299 
    300     if [ -z "$AR" ]; then
    301         AR=ar
    302     fi
    303     log "AR         : archiver ($AR)"
    304     clean_temp
    305 }
    306 
    307 # try to compile the current source file in $TMPC into an object
    308 # stores the error log into $TMPL
    309 #
    310 compile ()
    311 {
    312     log2 "Object     : $CC -o $TMPO -c $CFLAGS $TMPC"
    313     $CC -o $TMPO -c $CFLAGS $TMPC 2> $TMPL
    314 }
    315 
    316 # try to link the recently built file into an executable. error log in $TMPL
    317 #
    318 link()
    319 {
    320     log2 "Link      : $LD -o $TMPE $TMPO $LDFLAGS"
    321     $LD -o $TMPE $TMPO $LDFLAGS 2> $TMPL
    322 }
    323 
    324 # run a command
    325 #
    326 execute()
    327 {
    328     log2 "Running: $*"
    329     $*
    330 }
    331 
    332 # perform a simple compile / link / run of the source file in $TMPC
    333 compile_exec_run()
    334 {
    335     log2 "RunExec    : $CC -o $TMPE $CFLAGS $TMPC"
    336     compile
    337     if [ $? != 0 ] ; then
    338         echo "Failure to compile test program"
    339         cat $TMPC
    340         cat $TMPL
    341         clean_exit
    342     fi
    343     link
    344     if [ $? != 0 ] ; then
    345         echo "Failure to link test program"
    346         cat $TMPC
    347         echo "------"
    348         cat $TMPL
    349         clean_exit
    350     fi
    351     $TMPE
    352 }
    353 
    354 ## Feature test support
    355 ##
    356 
    357 # Each feature test allows us to check against a single target-specific feature
    358 # We run the feature checks in a Makefile in order to be able to do them in
    359 # parallel, and we also have some cached values in our output directory, just
    360 # in case.
    361 #
    362 # check that a given C program in $TMPC can be compiled on the host system
    363 # $1: variable name which will be set to "yes" or "no" depending on result
    364 # you can define EXTRA_CFLAGS for extra C compiler flags
    365 # for convenience, this variable will be unset by the function
    366 #
    367 feature_check_compile ()
    368 {
    369     local result_cc=yes
    370     local OLD_CFLAGS
    371     OLD_CFLAGS="$CFLAGS"
    372     CFLAGS="$CFLAGS $EXTRA_CFLAGS"
    373     compile
    374     if [ $? != 0 ] ; then
    375         result_cc=no
    376     fi
    377     eval $1=$result_cc
    378     EXTRA_CFLAGS=
    379     CFLAGS=$OLD_CFLAGS
    380 }
    381 
    382 # check that a given C program $TMPC can be linked on the host system
    383 # $1: variable name which will be set to "yes" or "no" depending on result
    384 # you can define EXTRA_CFLAGS for extra C compiler flags
    385 # you can define EXTRA_LDFLAGS for extra linker flags
    386 # for convenience, these variables will be unset by the function
    387 #
    388 feature_check_link ()
    389 {
    390     local result_cl=yes
    391     local OLD_CFLAGS OLD_LDFLAGS
    392     OLD_CFLAGS=$CFLAGS
    393     OLD_LDFLAGS=$LDFLAGS
    394     CFLAGS="$CFLAGS $EXTRA_CFLAGS"
    395     LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS"
    396     compile
    397     if [ $? != 0 ] ; then
    398         result_cl=no
    399     else
    400         link
    401         if [ $? != 0 ] ; then
    402             result_cl=no
    403         fi
    404     fi
    405     CFLAGS=$OLD_CFLAGS
    406     LDFLAGS=$OLD_LDFLAGS
    407     eval $1=$result_cl
    408     clean_temp
    409 }
    410 
    411 # check that a given C header file exists on the host system
    412 # $1: variable name which will be set to "yes" or "no" depending on result
    413 # $2: header name
    414 #
    415 # you can define EXTRA_CFLAGS for extra C compiler flags
    416 # for convenience, this variable will be unset by the function.
    417 #
    418 feature_check_header ()
    419 {
    420     local result_ch
    421     log "HeaderCheck: $2"
    422     echo "#include $2" > $TMPC
    423     cat >> $TMPC <<EOF
    424         int main(void) { return 0; }
    425 EOF
    426     feature_check_compile result_ch
    427     eval $1=$result_ch
    428     #eval result=$`echo $1`
    429     #log  "Host       : $1=$result_ch"
    430     clean_temp
    431 }
    432 
    433 # run the test program that is in $TMPC and set its exit status
    434 # in the $1 variable.
    435 # you can define EXTRA_CFLAGS and EXTRA_LDFLAGS
    436 #
    437 feature_run_exec ()
    438 {
    439     local run_exec_result
    440     local OLD_CFLAGS="$CFLAGS"
    441     local OLD_LDFLAGS="$LDFLAGS"
    442     CFLAGS="$CFLAGS $EXTRA_CFLAGS"
    443     LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS"
    444     compile_exec_run
    445     run_exec_result=$?
    446     CFLAGS="$OLD_CFLAGS"
    447     LDFLAGS="$OLD_LDFLAGS"
    448     eval $1=$run_exec_result
    449     log "Host       : $1=$run_exec_result"
    450     clean_temp
    451 }
    452 
    453 ## Android build system auto-detection
    454 ##
    455 
    456 # check whether we're running within the Android build system
    457 # sets the variable IN_ANDROID_BUILD to either "yes" or "no"
    458 #
    459 # in case of success, defines ANDROID_TOP to point to the top
    460 # of the Android source tree.
    461 #
    462 check_android_build ()
    463 {
    464     unset ANDROID_TOP
    465     IN_ANDROID_BUILD=no
    466 
    467     if [ -z "$ANDROID_BUILD_TOP" ] ; then
    468         return ;
    469     fi
    470 
    471     ANDROID_TOP=$ANDROID_BUILD_TOP
    472     log "ANDROID_TOP found at $ANDROID_TOP"
    473     # $ANDROID_TOP/config/envsetup.make is for the old tree layout
    474     # $ANDROID_TOP/build/envsetup.sh is for the new one
    475     ANDROID_CONFIG_MK=$ANDROID_TOP/build/core/config.mk
    476     if [ ! -f $ANDROID_CONFIG_MK ] ; then
    477         ANDROID_CONFIG_MK=$ANDROID_TOP/config/envsetup.make
    478     fi
    479     if [ ! -f $ANDROID_CONFIG_MK ] ; then
    480         echo "Weird: Cannot find build system root defaulting to non-Android build"
    481         unset ANDROID_TOP
    482         return
    483     fi
    484     # normalize ANDROID_TOP, we don't want a trailing /
    485     ANDROID_TOPDIR=`dirname $ANDROID_TOP`
    486     if [ "$ANDROID_TOPDIR" != "." ] ; then
    487         ANDROID_TOP=$ANDROID_TOPDIR/`basename $ANDROID_TOP`
    488     fi
    489     IN_ANDROID_BUILD=yes
    490 }
    491 
    492 # Get the value of an Android build variable as an absolute path.
    493 # you should only call this if IN_ANDROID_BUILD is "yes"
    494 #
    495 get_android_abs_build_var ()
    496 {
    497    (cd $ANDROID_TOP && CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core make -f $ANDROID_CONFIG_MK dumpvar-abs-$1)
    498 }
    499 
    500 # Locate the Android prebuilt directory for your os
    501 # you should only call this if IN_ANDROID_BUILD is "yes"
    502 #
    503 # This will set ANDROID_PREBUILT_HOST_TAG, ANDROID_PREBUILT and ANDROID_PREBUILTS
    504 #
    505 locate_android_prebuilt ()
    506 {
    507     # locate prebuilt directory
    508     ANDROID_PREBUILT_HOST_TAG=$OS
    509     ANDROID_PREBUILT=$ANDROID_TOP/prebuilt/$ANDROID_PREBUILT_HOST_TAG  # AOSP still has it
    510     ANDROID_PREBUILTS=$ANDROID_TOP/prebuilts/misc/$ANDROID_PREBUILT_HOST_TAG # AOSP does't have it yet
    511     if [ ! -d $ANDROID_PREBUILT ] ; then
    512         # this can happen when building on x86_64, or in AOSP
    513         case $OS in
    514             linux-x86_64)
    515                 ANDROID_PREBUILT_HOST_TAG=linux-x86
    516                 ANDROID_PREBUILT=$ANDROID_TOP/prebuilt/$ANDROID_PREBUILT_HOST_TAG
    517                 ;;
    518             *)
    519         esac
    520         if [ ! -d $ANDROID_PREBUILT ] ; then
    521             ANDROID_PREBUILT=
    522         fi
    523     fi
    524     if [ ! -d $ANDROID_PREBUILTS ] ; then
    525         # this can happen when building on x86_64
    526         case $OS in
    527             linux-x86_64)
    528                 ANDROID_PREBUILT_HOST_TAG=linux-x86
    529                 ANDROID_PREBUILTS=$ANDROID_TOP/prebuilts/misc/$ANDROID_PREBUILT_HOST_TAG
    530                 ;;
    531             *)
    532         esac
    533         if [ ! -d $ANDROID_PREBUILTS ] ; then
    534             ANDROID_PREBUILTS=
    535         fi
    536     fi
    537     log "Prebuilt   : ANDROID_PREBUILT=$ANDROID_PREBUILT"
    538     log "Prebuilts  : ANDROID_PREBUILTS=$ANDROID_PREBUILTS"
    539 }
    540 
    541 ## Build configuration file support
    542 ## you must define $config_mk before calling this function
    543 ##
    544 ## $1: Optional output directory.
    545 create_config_mk ()
    546 {
    547     # create the directory if needed
    548     local  config_dir
    549     local out_dir=${1:-objs}
    550     config_mk=${config_mk:-$out_dir/config.make}
    551     config_dir=`dirname $config_mk`
    552     mkdir -p $config_dir 2> $TMPL
    553     if [ $? != 0 ] ; then
    554         echo "Can't create directory for build config file: $config_dir"
    555         cat $TMPL
    556         clean_exit
    557     fi
    558 
    559     # re-create the start of the configuration file
    560     log "Generate   : $config_mk"
    561 
    562     echo "# This file was autogenerated by $PROGNAME. Do not edit !" > $config_mk
    563     echo "OS          := $OS" >> $config_mk
    564     echo "HOST_OS     := $HOST_OS" >> $config_mk
    565     echo "HOST_ARCH   := $HOST_ARCH" >> $config_mk
    566     echo "CC          := $CC" >> $config_mk
    567     echo "LD          := $LD" >> $config_mk
    568     echo "AR          := $AR" >> $config_mk
    569     echo "CFLAGS      := $CFLAGS" >> $config_mk
    570     echo "LDFLAGS     := $LDFLAGS" >> $config_mk
    571     echo "HOST_CC     := $CC" >> $config_mk
    572     echo "HOST_LD     := $LD" >> $config_mk
    573     echo "HOST_AR     := $AR" >> $config_mk
    574     echo "OBJS_DIR    := $out_dir" >> $config_mk
    575 }
    576 
    577 add_android_config_mk ()
    578 {
    579     echo "" >> $config_mk
    580     if [ $TARGET_ARCH = arm ] ; then
    581     echo "TARGET_ARCH       := arm" >> $config_mk
    582     fi
    583     if [ $TARGET_ARCH = x86 ] ; then
    584     echo "TARGET_ARCH       := x86" >> $config_mk
    585     fi
    586     echo "HOST_PREBUILT_TAG := $HOST_TAG" >> $config_mk
    587     echo "PREBUILT          := $ANDROID_PREBUILT" >> $config_mk
    588     echo "PREBUILTS         := $ANDROID_PREBUILTS" >> $config_mk
    589 }
    590 
    591 # Find pattern $1 in string $2
    592 # This is to be used in if statements as in:
    593 #
    594 #    if pattern_match <pattern> <string>; then
    595 #       ...
    596 #    fi
    597 #
    598 pattern_match ()
    599 {
    600     echo "$2" | grep -q -E -e "$1"
    601 }
    602 
    603 # Find if a given shell program is available.
    604 # We need to take care of the fact that the 'which <foo>' command
    605 # may return either an empty string (Linux) or something like
    606 # "no <foo> in ..." (Darwin). Also, we need to redirect stderr
    607 # to /dev/null for Cygwin
    608 #
    609 # $1: variable name
    610 # $2: program name
    611 #
    612 # Result: set $1 to the full path of the corresponding command
    613 #         or to the empty/undefined string if not available
    614 #
    615 find_program ()
    616 {
    617     local PROG
    618     PROG=`which $2 2>/dev/null`
    619     if [ -n "$PROG" ] ; then
    620         if pattern_match '^no ' "$PROG"; then
    621             PROG=
    622         fi
    623     fi
    624     eval $1="$PROG"
    625 }
    626