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 23 builder_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 36 builder_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 47 builder_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 100 builder_set_prefix () 101 { 102 _BUILD_PREFIX="$@" 103 } 104 105 builder_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 126 builder_set_binprefix () 127 { 128 _BUILD_BINPREFIX=$1 129 _BUILD_CC=${1}gcc 130 _BUILD_CXX=${1}g++ 131 _BUILD_AR=${1}ar 132 } 133 134 builder_set_binprefix_llvm () 135 { 136 _BUILD_BINPREFIX=$1 137 _BUILD_CC=${1}clang 138 _BUILD_CXX=${1}clang++ 139 } 140 141 builder_set_builddir () 142 { 143 _BUILD_DIR=$1 144 } 145 146 builder_set_srcdir () 147 { 148 _BUILD_SRCDIR=$1 149 } 150 151 builder_set_dstdir () 152 { 153 _BUILD_DSTDIR=$1 154 } 155 156 builder_ldflags () 157 { 158 _builder_varadd _BUILD_LDFLAGS "$@" 159 } 160 161 builder_ldflags_exe () 162 { 163 _builder_varadd _BUILD_LDFLAGS_EXE "$@" 164 } 165 166 builder_cflags () 167 { 168 _builder_varadd _BUILD_CFLAGS "$@" 169 } 170 171 builder_cxxflags () 172 { 173 _builder_varadd _BUILD_CXXFLAGS "$@" 174 } 175 176 builder_c_includes () 177 { 178 _builder_varadd _BUILD_C_INCLUDES "$@" 179 } 180 181 # $1: optional var to hold the original cflags before reset 182 builder_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 192 builder_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 202 builder_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 211 builder_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 229 builder_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=$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 # Source file path can include ../ path items, ensure 283 # that the generated object do not back up the output 284 # directory by translating them to __/ 285 obj=$(echo "$obj" | tr '../' '__/') 286 287 # Ensure we have unwind tables in the generated machine code 288 # This is useful to get good stack traces 289 cflags=$cflags" -funwind-tables" 290 291 obj=$_BUILD_DIR/$obj.o 292 if [ "$_BUILD_MK" ]; then 293 echo "$obj: $srcfull" >> $_BUILD_MK 294 fi 295 builder_log "${_BUILD_PREFIX}$text: $src" 296 builder_command mkdir -p $(dirname "$obj") 297 builder_command $NDK_CCACHE $cc -c -o "$obj" "$srcfull" $cflags 298 fail_panic "Could not compile ${_BUILD_PREFIX}$src" 299 _BUILD_OBJECTS=$_BUILD_OBJECTS" $obj" 300 done 301 } 302 303 builder_static_library () 304 { 305 local lib libname 306 libname=$1 307 if [ -z "$_BUILD_DSTDIR" ]; then 308 panic "Destination directory not set" 309 fi 310 lib=$_BUILD_DSTDIR/$libname 311 lib=${lib%%.a}.a 312 if [ "$_BUILD_MK" ]; then 313 _BUILD_TARGETS=$_BUILD_TARGETS" $lib" 314 echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK 315 fi 316 if [ -z "${_BUILD_AR}" ]; then 317 _BUILD_AR=${AR:-ar} 318 fi 319 builder_log "${_BUILD_PREFIX}Archive: $libname" 320 rm -f "$lib" 321 builder_command ${_BUILD_AR} crs "$lib" "$_BUILD_OBJECTS" 322 fail_panic "Could not archive ${_BUILD_PREFIX}$libname objects!" 323 } 324 325 builder_host_static_library () 326 { 327 local lib libname 328 libname=$1 329 if [ -z "$_BUILD_DSTDIR" ]; then 330 panic "Destination directory not set" 331 fi 332 lib=$_BUILD_DSTDIR/$libname 333 lib=${lib%%.a}.a 334 if [ "$_BUILD_MK" ]; then 335 _BUILD_TARGETS=$_BUILD_TARGETS" $lib" 336 echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK 337 fi 338 if [ -z "$BUILD_AR" ]; then 339 _BUILD_AR=${AR:-ar} 340 fi 341 builder_log "${_BUILD_PREFIX}Archive: $libname" 342 rm -f "$lib" 343 builder_command ${_BUILD_AR} crs "$lib" "$_BUILD_OBJECTS" 344 fail_panic "Could not archive ${_BUILD_PREFIX}$libname objects!" 345 } 346 347 builder_shared_library () 348 { 349 local lib libname 350 libname=$1 351 lib=$_BUILD_DSTDIR/$libname 352 lib=${lib%%.so}.so 353 if [ "$_BUILD_MK" ]; then 354 _BUILD_TARGETS=$_BUILD_TARGETS" $lib" 355 echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK 356 fi 357 builder_log "${_BUILD_PREFIX}SharedLibrary: $libname" 358 359 # Important: -lgcc must appear after objects and static libraries, 360 # but before shared libraries for Android. It doesn't hurt 361 # for other platforms. 362 builder_command ${_BUILD_CXX} \ 363 -Wl,-soname,$(basename $lib) \ 364 -Wl,-shared,-Bsymbolic \ 365 $_BUILD_LDFLAGS_BEGIN_SO \ 366 $_BUILD_OBJECTS \ 367 $_BUILD_STATIC_LIBRARIES \ 368 -lgcc \ 369 $_BUILD_SHARED_LIBRARIES \ 370 -lc -lm \ 371 $_BUILD_LDFLAGS \ 372 $_BUILD_LDFLAGS_END_SO \ 373 -o $lib 374 fail_panic "Could not create ${_BUILD_PREFIX}shared library $libname" 375 } 376 377 # Same as builder_shared_library, but do not link the default libs 378 builder_nostdlib_shared_library () 379 { 380 local lib libname 381 libname=$1 382 lib=$_BUILD_DSTDIR/$libname 383 lib=${lib%%.so}.so 384 if [ "$_BUILD_MK" ]; then 385 _BUILD_TARGETS=$_BUILD_TARGETS" $lib" 386 echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK 387 fi 388 builder_log "${_BUILD_PREFIX}SharedLibrary: $libname" 389 390 builder_command ${_BUILD_CXX} \ 391 -Wl,-soname,$(basename $lib) \ 392 -Wl,-shared,-Bsymbolic \ 393 $_BUILD_LDFLAGS_BEGIN_SO \ 394 $_BUILD_OBJECTS \ 395 $_BUILD_STATIC_LIBRARIES \ 396 $_BUILD_SHARED_LIBRARIES \ 397 $_BUILD_LDFLAGS \ 398 $_BUILD_LDFLAGS_END_SO \ 399 -o $lib 400 fail_panic "Could not create ${_BUILD_PREFIX}shared library $libname" 401 } 402 403 builder_host_shared_library () 404 { 405 local lib libname 406 libname=$1 407 lib=$_BUILD_DSTDIR/$libname 408 lib=${lib%%.so}.so 409 if [ "$_BUILD_MK" ]; then 410 _BUILD_TARGETS=$_BUILD_TARGETS" $lib" 411 echo "$lib: $_BUILD_OBJECTS" >> $_BUILD_MK 412 fi 413 builder_log "${_BUILD_PREFIX}SharedLibrary: $libname" 414 415 if [ -z "$_BUILD_CXX" ]; then 416 _BUILD_CXX=${CXX:-g++} 417 fi 418 419 # Important: -lgcc must appear after objects and static libraries, 420 # but before shared libraries for Android. It doesn't hurt 421 # for other platforms. 422 builder_command ${_BUILD_CXX} \ 423 -shared -s \ 424 $_BUILD_OBJECTS \ 425 $_BUILD_STATIC_LIBRARIES \ 426 $_BUILD_SHARED_LIBRARIES \ 427 $_BUILD_LDFLAGS \ 428 -o $lib 429 fail_panic "Could not create ${_BUILD_PREFIX}shared library $libname" 430 } 431 432 builder_host_executable () 433 { 434 local exe exename 435 exename=$1 436 exe=$_BUILD_DSTDIR/$exename$HOST_EXE 437 if [ "$_BUILD_MK" ]; then 438 _BUILD_TARGETS=$_BUILD_TARGETS" $exe" 439 echo "$exe: $_BUILD_OBJECTS" >> $_BUILD_MK 440 fi 441 builder_log "${_BUILD_PREFIX}Executable: $exename$HOST_EXE" 442 443 if [ -z "$_BUILD_CXX" ]; then 444 _BUILD_CXX=${CXX:-g++} 445 fi 446 447 # Important: -lgcc must appear after objects and static libraries, 448 # but before shared libraries for Android. It doesn't hurt 449 # for other platforms. 450 builder_command ${_BUILD_CXX} \ 451 -s \ 452 $_BUILD_OBJECTS \ 453 $_BUILD_STATIC_LIBRARIES \ 454 $_BUILD_SHARED_LIBRARIES \ 455 $_BUILD_LDFLAGS \ 456 -o $exe 457 fail_panic "Could not create ${_BUILD_PREFIX}executable $libname" 458 } 459 460 461 builder_end () 462 { 463 if [ "$_BUILD_MK" ]; then 464 echo "all: $_BUILD_TARGETS" >> $_BUILD_MK 465 run make -j$NUM_JOBS -f $_BUILD_MK 466 fail_panic "Could not build project!" 467 fi 468 469 if [ "$_BUILD_DIR_NEW" ]; then 470 log2 "Cleaning up build directory: $_BUILD_DIR" 471 rm -rf "$_BUILD_DIR" 472 _BUILD_DIR_NEW= 473 fi 474 } 475 476 # Same as builder_begin, but to target Android with a specific ABI 477 # $1: ABI name (e.g. armeabi) 478 # $2: Build directory 479 # $3: Gcc version 480 # $4: Optional llvm version 481 # $5: Optional Makefile name 482 builder_begin_android () 483 { 484 local ABI BUILDDIR LLVM_VERSION MAKEFILE 485 local ARCH PLATFORM SYSROOT FLAGS 486 local CRTBEGIN_SO_O CRTEND_SO_O CRTBEGIN_EXE_SO CRTEND_SO_O 487 local BINPREFIX GCC_TOOLCHAIN LLVM_TRIPLE 488 if [ -z "$NDK_DIR" ]; then 489 panic "NDK_DIR is not defined!" 490 elif [ ! -d "$NDK_DIR/platforms" ]; then 491 panic "Missing directory: $NDK_DIR/platforms" 492 fi 493 ABI=$1 494 BUILDDIR=$2 495 GCC_VERSION=$3 496 LLVM_VERSION=$4 497 MAKEFILE=$5 498 ARCH=$(convert_abi_to_arch $ABI) 499 PLATFORM=${2##android-} 500 SYSROOT=$NDK_DIR/platforms/android-$PLATFORM/arch-$ARCH 501 502 if [ "$(arch_in_unknown_archs $ARCH)" = "yes" ]; then 503 LLVM_VERSION=$DEFAULT_LLVM_VERSION 504 fi 505 506 if [ -z "$LLVM_VERSION" ]; then 507 BINPREFIX=$NDK_DIR/$(get_toolchain_binprefix_for_arch $ARCH $GCC_VERSION) 508 else 509 BINPREFIX=$NDK_DIR/$(get_llvm_toolchain_binprefix $LLVM_VERSION) 510 GCC_TOOLCHAIN=`dirname $NDK_DIR/$(get_toolchain_binprefix_for_arch $ARCH $GCC_VERSION)` 511 GCC_TOOLCHAIN=`dirname $GCC_TOOLCHAIN` 512 fi 513 514 SYSROOT=$NDK_DIR/$(get_default_platform_sysroot_for_arch $ARCH) 515 516 CRTBEGIN_EXE_O=$SYSROOT/usr/lib/crtbegin_dynamic.o 517 CRTEND_EXE_O=$SYSROOT/usr/lib/crtend_android.o 518 519 CRTBEGIN_SO_O=$SYSROOT/usr/lib/crtbegin_so.o 520 CRTEND_SO_O=$SYSROOT/usr/lib/crtend_so.o 521 if [ ! -f "$CRTBEGIN_SO_O" ]; then 522 CRTBEGIN_SO_O=$CRTBEGIN_EXE_O 523 fi 524 if [ ! -f "$CRTEND_SO_O" ]; then 525 CRTEND_SO_O=$CRTEND_EXE_O 526 fi 527 528 builder_begin "$BUILDDIR" "$MAKEFILE" 529 builder_set_prefix "$ABI " 530 if [ -z "$LLVM_VERSION" ]; then 531 builder_set_binprefix "$BINPREFIX" 532 else 533 builder_set_binprefix_llvm "$BINPREFIX" 534 case $ABI in 535 armeabi) 536 LLVM_TRIPLE=armv5te-none-linux-androideabi 537 ;; 538 armeabi-v7a) 539 LLVM_TRIPLE=armv7-none-linux-androideabi 540 ;; 541 x86) 542 LLVM_TRIPLE=i686-none-linux-android 543 ;; 544 mips) 545 LLVM_TRIPLE=mipsel-none-linux-android 546 ;; 547 *) 548 LLVM_TRIPLE=le32-none-ndk 549 GCC_TOOLCHAIN= 550 CRTBEGIN_SO_O= 551 CRTEND_SO_O= 552 CRTBEGIN_EXE_O= 553 CRTEND_EXE_O= 554 FLAGS=-emit-llvm 555 ;; 556 esac 557 builder_cflags "-target $LLVM_TRIPLE $FLAGS" 558 builder_ldflags "-target $LLVM_TRIPLE $FLAGS" 559 if [ ! -z $GCC_TOOLCHAIN ]; then 560 builder_cflags "-gcc-toolchain $GCC_TOOLCHAIN" 561 builder_ldflags "-gcc-toolchain $GCC_TOOLCHAIN" 562 fi 563 fi 564 565 builder_cflags "--sysroot=$SYSROOT" 566 builder_cxxflags "--sysroot=$SYSROOT" 567 _BUILD_LDFLAGS_BEGIN_SO="--sysroot=$SYSROOT -nostdlib $CRTBEGIN_SO_O" 568 _BUILD_LDFLAGS_BEGIN_EXE="--sysroot=$SYSROOT -nostdlib $CRTBEGIN_EXE_O" 569 570 _BUILD_LDFLAGS_END_SO="$CRTEND_SO_O" 571 _BUILD_LDFLAGS_END_EXE="$CRTEND_EXE_O" 572 573 case $ABI in 574 armeabi) 575 # add -minline-thumb1-jumptable such that gabi++/stlport/libc++ can be linked 576 # with compiler-rt where helpers __gnu_thumb1_case_* (in libgcc.a) don't exist 577 builder_cflags "-mthumb -minline-thumb1-jumptable" 578 ;; 579 armeabi-v7a) 580 builder_cflags "-mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16" 581 builder_ldflags "-march=armv7-a -Wl,--fix-cortex-a8" 582 ;; 583 esac 584 } 585 586 # $1: Build directory 587 # $2: Optional Makefile name 588 builder_begin_host () 589 { 590 prepare_host_build 591 builder_begin "$1" "$2" 592 builder_set_prefix "$HOST_TAG " 593 } 594