• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#
2# Copyright (C) 2011 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16#  This file contains various shell function definitions that can be
17#  used to either build a static and shared libraries from sources, or
18#  generate a Makefile to do it in parallel.
19#
20
21_BUILD_TAB=$(echo " " | tr ' ' '\t')
22
23builder_command ()
24{
25    if [ -z "$_BUILD_MK" ]; then
26        if [ "$VERBOSE2" = "yes" ]; then
27            echo "$@"
28        fi
29        "$@"
30    else
31        echo "${_BUILD_TAB}${_BUILD_HIDE}$@" >> $_BUILD_MK
32    fi
33}
34
35
36builder_log ()
37{
38    if [ "$_BUILD_MK" ]; then
39        echo "${_BUILD_TAB}${_BUILD_HIDE}echo $@" >> $_BUILD_MK
40    else
41        log "$@"
42    fi
43}
44
45# $1: Build directory
46# $2: Optional Makefile name
47builder_begin ()
48{
49    _BUILD_DIR_NEW=
50    _BUILD_DIR=$1
51    if [ ! -d "$_BUILD_DIR" ]; then
52        mkdir -p "$_BUILD_DIR"
53        fail_panic "Can't create build directory: $_BUILD_DIR"
54        _BUILD_DIR_NEW=true
55    else
56        rm -rf "$_BUILD_DIR/*"
57        fail_panic "Can't cleanup build directory: $_BUILD_DIR"
58    fi
59    _BUILD_TARGETS=
60    _BUILD_PREFIX=
61    _BUILD_MK=$2
62    if [ -n "$_BUILD_MK" ]; then
63        log "Creating temporary build Makefile: $_BUILD_MK"
64        rm -f $_BUILD_MK &&
65        echo "# Auto-generated by $0 - do not edit!" > $_BUILD_MK
66        echo ".PHONY: all" >> $_BUILD_MK
67        echo "all:" >> $_BUILD_MK
68    fi
69    # HIDE is used to hide the Makefile output, unless --verbose --verbose
70    # is used.
71    if [ "$VERBOSE2" = "yes" ]; then
72        _BUILD_HIDE=""
73    else
74        _BUILD_HIDE=@
75    fi
76
77    builder_begin_module
78}
79
80# $1: Variable name
81# out: Variable value
82_builder_varval ()
83{
84    eval echo "\$$1"
85}
86
87_builder_varadd ()
88{
89    local _varname="$1"
90    local _varval="$(_builder_varval $_varname)"
91    shift
92    if [ -z "$_varval" ]; then
93        eval $_varname=\"$@\"
94    else
95        eval $_varname=\$$_varname\" $@\"
96    fi
97}
98
99
100builder_set_prefix ()
101{
102    _BUILD_PREFIX="$@"
103}
104
105builder_begin_module ()
106{
107    _BUILD_CC=
108    _BUILD_CXX=
109    _BUILD_AR=
110    _BUILD_C_INCLUDES=
111    _BUILD_CFLAGS=
112    _BUILD_CXXFLAGS=
113    _BUILD_LDFLAGS_BEGIN_SO=
114    _BUILD_LDFLAGS_END_SO=
115    _BUILD_LDFLAGS_BEGIN_EXE=
116    _BUILD_LDFLAGS_END_EXE=
117    _BUILD_LDFLAGS=
118    _BUILD_BINPREFIX=
119    _BUILD_DSTDIR=
120    _BUILD_SRCDIR=.
121    _BUILD_OBJECTS=
122    _BUILD_STATIC_LIBRARIES=
123    _BUILD_SHARED_LIBRARIES=
124}
125
126builder_set_binprefix ()
127{
128    _BUILD_BINPREFIX=$1
129    _BUILD_CC=${1}gcc
130    _BUILD_CXX=${1}g++
131    _BUILD_AR=${1}ar
132}
133
134builder_set_binprefix_llvm ()
135{
136    _BUILD_BINPREFIX=$1
137    _BUILD_CC=${1}clang
138    _BUILD_CXX=${1}clang++
139}
140
141builder_set_builddir ()
142{
143    _BUILD_DIR=$1
144}
145
146builder_set_srcdir ()
147{
148    _BUILD_SRCDIR=$1
149}
150
151builder_set_dstdir ()
152{
153    _BUILD_DSTDIR=$1
154}
155
156builder_ldflags ()
157{
158    _builder_varadd _BUILD_LDFLAGS "$@"
159}
160
161builder_ldflags_exe ()
162{
163    _builder_varadd _BUILD_LDFLAGS_EXE "$@"
164}
165
166builder_cflags ()
167{
168    _builder_varadd _BUILD_CFLAGS "$@"
169}
170
171builder_cxxflags ()
172{
173    _builder_varadd _BUILD_CXXFLAGS "$@"
174}
175
176builder_c_includes ()
177{
178    _builder_varadd _BUILD_C_INCLUDES "$@"
179}
180
181# $1: optional var to hold the original cflags before reset
182builder_reset_cflags ()
183{
184    local _varname="$1"
185    if [ -n "$_varname" ] ; then
186        eval $_varname=\"$_BUILD_CFLAGS\"
187    fi
188    _BUILD_CFLAGS=
189}
190
191# $1: optional var to hold the original cxxflags before reset
192builder_reset_cxxflags ()
193{
194    local _varname="$1"
195    if [ -n "$_varname" ] ; then
196        eval $_varname=\"$_BUILD_CXXFLAGS\"
197    fi
198    _BUILD_CXXFLAGS=
199}
200
201# $1: optional var to hold the original c_includes before reset
202builder_reset_c_includes ()
203{
204    local _varname="$1"
205    if [ -n "$_varname" ] ; then
206        eval $_varname=\"$_BUILD_C_INCLUDES\"
207    fi
208    _BUILD_C_INCLUDES=
209}
210
211builder_link_with ()
212{
213    local LIB
214    for LIB; do
215        case $LIB in
216            *.a)
217                _builder_varadd _BUILD_STATIC_LIBRARIES $LIB
218                ;;
219            *.so)
220                _builder_varadd _BUILD_SHARED_LIBRARIES $LIB
221                ;;
222            *)
223                echo "ERROR: Unknown link library extension: $LIB"
224                exit 1
225        esac
226    done
227}
228
229builder_sources ()
230{
231    local src srcfull obj cc cflags text
232    if [ -z "$_BUILD_DIR" ]; then
233        panic "Build directory not set!"
234    fi
235    if [ -z "$_BUILD_CC" ]; then
236        _BUILD_CC=${CC:-gcc}
237    fi
238    if [ -z "$_BUILD_CXX" ]; then
239        _BUILD_CXX=${CXX:-g++}
240    fi
241    for src in "$@"; do
242        srcfull=$_BUILD_SRCDIR/$src
243        if [ ! -f "$srcfull" ]; then
244            echo "ERROR: Missing source file: $srcfull"
245            exit 1
246        fi
247        obj=$(basename "$src")
248        cflags="$_BUILD_CFLAGS"
249        for inc in $_BUILD_C_INCLUDES; do
250            cflags=$cflags" -I$inc"
251        done
252        cflags=$cflags" -I$_BUILD_SRCDIR"
253        case $obj in
254            *.c)
255                obj=${obj%%.c}
256                text="C"
257                cc=$_BUILD_CC
258                ;;
259            *.cpp)
260                obj=${obj%%.cpp}
261                text="C++"
262                cc=$_BUILD_CXX
263                cflags="$cflags $_BUILD_CXXFLAGS"
264                ;;
265            *.cc)
266                obj=${obj%%.cc}
267                text="C++"
268                cc=$_BUILD_CXX
269                cflags="$cflags $_BUILD_CXXFLAGS"
270                ;;
271            *.S|*.s)
272                obj=${obj%%.$obj}
273                text="ASM"
274                cc=$_BUILD_CC
275                ;;
276            *)
277                echo "Unknown source file extension: $obj"
278                exit 1
279                ;;
280        esac
281
282        # Ensure we have unwind tables in the generated machine code
283        # This is useful to get good stack traces
284        cflags=$cflags" -funwind-tables"
285
286        obj=$_BUILD_DIR/$obj.o
287        if [ "$_BUILD_MK" ]; then
288            echo "$obj: $srcfull" >> $_BUILD_MK
289        fi
290        builder_log "${_BUILD_PREFIX}$text: $src"
291        builder_command $NDK_CCACHE $cc -c -o "$obj" "$srcfull" $cflags
292        fail_panic "Could not compile ${_BUILD_PREFIX}$src"
293        _BUILD_OBJECTS=$_BUILD_OBJECTS" $obj"
294    done
295}
296
297builder_static_library ()
298{
299    local lib libname
300    libname=$1
301    if [ -z "$_BUILD_DSTDIR" ]; then
302        panic "Destination directory not set"
303    fi
304    lib=$_BUILD_DSTDIR/$libname
305    lib=${lib%%.a}.a
306    if [ "$_BUILD_MK" ]; then
307        _BUILD_TARGETS=$_BUILD_TARGETS" $lib"
308        echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK
309    fi
310    if [ -z "${_BUILD_AR}" ]; then
311        _BUILD_AR=${AR:-ar}
312    fi
313    builder_log "${_BUILD_PREFIX}Archive: $libname"
314    rm -f "$lib"
315    builder_command ${_BUILD_AR} crs "$lib" "$_BUILD_OBJECTS"
316    fail_panic "Could not archive ${_BUILD_PREFIX}$libname objects!"
317}
318
319builder_host_static_library ()
320{
321    local lib libname
322    libname=$1
323    if [ -z "$_BUILD_DSTDIR" ]; then
324        panic "Destination directory not set"
325    fi
326    lib=$_BUILD_DSTDIR/$libname
327    lib=${lib%%.a}.a
328    if [ "$_BUILD_MK" ]; then
329        _BUILD_TARGETS=$_BUILD_TARGETS" $lib"
330        echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK
331    fi
332    if [ -z "$BUILD_AR" ]; then
333        _BUILD_AR=${AR:-ar}
334    fi
335    builder_log "${_BUILD_PREFIX}Archive: $libname"
336    rm -f "$lib"
337    builder_command ${_BUILD_AR} crs "$lib" "$_BUILD_OBJECTS"
338    fail_panic "Could not archive ${_BUILD_PREFIX}$libname objects!"
339}
340
341builder_shared_library ()
342{
343    local lib libname
344    libname=$1
345    lib=$_BUILD_DSTDIR/$libname
346    lib=${lib%%.so}.so
347    if [ "$_BUILD_MK" ]; then
348        _BUILD_TARGETS=$_BUILD_TARGETS" $lib"
349        echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK
350    fi
351    builder_log "${_BUILD_PREFIX}SharedLibrary: $libname"
352
353    # Important: -lgcc must appear after objects and static libraries,
354    #            but before shared libraries for Android. It doesn't hurt
355    #            for other platforms.
356    builder_command ${_BUILD_CXX} \
357        -Wl,-soname,$(basename $lib) \
358        -Wl,-shared,-Bsymbolic \
359        $_BUILD_LDFLAGS_BEGIN_SO \
360        $_BUILD_OBJECTS \
361        $_BUILD_STATIC_LIBRARIES \
362        -lgcc \
363        $_BUILD_SHARED_LIBRARIES \
364        -lc -lm \
365        $_BUILD_LDFLAGS \
366        $_BUILD_LDFLAGS_END_SO \
367        -o $lib
368    fail_panic "Could not create ${_BUILD_PREFIX}shared library $libname"
369}
370
371builder_host_shared_library ()
372{
373    local lib libname
374    libname=$1
375    lib=$_BUILD_DSTDIR/$libname
376    lib=${lib%%.so}.so
377    if [ "$_BUILD_MK" ]; then
378        _BUILD_TARGETS=$_BUILD_TARGETS" $lib"
379        echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK
380    fi
381    builder_log "${_BUILD_PREFIX}SharedLibrary: $libname"
382
383    if [ -z "$_BUILD_CXX" ]; then
384        _BUILD_CXX=${CXX:-g++}
385    fi
386
387    # Important: -lgcc must appear after objects and static libraries,
388    #            but before shared libraries for Android. It doesn't hurt
389    #            for other platforms.
390    builder_command ${_BUILD_CXX} \
391        -shared -s \
392        $_BUILD_OBJECTS \
393        $_BUILD_STATIC_LIBRARIES \
394        $_BUILD_SHARED_LIBRARIES \
395        $_BUILD_LDFLAGS \
396        -o $lib
397    fail_panic "Could not create ${_BUILD_PREFIX}shared library $libname"
398}
399
400builder_host_executable ()
401{
402    local exe exename
403    exename=$1
404    exe=$_BUILD_DSTDIR/$exename$HOST_EXE
405    if [ "$_BUILD_MK" ]; then
406        _BUILD_TARGETS=$_BUILD_TARGETS" $exe"
407        echo "$exe: $_BUILD_OBJECTS" >> $_BUILD_MK
408    fi
409    builder_log "${_BUILD_PREFIX}Executable: $exename$HOST_EXE"
410
411    if [ -z "$_BUILD_CXX" ]; then
412        _BUILD_CXX=${CXX:-g++}
413    fi
414
415    # Important: -lgcc must appear after objects and static libraries,
416    #            but before shared libraries for Android. It doesn't hurt
417    #            for other platforms.
418    builder_command ${_BUILD_CXX} \
419        -s \
420        $_BUILD_OBJECTS \
421        $_BUILD_STATIC_LIBRARIES \
422        $_BUILD_SHARED_LIBRARIES \
423        $_BUILD_LDFLAGS \
424        -o $exe
425    fail_panic "Could not create ${_BUILD_PREFIX}executable $libname"
426}
427
428
429builder_end ()
430{
431    if [ "$_BUILD_MK" ]; then
432        echo "all: $_BUILD_TARGETS" >> $_BUILD_MK
433        run make -j$NUM_JOBS -f $_BUILD_MK
434        fail_panic "Could not build project!"
435    fi
436
437    if [ "$_BUILD_DIR_NEW" ]; then
438        log2 "Cleaning up build directory: $_BUILD_DIR"
439        rm -rf "$_BUILD_DIR"
440        _BUILD_DIR_NEW=
441    fi
442}
443
444# Same as builder_begin, but to target Android with a specific ABI
445# $1: ABI name (e.g. armeabi)
446# $2: Build directory
447# $3: Optional llvm version
448# $4: Optional Makefile name
449builder_begin_android ()
450{
451    local ABI BUILDDIR LLVM_VERSION MAKEFILE
452    local ARCH UNKNOWN_ARCH PLATFORM SYSROOT FLAGS
453    local CRTBEGIN_SO_O CRTEND_SO_O CRTBEGIN_EXE_SO CRTEND_SO_O
454    local BINPREFIX GCC_TOOLCHAIN LLVM_TRIPLE
455    if [ -z "$NDK_DIR" ]; then
456        panic "NDK_DIR is not defined!"
457    elif [ ! -d "$NDK_DIR/platforms" ]; then
458        panic "Missing directory: $NDK_DIR/platforms"
459    fi
460    ABI=$1
461    BUILDDIR=$2
462    LLVM_VERSION=$3
463    MAKEFILE=$4
464    ARCH=$(convert_abi_to_arch $ABI)
465    UNKNOWN_ARCH=$(find_ndk_unknown_archs | grep $ARCH)
466    PLATFORM=${2##android-}
467    SYSROOT=$NDK_DIR/platforms/android-$PLATFORM/arch-$ARCH
468
469    if [ ! -z "$UNKNOWN_ARCH" ]; then
470        LLVM_VERSION=$DEFAULT_LLVM_VERSION
471    fi
472
473    if [ -z "$LLVM_VERSION" ]; then
474        BINPREFIX=$NDK_DIR/$(get_default_toolchain_binprefix_for_arch $ARCH)
475    else
476        BINPREFIX=$NDK_DIR/$(get_llvm_toolchain_binprefix $LLVM_VERSION)
477        GCC_TOOLCHAIN=`dirname $NDK_DIR/$(get_default_toolchain_binprefix_for_arch $ARCH)`
478        GCC_TOOLCHAIN=`dirname $GCC_TOOLCHAIN`
479    fi
480
481    SYSROOT=$NDK_DIR/$(get_default_platform_sysroot_for_arch $ARCH)
482
483    CRTBEGIN_EXE_O=$SYSROOT/usr/lib/crtbegin_dynamic.o
484    CRTEND_EXE_O=$SYSROOT/usr/lib/crtend_android.o
485
486    CRTBEGIN_SO_O=$SYSROOT/usr/lib/crtbegin_so.o
487    CRTEND_SO_O=$SYSROOT/usr/lib/crtend_so.o
488    if [ ! -f "$CRTBEGIN_SO_O" ]; then
489        CRTBEGIN_SO_O=$CRTBEGIN_EXE_O
490    fi
491    if [ ! -f "$CRTEND_SO_O" ]; then
492        CRTEND_SO_O=$CRTEND_EXE_O
493    fi
494
495    builder_begin "$BUILDDIR" "$MAKEFILE"
496    builder_set_prefix "$ABI "
497    if [ -z "$LLVM_VERSION" ]; then
498        builder_set_binprefix "$BINPREFIX"
499    else
500        builder_set_binprefix_llvm "$BINPREFIX"
501        case $ABI in
502            armeabi)
503                LLVM_TRIPLE=armv5te-none-linux-androideabi
504                ;;
505            armeabi-v7a)
506                LLVM_TRIPLE=armv7-none-linux-androideabi
507                ;;
508            x86)
509                LLVM_TRIPLE=i686-none-linux-android
510                ;;
511            mips)
512                LLVM_TRIPLE=mipsel-none-linux-android
513                ;;
514            *)
515                LLVM_TRIPLE=le32-none-ndk
516                GCC_TOOLCHAIN=
517                CRTBEGIN_SO_O=
518                CRTEND_SO_O=
519                CRTBEGIN_EXE_O=
520                CRTEND_EXE_O=
521                FLAGS=-emit-llvm
522                ;;
523        esac
524        builder_cflags "-target $LLVM_TRIPLE $FLAGS"
525        builder_ldflags "-target $LLVM_TRIPLE $FLAGS"
526        if [ ! -z $GCC_TOOLCHAIN ]; then
527            builder_cflags "-gcc-toolchain $GCC_TOOLCHAIN"
528            builder_ldflags "-gcc-toolchain $GCC_TOOLCHAIN"
529        fi
530    fi
531
532    builder_cflags "--sysroot=$SYSROOT"
533    builder_cxxflags "--sysroot=$SYSROOT"
534    _BUILD_LDFLAGS_BEGIN_SO="--sysroot=$SYSROOT -nostdlib $CRTBEGIN_SO_O"
535    _BUILD_LDFLAGS_BEGIN_EXE="--sysroot=$SYSROOT -nostdlib $CRTBEGIN_EXE_O"
536
537    _BUILD_LDFLAGS_END_SO="$CRTEND_SO_O"
538    _BUILD_LDFLAGS_END_EXE="$CRTEND_EXE_O"
539
540    case $ABI in
541        armeabi)
542            builder_cflags "-mthumb"
543            ;;
544        armeabi-v7a)
545            builder_cflags "-mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16"
546            builder_ldflags "-march=armv7-a -Wl,--fix-cortex-a8"
547            ;;
548    esac
549}
550
551# $1: Build directory
552# $2: Optional Makefile name
553builder_begin_host ()
554{
555    prepare_host_build
556    builder_begin "$1" "$2"
557    builder_set_prefix "$HOST_TAG "
558}
559