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