• 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        obj=$_BUILD_DIR/$obj.o
255        if [ "$_BUILD_MK" ]; then
256            echo "$obj: $srcfull" >> $_BUILD_MK
257        fi
258        builder_log "${_BUILD_PREFIX}$text: $src"
259        builder_command $NDK_CCACHE $cc -c -o "$obj" "$srcfull" $cflags
260        fail_panic "Could not compile ${_BUILD_PREFIX}$src"
261        _BUILD_OBJECTS=$_BUILD_OBJECTS" $obj"
262    done
263}
264
265builder_static_library ()
266{
267    local lib libname
268    libname=$1
269    if [ -z "$_BUILD_DSTDIR" ]; then
270        panic "Destination directory not set"
271    fi
272    lib=$_BUILD_DSTDIR/$libname
273    lib=${lib%%.a}.a
274    if [ "$_BUILD_MK" ]; then
275        _BUILD_TARGETS=$_BUILD_TARGETS" $lib"
276        echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK
277    fi
278    builder_log "${_BUILD_PREFIX}Archive: $libname"
279    builder_command ${_BUILD_BINPREFIX}ar crs "$lib" "$_BUILD_OBJECTS"
280    fail_panic "Could not archive ${_BUILD_PREFIX}$libname objects!"
281}
282
283builder_host_static_library ()
284{
285    local lib libname
286    libname=$1
287    if [ -z "$_BUILD_DSTDIR" ]; then
288        panic "Destination directory not set"
289    fi
290    lib=$_BUILD_DSTDIR/$libname
291    lib=${lib%%.a}.a
292    if [ "$_BUILD_MK" ]; then
293        _BUILD_TARGETS=$_BUILD_TARGETS" $lib"
294        echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK
295    fi
296    if [ -z "$BUILD_AR" ]; then
297        _BUILD_AR=${AR:-ar}
298    fi
299    builder_log "${_BUILD_PREFIX}Archive: $libname"
300    builder_command ${_BUILD_AR} crs "$lib" "$_BUILD_OBJECTS"
301    fail_panic "Could not archive ${_BUILD_PREFIX}$libname objects!"
302}
303
304builder_shared_library ()
305{
306    local lib libname
307    libname=$1
308    lib=$_BUILD_DSTDIR/$libname
309    lib=${lib%%.so}.so
310    if [ "$_BUILD_MK" ]; then
311        _BUILD_TARGETS=$_BUILD_TARGETS" $lib"
312        echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK
313    fi
314    builder_log "${_BUILD_PREFIX}SharedLibrary: $libname"
315
316    # Important: -lgcc must appear after objects and static libraries,
317    #            but before shared libraries for Android. It doesn't hurt
318    #            for other platforms.
319    builder_command ${_BUILD_BINPREFIX}g++ \
320        -Wl,-soname,$(basename $lib) \
321        -Wl,-shared,-Bsymbolic \
322        $_BUILD_LDFLAGS_BEGIN_SO \
323        $_BUILD_OBJECTS \
324        $_BUILD_STATIC_LIBRARIES \
325        -lgcc \
326        $_BUILD_SHARED_LIBRARIES \
327        -lc -lm \
328        $_BUILD_LDFLAGS \
329        $_BUILD_LDFLAGS_END_SO \
330        -o $lib
331    fail_panic "Could not create ${_BUILD_PREFIX}shared library $libname"
332}
333
334builder_host_shared_library ()
335{
336    local lib libname
337    libname=$1
338    lib=$_BUILD_DSTDIR/$libname
339    lib=${lib%%.so}.so
340    if [ "$_BUILD_MK" ]; then
341        _BUILD_TARGETS=$_BUILD_TARGETS" $lib"
342        echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK
343    fi
344    builder_log "${_BUILD_PREFIX}SharedLibrary: $libname"
345
346    if [ -z "$_BUILD_CXX" ]; then
347        _BUILD_CXX=${CXX:-g++}
348    fi
349
350    # Important: -lgcc must appear after objects and static libraries,
351    #            but before shared libraries for Android. It doesn't hurt
352    #            for other platforms.
353    builder_command ${_BUILD_CXX} \
354        -shared -s \
355        $_BUILD_OBJECTS \
356        $_BUILD_STATIC_LIBRARIES \
357        $_BUILD_SHARED_LIBRARIES \
358        $_BUILD_LDFLAGS \
359        -o $lib
360    fail_panic "Could not create ${_BUILD_PREFIX}shared library $libname"
361}
362
363builder_host_executable ()
364{
365    local exe exename
366    exename=$1
367    exe=$_BUILD_DSTDIR/$exename$HOST_EXE
368    if [ "$_BUILD_MK" ]; then
369        _BUILD_TARGETS=$_BUILD_TARGETS" $exe"
370        echo "$exe: $_BUILD_OBJECTS" >> $_BUILD_MK
371    fi
372    builder_log "${_BUILD_PREFIX}Executable: $exename$HOST_EXE"
373
374    if [ -z "$_BUILD_CXX" ]; then
375        _BUILD_CXX=${CXX:-g++}
376    fi
377
378    # Important: -lgcc must appear after objects and static libraries,
379    #            but before shared libraries for Android. It doesn't hurt
380    #            for other platforms.
381    builder_command ${_BUILD_CXX} \
382        -s \
383        $_BUILD_OBJECTS \
384        $_BUILD_STATIC_LIBRARIES \
385        $_BUILD_SHARED_LIBRARIES \
386        $_BUILD_LDFLAGS \
387        -o $exe
388    fail_panic "Could not create ${_BUILD_PREFIX}executable $libname"
389}
390
391
392builder_end ()
393{
394    if [ "$_BUILD_MK" ]; then
395        echo "all: $_BUILD_TARGETS" >> $_BUILD_MK
396        run make -j$NUM_JOBS -f $_BUILD_MK
397        fail_panic "Could not build project!"
398    fi
399
400    if [ "$_BUILD_DIR_NEW" ]; then
401        log2 "Cleaning up build directory: $_BUILD_DIR"
402        rm -rf "$_BUILD_DIR"
403        _BUILD_DIR_NEW=
404    fi
405}
406
407# Same as builder_begin, but to target Android with a specific ABI
408# $1: ABI name (e.g. armeabi)
409# $2: Build directory
410# $3: Optional Makefile name
411builder_begin_android ()
412{
413    local ARCH ABI PLATFORM BUILDDIR DSTDIR SYSROOT CFLAGS
414    local CRTBEGIN_SO_O CRTEND_SO_O CRTBEGIN_EXE_SO CRTEND_SO_O
415    if [ -z "$NDK_DIR" ]; then
416        panic "NDK_DIR is not defined!"
417    elif [ ! -d "$NDK_DIR/platforms" ]; then
418        panic "Missing directory: $NDK_DIR/platforms"
419    fi
420    ABI=$1
421    ARCH=$(convert_abi_to_arch $ABI)
422    PLATFORM=${2##android-}
423    SYSROOT=$NDK_DIR/platforms/android-$PLATFORM/arch-$ARCH
424
425    BINPREFIX=$NDK_DIR/$(get_default_toolchain_binprefix_for_arch $ARCH)
426    SYSROOT=$NDK_DIR/$(get_default_platform_sysroot_for_arch $ARCH)
427
428    CRTBEGIN_EXE_O=$SYSROOT/usr/lib/crtbegin_dynamic.o
429    CRTEND_EXE_O=$SYSROOT/usr/lib/crtend_android.o
430
431    CRTBEGIN_SO_O=$SYSROOT/usr/lib/crtbegin_so.o
432    CRTEND_SO_O=$SYSROOT/usr/lib/crtend_so.o
433    if [ ! -f "$CRTBEGIN_SO_O" ]; then
434        CRTBEGIN_SO_O=$CRTBEGIN_EXE_O
435    fi
436    if [ ! -f "$CRTEND_SO_O" ]; then
437        CRTEND_SO_O=$CRTEND_EXE_O
438    fi
439
440    builder_begin "$2" "$3"
441    builder_set_prefix "$ABI "
442    builder_set_binprefix "$BINPREFIX"
443
444    builder_cflags "--sysroot=$SYSROOT"
445    builder_cxxflags "--sysroot=$SYSROOT"
446    _BUILD_LDFLAGS_BEGIN_SO="--sysroot=$SYSROOT -nostdlib $CRTBEGIN_SO_O"
447    _BUILD_LDFLAGS_BEGIN_EXE="--sysroot=$SYSROOT -nostdlib $CRTBEGIN_EXE_O"
448
449    _BUILD_LDFLAGS_END_SO="$CRTEND_SO_O"
450    _BUILD_LDFLAGS_END_EXE="$CRTEND_EXE_O"
451
452    case $ABI in
453        armeabi)
454            builder_cflags "-mthumb"
455            ;;
456        armeabi-v7a)
457            builder_cflags "-mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16"
458            builder_ldflags "-Wl,--fix-cortex-a8"
459            ;;
460        mips)
461            builder_ldflags "-Wl,-T,$NDK_DIR/toolchains/mipsel-linux-android-4.4.3/mipself.xsc"
462            ;;
463    esac
464}
465
466# $1: Build directory
467# $2: Optional Makefile name
468builder_begin_host ()
469{
470    prepare_host_build
471    builder_begin "$1" "$2"
472    builder_set_prefix "$HOST_TAG "
473}
474