# Copyright (C) 2008 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This file is included by other shell scripts; do not execute it directly. # It contains common definitions. # PROGNAME=`basename $0` ## Logging support ## VERBOSE=yes VERBOSE2=no log () { if [ "$VERBOSE" = "yes" ] ; then echo "$1" fi } log2 () { if [ "$VERBOSE2" = "yes" ] ; then echo "$1" fi } ## Utilities ## # return the value of a given named variable # $1: variable name # var_value () { # find a better way to do that ? local result eval result="$`echo $1`" echo $result } # convert to uppercase to_uppercase () { echo $1 | tr "[:lower:]" "[:upper:]" } ## Normalize OS and CPU ## CPU=`uname -m` case "$CPU" in i?86) CPU=x86 ;; amd64) CPU=x86_64 ;; powerpc) CPU=ppc ;; esac log2 "CPU=$CPU" # at this point, the supported values for CPU are: # x86 # x86_64 # ppc # # other values may be possible but haven't been tested # EXE="" OS=`uname -s` case "$OS" in Darwin) OS=darwin-$CPU ;; Linux) # note that building 32-bit binaries on x86_64 is handled later OS=linux-$CPU ;; FreeBSD) OS=freebsd-$CPU ;; CYGWIN*|*_NT-*) OS=windows EXE=.exe if [ "x$OSTYPE" = xcygwin ] ; then OS=cygwin HOST_CFLAGS="$CFLAGS -mno-cygwin" HOST_LDFLAGS="$LDFLAGS -mno-cygwin" fi ;; esac log2 "OS=$OS" log2 "EXE=$EXE" # at this point, the value of OS should be one of the following: # linux-x86 # linux-x86_64 # darwin-x86 # darwin-ppc # windows (MSys) # cygwin # # Note that cygwin is treated as a special case because it behaves very differently # for a few things # # other values may be possible but have not been tested # define HOST_OS as $OS without any cpu-specific suffix # case $OS in linux-*) HOST_OS=linux ;; darwin-*) HOST_OS=darwin ;; freebsd-*) HOST_OS=freebsd ;; *) HOST_OS=$OS esac # define HOST_ARCH as the $CPU HOST_ARCH=$CPU # define HOST_TAG # special case: windows-x86 => windows compute_host_tag () { case $HOST_OS-$HOST_ARCH in cygwin-x86|windows-x86) HOST_TAG=windows ;; *) HOST_TAG=$HOST_OS-$HOST_ARCH ;; esac } compute_host_tag #### Toolchain support #### # Various probes are going to need to run a small C program TMPC=/tmp/android-$$-test.c TMPO=/tmp/android-$$-test.o TMPE=/tmp/android-$$-test$EXE TMPL=/tmp/android-$$-test.log # cleanup temporary files clean_temp () { rm -f $TMPC $TMPO $TMPL $TMPE } # cleanup temp files then exit with an error clean_exit () { clean_temp exit 1 } # this function should be called to enforce the build of 32-bit binaries on 64-bit systems # that support it. FORCE_32BIT=no force_32bit_binaries () { if [ $CPU = x86_64 ] ; then FORCE_32BIT=yes case $OS in linux-x86_64) OS=linux-x86 ;; darwin-x86_64) OS=darwin-x86 ;; freebsd-x86_64) OS=freebsd-x86 ;; esac HOST_ARCH=x86 CPU=x86 compute_host_tag log "Check32Bits: Forcing generation of 32-bit binaries (--try-64 to disable)" fi } # Enable linux-mingw32 compilation. This allows you to build # windows executables on a Linux machine, which is considerably # faster than using Cygwin / MSys to do the same job. # enable_linux_mingw () { # Are we on Linux ? log "Mingw : Checking for Linux host" if [ "$HOST_OS" != "linux" ] ; then echo "Sorry, but mingw compilation is only supported on Linux !" exit 1 fi # Do we have the binaries installed log "Mingw : Checking for mingw32 installation" MINGW32_PREFIX=i586-mingw32msvc find_program MINGW32_CC $MINGW32_PREFIX-gcc if [ -z "$MINGW32_CC" ] ; then echo "ERROR: It looks like $MINGW32_PREFIX-gcc is not in your path" echo "Please install the mingw32 package !" exit 1 fi log2 "Mingw : Found $MINGW32_CC" CC=$MINGW32_CC LD=$MINGW32_CC AR=$MINGW32_PREFIX-ar FORCE_32BIT=no } # Cygwin is normally not supported, unless you call this function # enable_cygwin () { if [ $OS = cygwin ] ; then CFLAGS="$CFLAGS -mno-cygwin" LDFLAGS="$LDFLAGS -mno-cygwin" OS=windows HOST_OS=windows fi } # this function will setup the compiler and linker and check that they work as advertized # note that you should call 'force_32bit_binaries' before this one if you want it to work # as advertized. # setup_toolchain () { if [ "$OS" = cygwin ] ; then echo "Do not compile this program or library with Cygwin, use MSYS instead !!" echo "As an experimental feature, you can try to --try-cygwin option to override this" exit 2 fi if [ -z "$CC" ] ; then CC=gcc if [ $CPU = "powerpc" ] ; then CC=gcc-3.3 fi fi # check that we can compile a trivial C program with this compiler cat > $TMPC < $TMPL } # try to link the recently built file into an executable. error log in $TMPL # link() { log2 "Link : $LD -o $TMPE $TMPO $LDFLAGS" $LD -o $TMPE $TMPO $LDFLAGS 2> $TMPL } # run a command # execute() { log2 "Running: $*" $* } # perform a simple compile / link / run of the source file in $TMPC compile_exec_run() { log2 "RunExec : $CC -o $TMPE $CFLAGS $TMPC" compile if [ $? != 0 ] ; then echo "Failure to compile test program" cat $TMPC cat $TMPL clean_exit fi link if [ $? != 0 ] ; then echo "Failure to link test program" cat $TMPC echo "------" cat $TMPL clean_exit fi $TMPE } ## Feature test support ## # Each feature test allows us to check against a single target-specific feature # We run the feature checks in a Makefile in order to be able to do them in # parallel, and we also have some cached values in our output directory, just # in case. # # check that a given C program in $TMPC can be compiled on the host system # $1: variable name which will be set to "yes" or "no" depending on result # you can define EXTRA_CFLAGS for extra C compiler flags # for convenience, this variable will be unset by the function # feature_check_compile () { local result_cc=yes local OLD_CFLAGS OLD_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $EXTRA_CFLAGS" compile if [ $? != 0 ] ; then result_cc=no fi eval $1=$result_cc EXTRA_CFLAGS= CFLAGS=$OLD_CFLAGS } # check that a given C program $TMPC can be linked on the host system # $1: variable name which will be set to "yes" or "no" depending on result # you can define EXTRA_CFLAGS for extra C compiler flags # you can define EXTRA_LDFLAGS for extra linker flags # for convenience, these variables will be unset by the function # feature_check_link () { local result_cl=yes local OLD_CFLAGS OLD_LDFLAGS OLD_CFLAGS=$CFLAGS OLD_LDFLAGS=$LDFLAGS CFLAGS="$CFLAGS $EXTRA_CFLAGS" LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS" compile if [ $? != 0 ] ; then result_cl=no else link if [ $? != 0 ] ; then result_cl=no fi fi CFLAGS=$OLD_CFLAGS LDFLAGS=$OLD_LDFLAGS eval $1=$result_cl } # check that a given C header file exists on the host system # $1: variable name which will be set to "yes" or "no" depending on result # $2: header name # # you can define EXTRA_CFLAGS for extra C compiler flags # for convenience, this variable will be unset by the function. # feature_check_header () { local result_ch log "HeaderCheck: $2" echo "#include $2" > $TMPC cat >> $TMPC < $TMPL if [ $? != 0 ] ; then echo "Can't create directory for build config file: $config_dir" cat $TMPL clean_exit fi # re-create the start of the configuration file log "Generate : $config_mk" echo "# This file was autogenerated by $PROGNAME. Do not edit !" > $config_mk echo "OS := $OS" >> $config_mk echo "HOST_OS := $HOST_OS" >> $config_mk echo "HOST_ARCH := $HOST_ARCH" >> $config_mk echo "CC := $CC" >> $config_mk echo "HOST_CC := $CC" >> $config_mk echo "LD := $LD" >> $config_mk echo "AR := $AR" >> $config_mk echo "CFLAGS := $CFLAGS" >> $config_mk echo "LDFLAGS := $LDFLAGS" >> $config_mk } add_android_config_mk () { echo "" >> $config_mk echo "TARGET_ARCH := arm" >> $config_mk echo "HOST_PREBUILT_TAG := $HOST_TAG" >> $config_mk echo "PREBUILT := $ANDROID_PREBUILT" >> $config_mk } # Find pattern $1 in string $2 # This is to be used in if statements as in: # # if pattern_match ; then # ... # fi # pattern_match () { echo "$2" | grep -q -E -e "$1" } # Find if a given shell program is available. # We need to take care of the fact that the 'which ' command # may return either an empty string (Linux) or something like # "no in ..." (Darwin). Also, we need to redirect stderr # to /dev/null for Cygwin # # $1: variable name # $2: program name # # Result: set $1 to the full path of the corresponding command # or to the empty/undefined string if not available # find_program () { local PROG PROG=`which $2 2>/dev/null` if [ -n "$PROG" ] ; then if pattern_match '^no ' "$PROG"; then PROG= fi fi eval $1="$PROG" }