• 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_builddir ()
135{
136    _BUILD_DIR=$1
137}
138
139builder_set_srcdir ()
140{
141    _BUILD_SRCDIR=$1
142}
143
144builder_set_dstdir ()
145{
146    _BUILD_DSTDIR=$1
147}
148
149builder_ldflags ()
150{
151    _builder_varadd _BUILD_LDFLAGS "$@"
152}
153
154builder_ldflags_exe ()
155{
156    _builder_varadd _BUILD_LDFLAGS_EXE "$@"
157}
158
159builder_cflags ()
160{
161    _builder_varadd _BUILD_CFLAGS "$@"
162}
163
164builder_cxxflags ()
165{
166    _builder_varadd _BUILD_CXXFLAGS "$@"
167}
168
169builder_c_includes ()
170{
171    _builder_varadd _BUILD_C_INCLUDES "$@"
172}
173
174builder_reset_cflags ()
175{
176    _BUILD_CFLAGS=
177}
178
179builder_reset_cxxflags ()
180{
181    _BUILD_CXXFLAGS=
182}
183
184builder_reset_c_includes ()
185{
186    _BUILD_C_INCLUDES=
187}
188
189builder_link_with ()
190{
191    local LIB
192    for LIB; do
193        case $LIB in
194            *.a)
195                _builder_varadd _BUILD_STATIC_LIBRARIES $LIB
196                ;;
197            *.so)
198                _builder_varadd _BUILD_SHARED_LIBRARIES $LIB
199                ;;
200            *)
201                echo "ERROR: Unknown link library extension: $LIB"
202                exit 1
203        esac
204    done
205}
206
207builder_sources ()
208{
209    local src srcfull obj cc cflags text
210    if [ -z "$_BUILD_DIR" ]; then
211        panic "Build directory not set!"
212    fi
213    if [ -z "$_BUILD_CC" ]; then
214        _BUILD_CC=${CC:-gcc}
215    fi
216    if [ -z "$_BUILD_CXX" ]; then
217        _BUILD_CXX=${CXX:-g++}
218    fi
219    for src in "$@"; do
220        srcfull=$_BUILD_SRCDIR/$src
221        if [ ! -f "$srcfull" ]; then
222            echo "ERROR: Missing source file: $srcfull"
223            exit 1
224        fi
225        obj=$(basename "$src")
226        cflags="$_BUILD_CFLAGS"
227        for inc in $_BUILD_C_INCLUDES; do
228            cflags=$cflags" -I$inc"
229        done
230        cflags=$cflags" -I$_BUILD_SRCDIR"
231        case $obj in
232            *.c)
233                obj=${obj%%.c}
234                text="C"
235                cc=$_BUILD_CC
236                ;;
237            *.cpp)
238                obj=${obj%%.cpp}
239                text="C++"
240                cc=$_BUILD_CXX
241                cflags="$cflags $_BUILD_CXXFLAGS"
242                ;;
243            *.cc)
244                obj=${obj%%.cc}
245                text="C++"
246                cc=$_BUILD_CXX
247                cflags="$cflags $_BUILD_CXXFLAGS"
248                ;;
249            *)
250                echo "Unknown source file extension: $obj"
251                exit 1
252                ;;
253        esac
254
255        # Ensure we have unwind tables in the generated machine code
256        # This is useful to get good stack traces
257        cflags=$cflags" -funwind-tables"
258
259        obj=$_BUILD_DIR/$obj.o
260        if [ "$_BUILD_MK" ]; then
261            echo "$obj: $srcfull" >> $_BUILD_MK
262        fi
263        builder_log "${_BUILD_PREFIX}$text: $src"
264        builder_command $NDK_CCACHE $cc -c -o "$obj" "$srcfull" $cflags
265        fail_panic "Could not compile ${_BUILD_PREFIX}$src"
266        _BUILD_OBJECTS=$_BUILD_OBJECTS" $obj"
267    done
268}
269
270builder_static_library ()
271{
272    local lib libname
273    libname=$1
274    if [ -z "$_BUILD_DSTDIR" ]; then
275        panic "Destination directory not set"
276    fi
277    lib=$_BUILD_DSTDIR/$libname
278    lib=${lib%%.a}.a
279    if [ "$_BUILD_MK" ]; then
280        _BUILD_TARGETS=$_BUILD_TARGETS" $lib"
281        echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK
282    fi
283    builder_log "${_BUILD_PREFIX}Archive: $libname"
284    builder_command ${_BUILD_BINPREFIX}ar crs "$lib" "$_BUILD_OBJECTS"
285    fail_panic "Could not archive ${_BUILD_PREFIX}$libname objects!"
286}
287
288builder_host_static_library ()
289{
290    local lib libname
291    libname=$1
292    if [ -z "$_BUILD_DSTDIR" ]; then
293        panic "Destination directory not set"
294    fi
295    lib=$_BUILD_DSTDIR/$libname
296    lib=${lib%%.a}.a
297    if [ "$_BUILD_MK" ]; then
298        _BUILD_TARGETS=$_BUILD_TARGETS" $lib"
299        echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK
300    fi
301    if [ -z "$BUILD_AR" ]; then
302        _BUILD_AR=${AR:-ar}
303    fi
304    builder_log "${_BUILD_PREFIX}Archive: $libname"
305    builder_command ${_BUILD_AR} crs "$lib" "$_BUILD_OBJECTS"
306    fail_panic "Could not archive ${_BUILD_PREFIX}$libname objects!"
307}
308
309builder_shared_library ()
310{
311    local lib libname
312    libname=$1
313    lib=$_BUILD_DSTDIR/$libname
314    lib=${lib%%.so}.so
315    if [ "$_BUILD_MK" ]; then
316        _BUILD_TARGETS=$_BUILD_TARGETS" $lib"
317        echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK
318    fi
319    builder_log "${_BUILD_PREFIX}SharedLibrary: $libname"
320
321    # Important: -lgcc must appear after objects and static libraries,
322    #            but before shared libraries for Android. It doesn't hurt
323    #            for other platforms.
324    builder_command ${_BUILD_BINPREFIX}g++ \
325        -Wl,-soname,$(basename $lib) \
326        -Wl,-shared,-Bsymbolic \
327        $_BUILD_LDFLAGS_BEGIN_SO \
328        $_BUILD_OBJECTS \
329        $_BUILD_STATIC_LIBRARIES \
330        -lgcc \
331        $_BUILD_SHARED_LIBRARIES \
332        -lc -lm \
333        $_BUILD_LDFLAGS \
334        $_BUILD_LDFLAGS_END_SO \
335        -o $lib
336    fail_panic "Could not create ${_BUILD_PREFIX}shared library $libname"
337}
338
339builder_host_shared_library ()
340{
341    local lib libname
342    libname=$1
343    lib=$_BUILD_DSTDIR/$libname
344    lib=${lib%%.so}.so
345    if [ "$_BUILD_MK" ]; then
346        _BUILD_TARGETS=$_BUILD_TARGETS" $lib"
347        echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK
348    fi
349    builder_log "${_BUILD_PREFIX}SharedLibrary: $libname"
350
351    if [ -z "$_BUILD_CXX" ]; then
352        _BUILD_CXX=${CXX:-g++}
353    fi
354
355    # Important: -lgcc must appear after objects and static libraries,
356    #            but before shared libraries for Android. It doesn't hurt
357    #            for other platforms.
358    builder_command ${_BUILD_CXX} \
359        -shared -s \
360        $_BUILD_OBJECTS \
361        $_BUILD_STATIC_LIBRARIES \
362        $_BUILD_SHARED_LIBRARIES \
363        $_BUILD_LDFLAGS \
364        -o $lib
365    fail_panic "Could not create ${_BUILD_PREFIX}shared library $libname"
366}
367
368builder_host_executable ()
369{
370    local exe exename
371    exename=$1
372    exe=$_BUILD_DSTDIR/$exename$HOST_EXE
373    if [ "$_BUILD_MK" ]; then
374        _BUILD_TARGETS=$_BUILD_TARGETS" $exe"
375        echo "$exe: $_BUILD_OBJECTS" >> $_BUILD_MK
376    fi
377    builder_log "${_BUILD_PREFIX}Executable: $exename$HOST_EXE"
378
379    if [ -z "$_BUILD_CXX" ]; then
380        _BUILD_CXX=${CXX:-g++}
381    fi
382
383    # Important: -lgcc must appear after objects and static libraries,
384    #            but before shared libraries for Android. It doesn't hurt
385    #            for other platforms.
386    builder_command ${_BUILD_CXX} \
387        -s \
388        $_BUILD_OBJECTS \
389        $_BUILD_STATIC_LIBRARIES \
390        $_BUILD_SHARED_LIBRARIES \
391        $_BUILD_LDFLAGS \
392        -o $exe
393    fail_panic "Could not create ${_BUILD_PREFIX}executable $libname"
394}
395
396
397builder_end ()
398{
399    if [ "$_BUILD_MK" ]; then
400        echo "all: $_BUILD_TARGETS" >> $_BUILD_MK
401        run make -j$NUM_JOBS -f $_BUILD_MK
402        fail_panic "Could not build project!"
403    fi
404
405    if [ "$_BUILD_DIR_NEW" ]; then
406        log2 "Cleaning up build directory: $_BUILD_DIR"
407        rm -rf "$_BUILD_DIR"
408        _BUILD_DIR_NEW=
409    fi
410}
411
412# Same as builder_begin, but to target Android with a specific ABI
413# $1: ABI name (e.g. armeabi)
414# $2: Build directory
415# $3: Optional Makefile name
416builder_begin_android ()
417{
418    local ARCH ABI PLATFORM BUILDDIR DSTDIR SYSROOT CFLAGS
419    local CRTBEGIN_SO_O CRTEND_SO_O CRTBEGIN_EXE_SO CRTEND_SO_O
420    if [ -z "$NDK_DIR" ]; then
421        panic "NDK_DIR is not defined!"
422    elif [ ! -d "$NDK_DIR/platforms" ]; then
423        panic "Missing directory: $NDK_DIR/platforms"
424    fi
425    ABI=$1
426    ARCH=$(convert_abi_to_arch $ABI)
427    PLATFORM=${2##android-}
428    SYSROOT=$NDK_DIR/platforms/android-$PLATFORM/arch-$ARCH
429
430    BINPREFIX=$NDK_DIR/$(get_default_toolchain_binprefix_for_arch $ARCH)
431    SYSROOT=$NDK_DIR/$(get_default_platform_sysroot_for_arch $ARCH)
432
433    CRTBEGIN_EXE_O=$SYSROOT/usr/lib/crtbegin_dynamic.o
434    CRTEND_EXE_O=$SYSROOT/usr/lib/crtend_android.o
435
436    CRTBEGIN_SO_O=$SYSROOT/usr/lib/crtbegin_so.o
437    CRTEND_SO_O=$SYSROOT/usr/lib/crtend_so.o
438    if [ ! -f "$CRTBEGIN_SO_O" ]; then
439        CRTBEGIN_SO_O=$CRTBEGIN_EXE_O
440    fi
441    if [ ! -f "$CRTEND_SO_O" ]; then
442        CRTEND_SO_O=$CRTEND_EXE_O
443    fi
444
445    builder_begin "$2" "$3"
446    builder_set_prefix "$ABI "
447    builder_set_binprefix "$BINPREFIX"
448
449    builder_cflags "--sysroot=$SYSROOT"
450    builder_cxxflags "--sysroot=$SYSROOT"
451    _BUILD_LDFLAGS_BEGIN_SO="--sysroot=$SYSROOT -nostdlib $CRTBEGIN_SO_O"
452    _BUILD_LDFLAGS_BEGIN_EXE="--sysroot=$SYSROOT -nostdlib $CRTBEGIN_EXE_O"
453
454    _BUILD_LDFLAGS_END_SO="$CRTEND_SO_O"
455    _BUILD_LDFLAGS_END_EXE="$CRTEND_EXE_O"
456
457    case $ABI in
458        armeabi)
459            builder_cflags "-mthumb"
460            ;;
461        armeabi-v7a)
462            builder_cflags "-mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16"
463            builder_ldflags "-Wl,--fix-cortex-a8"
464            ;;
465    esac
466}
467
468# $1: Build directory
469# $2: Optional Makefile name
470builder_begin_host ()
471{
472    prepare_host_build
473    builder_begin "$1" "$2"
474    builder_set_prefix "$HOST_TAG "
475}
476