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=$(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 297 builder_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 319 builder_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 341 builder_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 371 builder_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 400 builder_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 429 builder_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 449 builder_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 553 builder_begin_host () 554 { 555 prepare_host_build 556 builder_begin "$1" "$2" 557 builder_set_prefix "$HOST_TAG " 558 } 559