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