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