1 # Copyright (C) 2009 The Android Open Source Project 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 # 15 16 # A collection of shell function definitions used by various build scripts 17 # in the Android NDK (Native Development Kit) 18 # 19 20 # Get current script name into PROGNAME 21 PROGNAME=`basename $0` 22 23 # Find the Android NDK root, assuming we are invoked from a script 24 # within its directory structure. 25 # 26 # $1: Variable name that will receive the path 27 # $2: Path of invoking script 28 find_ndk_root () 29 { 30 # Try to auto-detect the NDK root by walking up the directory 31 # path to the current script. 32 local PROGDIR="`dirname \"$2\"`" 33 while [ -n "1" ] ; do 34 if [ -d "$PROGDIR/build/core" ] ; then 35 break 36 fi 37 if [ -z "$PROGDIR" -o "$PROGDIR" = '/' ] ; then 38 return 1 39 fi 40 PROGDIR="`cd \"$PROGDIR/..\" && pwd`" 41 done 42 eval $1="$PROGDIR" 43 } 44 45 # Put location of Android NDK into ANDROID_NDK_ROOT and 46 # perform a tiny amount of sanity check 47 # 48 if [ -z "$ANDROID_NDK_ROOT" ] ; then 49 find_ndk_root ANDROID_NDK_ROOT "$0" 50 if [ $? != 0 ]; then 51 echo "Please define ANDROID_NDK_ROOT to point to the root of your" 52 echo "Android NDK installation." 53 exit 1 54 fi 55 fi 56 57 echo "$ANDROID_NDK_ROOT" | grep -q -e " " 58 if [ $? = 0 ] ; then 59 echo "ERROR: The Android NDK installation path contains a space !" 60 echo "Please install to a different location." 61 exit 1 62 fi 63 64 if [ ! -d $ANDROID_NDK_ROOT ] ; then 65 echo "ERROR: Your ANDROID_NDK_ROOT variable does not point to a directory." 66 exit 1 67 fi 68 69 if [ ! -f $ANDROID_NDK_ROOT/build/tools/ndk-common.sh ] ; then 70 echo "ERROR: Your ANDROID_NDK_ROOT variable does not point to a valid directory." 71 exit 1 72 fi 73 74 ## Logging support 75 ## 76 VERBOSE=${VERBOSE-yes} 77 VERBOSE2=${VERBOSE2-no} 78 79 80 # If NDK_LOGFILE is defined in the environment, use this as the log file 81 TMPLOG= 82 if [ -n "$NDK_LOGFILE" ] ; then 83 mkdir -p `dirname "$NDK_LOGFILE"` && touch "$NDK_LOGFILE" 84 TMPLOG="$NDK_LOGFILE" 85 fi 86 87 # Setup a log file where all log() and log2() output will be sent 88 # 89 # $1: log file path (optional) 90 # 91 setup_default_log_file () 92 { 93 if [ -n "$NDK_LOGFILE" ] ; then 94 return 95 fi 96 if [ -n "$1" ] ; then 97 NDK_LOGFILE="$1" 98 else 99 NDK_LOGFILE=/tmp/ndk-log-$$.txt 100 fi 101 export NDK_LOGFILE 102 TMPLOG="$NDK_LOGFILE" 103 rm -rf "$TMPLOG" && mkdir -p `dirname "$TMPLOG"` && touch "$TMPLOG" 104 echo "To follow build in another terminal, please use: tail -F $TMPLOG" 105 } 106 107 dump () 108 { 109 if [ -n "$TMPLOG" ] ; then 110 echo "$@" >> $TMPLOG 111 fi 112 echo "$@" 113 } 114 115 dump_n () 116 { 117 if [ -n "$TMPLOG" ] ; then 118 printf %s "$@" >> $TMPLOG 119 fi 120 printf %s "$@" 121 } 122 123 log () 124 { 125 if [ "$VERBOSE" = "yes" ] ; then 126 echo "$@" 127 else 128 if [ -n "$TMPLOG" ] ; then 129 echo "$@" >> $TMPLOG 130 fi 131 fi 132 } 133 134 log_n () 135 { 136 if [ "$VERBOSE" = "yes" ] ; then 137 printf %s "$@" 138 else 139 if [ -n "$TMPLOG" ] ; then 140 printf %s "$@" >> $TMPLOG 141 fi 142 fi 143 } 144 145 log2 () 146 { 147 if [ "$VERBOSE2" = "yes" ] ; then 148 echo "$@" 149 else 150 if [ -n "$TMPLOG" ] ; then 151 echo "$@" >> $TMPLOG 152 fi 153 fi 154 } 155 156 run () 157 { 158 if [ "$VERBOSE" = "yes" ] ; then 159 echo "## COMMAND: $@" 160 "$@" 2>&1 161 else 162 if [ -n "$TMPLOG" ] ; then 163 echo "## COMMAND: $@" >> $TMPLOG 164 "$@" >>$TMPLOG 2>&1 165 else 166 "$@" > /dev/null 2>&1 167 fi 168 fi 169 } 170 171 run2 () 172 { 173 if [ "$VERBOSE2" = "yes" ] ; then 174 echo "## COMMAND: $@" 175 "$@" 2>&1 176 elif [ "$VERBOSE" = "yes" ]; then 177 echo "## COMMAND: $@" 178 if [ -n "$TMPLOG" ]; then 179 echo "## COMMAND: $@" >> $TMPLOG 180 "$@" >>$TMPLOG 2>&1 181 else 182 "$@" > /dev/null 2>&1 183 fi 184 else 185 if [ -n "$TMPLOG" ]; then 186 "$@" >>$TMPLOG 2>&1 187 else 188 "$@" > /dev/null 2>&1 189 fi 190 fi 191 } 192 193 panic () 194 { 195 dump "ERROR: $@" 196 exit 1 197 } 198 199 fail_panic () 200 { 201 if [ $? != 0 ] ; then 202 dump "ERROR: $@" 203 exit 1 204 fi 205 } 206 207 fail_warning () 208 { 209 if [ $? != 0 ] ; then 210 dump "WARNING: $@" 211 fi 212 } 213 214 215 ## Utilities 216 ## 217 218 # Return the value of a given named variable 219 # $1: variable name 220 # 221 # example: 222 # FOO=BAR 223 # BAR=ZOO 224 # echo `var_value $FOO` 225 # will print 'ZOO' 226 # 227 var_value () 228 { 229 # find a better way to do that ? 230 eval echo "$`echo $1`" 231 } 232 233 # convert to uppercase 234 # assumes tr is installed on the platform ? 235 # 236 to_uppercase () 237 { 238 echo $1 | tr "[:lower:]" "[:upper:]" 239 } 240 241 ## First, we need to detect the HOST CPU, because proper HOST_ARCH detection 242 ## requires platform-specific tricks. 243 ## 244 HOST_EXE="" 245 HOST_OS=`uname -s` 246 case "$HOST_OS" in 247 Darwin) 248 HOST_OS=darwin 249 ;; 250 Linux) 251 # note that building 32-bit binaries on x86_64 is handled later 252 HOST_OS=linux 253 ;; 254 FreeBsd) # note: this is not tested 255 HOST_OS=freebsd 256 ;; 257 CYGWIN*|*_NT-*) 258 HOST_OS=windows 259 HOST_EXE=.exe 260 if [ "x$OSTYPE" = xcygwin ] ; then 261 HOST_OS=cygwin 262 fi 263 ;; 264 esac 265 266 log2 "HOST_OS=$HOST_OS" 267 log2 "HOST_EXE=$HOST_EXE" 268 269 ## Now find the host architecture. This must correspond to the bitness of 270 ## the binaries we're going to run with this NDK. Certain platforms allow 271 ## you to use a 64-bit kernel with a 32-bit userland, and unfortunately 272 ## commands like 'uname -m' only report the kernel bitness. 273 ## 274 HOST_ARCH=`uname -m` 275 case "$HOST_ARCH" in 276 i?86) HOST_ARCH=x86 277 # "uname -m" reports i386 on Snow Leopard even though its architecture is 278 # 64-bit. In order to use it to build 64-bit toolchains we need to fix the 279 # reporting anomoly here. 280 if [ "$HOST_OS" = darwin ] ; then 281 if ! echo __LP64__ | (CCOPTS= gcc -E - 2>/dev/null) | grep -q __LP64__ ; then 282 # or if gcc -dM -E - < /dev/null | grep -q __LP64__; then 283 HOST_ARCH=x86_64 284 fi 285 fi 286 ;; 287 amd64) HOST_ARCH=x86_64 288 ;; 289 powerpc) HOST_ARCH=ppc 290 ;; 291 esac 292 293 HOST_FILE_PROGRAM="file" 294 case "$HOST_OS-$HOST_ARCH" in 295 linux-x86_64|darwin-x86_64) 296 ## On Linux or Darwin, a 64-bit kernel doesn't mean that the user-land 297 ## is always 32-bit, so use "file" to determine the bitness of the shell 298 ## that invoked us. The -L option is used to de-reference symlinks. 299 ## 300 ## Note that on Darwin, a single executable can contain both x86 and 301 ## x86_64 machine code, so just look for x86_64 (darwin) or x86-64 (Linux) 302 ## in the output. 303 ## 304 ## Also note that some versions of 'file' in MacPort may report erroneous 305 ## result. See http://b.android.com/53769. Use /usr/bin/file if exists. 306 if [ "$HOST_OS" = "darwin" ]; then 307 SYSTEM_FILE_PROGRAM="/usr/bin/file" 308 test -x "$SYSTEM_FILE_PROGRAM" && HOST_FILE_PROGRAM="$SYSTEM_FILE_PROGRAM" 309 fi 310 "$HOST_FILE_PROGRAM" -L "$SHELL" | grep -q "x86[_-]64" 311 if [ $? != 0 ]; then 312 # $SHELL is not a 64-bit executable, so assume our userland is too. 313 log2 "Detected 32-bit userland on 64-bit kernel system!" 314 HOST_ARCH=x86 315 fi 316 ;; 317 esac 318 319 log2 "HOST_ARCH=$HOST_ARCH" 320 321 # at this point, the supported values for HOST_ARCH are: 322 # x86 323 # x86_64 324 # ppc 325 # 326 # other values may be possible but haven't been tested 327 # 328 # at this point, the value of HOST_OS should be one of the following: 329 # linux 330 # darwin 331 # windows (MSys) 332 # cygwin 333 # 334 # Note that cygwin is treated as a special case because it behaves very differently 335 # for a few things. Other values may be possible but have not been tested 336 # 337 338 # define HOST_TAG as a unique tag used to identify both the host OS and CPU 339 # supported values are: 340 # 341 # linux-x86 342 # linux-x86_64 343 # darwin-x86 344 # darwin-x86_64 345 # darwin-ppc 346 # windows 347 # windows-x86_64 348 # 349 # other values are possible but were not tested. 350 # 351 compute_host_tag () 352 { 353 HOST_TAG=${HOST_OS}-${HOST_ARCH} 354 # Special case for windows-x86 => windows 355 case $HOST_TAG in 356 windows-x86|cygwin-x86) 357 HOST_TAG="windows" 358 ;; 359 esac 360 log2 "HOST_TAG=$HOST_TAG" 361 } 362 363 compute_host_tag 364 365 # Compute the number of host CPU cores an HOST_NUM_CPUS 366 # 367 case "$HOST_OS" in 368 linux) 369 HOST_NUM_CPUS=`cat /proc/cpuinfo | grep processor | wc -l` 370 ;; 371 darwin|freebsd) 372 HOST_NUM_CPUS=`sysctl -n hw.ncpu` 373 ;; 374 windows|cygwin) 375 HOST_NUM_CPUS=$NUMBER_OF_PROCESSORS 376 ;; 377 *) # let's play safe here 378 HOST_NUM_CPUS=1 379 esac 380 381 log2 "HOST_NUM_CPUS=$HOST_NUM_CPUS" 382 383 # If BUILD_NUM_CPUS is not already defined in your environment, 384 # define it as the double of HOST_NUM_CPUS. This is used to 385 # run Make commands in parralles, as in 'make -j$BUILD_NUM_CPUS' 386 # 387 if [ -z "$BUILD_NUM_CPUS" ] ; then 388 BUILD_NUM_CPUS=`expr $HOST_NUM_CPUS \* 2` 389 fi 390 391 log2 "BUILD_NUM_CPUS=$BUILD_NUM_CPUS" 392 393 394 ## HOST TOOLCHAIN SUPPORT 395 ## 396 397 # force the generation of 32-bit binaries on 64-bit systems 398 # 399 FORCE_32BIT=no 400 force_32bit_binaries () 401 { 402 if [ "$HOST_ARCH" = x86_64 ] ; then 403 log2 "Forcing generation of 32-bit host binaries on $HOST_ARCH" 404 FORCE_32BIT=yes 405 HOST_ARCH=x86 406 log2 "HOST_ARCH=$HOST_ARCH" 407 compute_host_tag 408 fi 409 } 410 411 # On Windows, cygwin binaries will be generated by default, but 412 # you can force mingw ones that do not link to cygwin.dll if you 413 # call this function. 414 # 415 disable_cygwin () 416 { 417 if [ $HOST_OS = cygwin ] ; then 418 log2 "Disabling cygwin binaries generation" 419 CFLAGS="$CFLAGS -mno-cygwin" 420 LDFLAGS="$LDFLAGS -mno-cygwin" 421 HOST_OS=windows 422 compute_host_tag 423 fi 424 } 425 426 # Various probes are going to need to run a small C program 427 mkdir -p /tmp/ndk-$USER/tmp/tests 428 429 TMPC=/tmp/ndk-$USER/tmp/tests/test-$$.c 430 TMPO=/tmp/ndk-$USER/tmp/tests/test-$$.o 431 TMPE=/tmp/ndk-$USER/tmp/tests/test-$$$EXE 432 TMPL=/tmp/ndk-$USER/tmp/tests/test-$$.log 433 434 # cleanup temporary files 435 clean_temp () 436 { 437 rm -f $TMPC $TMPO $TMPL $TMPE 438 } 439 440 # cleanup temp files then exit with an error 441 clean_exit () 442 { 443 clean_temp 444 exit 1 445 } 446 447 # this function will setup the compiler and linker and check that they work as advertised 448 # note that you should call 'force_32bit_binaries' before this one if you want it to 449 # generate 32-bit binaries on 64-bit systems (that support it). 450 # 451 setup_toolchain () 452 { 453 if [ -z "$CC" ] ; then 454 CC=gcc 455 fi 456 if [ -z "$CXX" ] ; then 457 CXX=g++ 458 fi 459 if [ -z "$CXXFLAGS" ] ; then 460 CXXFLAGS="$CFLAGS" 461 fi 462 if [ -z "$LD" ] ; then 463 LD="$CC" 464 fi 465 466 log2 "Using '$CC' as the C compiler" 467 468 # check that we can compile a trivial C program with this compiler 469 mkdir -p $(dirname "$TMPC") 470 cat > $TMPC <<EOF 471 int main(void) {} 472 EOF 473 474 if [ "$FORCE_32BIT" = yes ] ; then 475 CC="$CC -m32" 476 CXX="$CXX -m32" 477 LD="$LD -m32" 478 compile 479 if [ $? != 0 ] ; then 480 # sometimes, we need to also tell the assembler to generate 32-bit binaries 481 # this is highly dependent on your GCC installation (and no, we can't set 482 # this flag all the time) 483 CFLAGS="$CFLAGS -Wa,--32" 484 compile 485 fi 486 fi 487 488 compile 489 if [ $? != 0 ] ; then 490 echo "your C compiler doesn't seem to work:" 491 cat $TMPL 492 clean_exit 493 fi 494 log "CC : compiler check ok ($CC)" 495 496 # check that we can link the trivial program into an executable 497 link 498 if [ $? != 0 ] ; then 499 OLD_LD="$LD" 500 LD="$CC" 501 compile 502 link 503 if [ $? != 0 ] ; then 504 LD="$OLD_LD" 505 echo "your linker doesn't seem to work:" 506 cat $TMPL 507 clean_exit 508 fi 509 fi 510 log2 "Using '$LD' as the linker" 511 log "LD : linker check ok ($LD)" 512 513 # check the C++ compiler 514 log2 "Using '$CXX' as the C++ compiler" 515 516 cat > $TMPC <<EOF 517 #include <iostream> 518 using namespace std; 519 int main() 520 { 521 cout << "Hello World!" << endl; 522 return 0; 523 } 524 EOF 525 526 compile_cpp 527 if [ $? != 0 ] ; then 528 echo "your C++ compiler doesn't seem to work" 529 cat $TMPL 530 clean_exit 531 fi 532 533 log "CXX : C++ compiler check ok ($CXX)" 534 535 # XXX: TODO perform AR checks 536 AR=ar 537 ARFLAGS= 538 } 539 540 # try to compile the current source file in $TMPC into an object 541 # stores the error log into $TMPL 542 # 543 compile () 544 { 545 log2 "Object : $CC -o $TMPO -c $CFLAGS $TMPC" 546 $CC -o $TMPO -c $CFLAGS $TMPC 2> $TMPL 547 } 548 549 compile_cpp () 550 { 551 log2 "Object : $CXX -o $TMPO -c $CXXFLAGS $TMPC" 552 $CXX -o $TMPO -c $CXXFLAGS $TMPC 2> $TMPL 553 } 554 555 # try to link the recently built file into an executable. error log in $TMPL 556 # 557 link() 558 { 559 log2 "Link : $LD -o $TMPE $TMPO $LDFLAGS" 560 $LD -o $TMPE $TMPO $LDFLAGS 2> $TMPL 561 } 562 563 # run a command 564 # 565 execute() 566 { 567 log2 "Running: $*" 568 $* 569 } 570 571 # perform a simple compile / link / run of the source file in $TMPC 572 compile_exec_run() 573 { 574 log2 "RunExec : $CC -o $TMPE $CFLAGS $TMPC" 575 compile 576 if [ $? != 0 ] ; then 577 echo "Failure to compile test program" 578 cat $TMPC 579 cat $TMPL 580 clean_exit 581 fi 582 link 583 if [ $? != 0 ] ; then 584 echo "Failure to link test program" 585 cat $TMPC 586 echo "------" 587 cat $TMPL 588 clean_exit 589 fi 590 $TMPE 591 } 592 593 pattern_match () 594 { 595 echo "$2" | grep -q -E -e "$1" 596 } 597 598 # Let's check that we have a working md5sum here 599 check_md5sum () 600 { 601 A_MD5=`echo "A" | md5sum | cut -d' ' -f1` 602 if [ "$A_MD5" != "bf072e9119077b4e76437a93986787ef" ] ; then 603 echo "Please install md5sum on this machine" 604 exit 2 605 fi 606 } 607 608 # Find if a given shell program is available. 609 # We need to take care of the fact that the 'which <foo>' command 610 # may return either an empty string (Linux) or something like 611 # "no <foo> in ..." (Darwin). Also, we need to redirect stderr 612 # to /dev/null for Cygwin 613 # 614 # $1: variable name 615 # $2: program name 616 # 617 # Result: set $1 to the full path of the corresponding command 618 # or to the empty/undefined string if not available 619 # 620 find_program () 621 { 622 local PROG RET 623 PROG=`which $2 2>/dev/null` 624 RET=$? 625 if [ $RET != 0 ]; then 626 PROG= 627 fi 628 eval $1=\"$PROG\" 629 return $RET 630 } 631 632 prepare_download () 633 { 634 find_program CMD_WGET wget 635 find_program CMD_CURL curl 636 find_program CMD_SCRP scp 637 } 638 639 find_pbzip2 () 640 { 641 if [ -z "$_PBZIP2_initialized" ] ; then 642 find_program PBZIP2 pbzip2 643 _PBZIP2_initialized="yes" 644 fi 645 } 646 647 # Download a file with either 'curl', 'wget' or 'scp' 648 # 649 # $1: source URL (e.g. http://foo.com, ssh://blah, /some/path) 650 # $2: target file 651 download_file () 652 { 653 # Is this HTTP, HTTPS or FTP ? 654 if pattern_match "^(http|https|ftp):.*" "$1"; then 655 if [ -n "$CMD_WGET" ] ; then 656 run $CMD_WGET -O $2 $1 657 elif [ -n "$CMD_CURL" ] ; then 658 run $CMD_CURL -o $2 $1 659 else 660 echo "Please install wget or curl on this machine" 661 exit 1 662 fi 663 return 664 fi 665 666 # Is this SSH ? 667 # Accept both ssh://<path> or <machine>:<path> 668 # 669 if pattern_match "^(ssh|[^:]+):.*" "$1"; then 670 if [ -n "$CMD_SCP" ] ; then 671 scp_src=`echo $1 | sed -e s%ssh://%%g` 672 run $CMD_SCP $scp_src $2 673 else 674 echo "Please install scp on this machine" 675 exit 1 676 fi 677 return 678 fi 679 680 # Is this a file copy ? 681 # Accept both file://<path> or /<path> 682 # 683 if pattern_match "^(file://|/).*" "$1"; then 684 cp_src=`echo $1 | sed -e s%^file://%%g` 685 run cp -f $cp_src $2 686 return 687 fi 688 } 689 690 # Form the relative path between from one abs path to another 691 # 692 # $1 : start path 693 # $2 : end path 694 # 695 # From: 696 # http://stackoverflow.com/questions/2564634/bash-convert-absolute-path-into-relative-path-given-a-current-directory 697 relpath () 698 { 699 [ $# -ge 1 ] && [ $# -le 2 ] || return 1 700 current="${2:+"$1"}" 701 target="${2:-"$1"}" 702 [ "$target" != . ] || target=/ 703 target="/${target##/}" 704 [ "$current" != . ] || current=/ 705 current="${current:="/"}" 706 current="/${current##/}" 707 appendix="${target##/}" 708 relative='' 709 while appendix="${target#"$current"/}" 710 [ "$current" != '/' ] && [ "$appendix" = "$target" ]; do 711 if [ "$current" = "$appendix" ]; then 712 relative="${relative:-.}" 713 echo "${relative#/}" 714 return 0 715 fi 716 current="${current%/*}" 717 relative="$relative${relative:+/}.." 718 done 719 relative="$relative${relative:+${appendix:+/}}${appendix#/}" 720 echo "$relative" 721 } 722 723 # Unpack a given archive 724 # 725 # $1: archive file path 726 # $2: optional target directory (current one if omitted) 727 # 728 unpack_archive () 729 { 730 local ARCHIVE="$1" 731 local DIR=${2-.} 732 local RESULT TARFLAGS ZIPFLAGS 733 mkdir -p "$DIR" 734 if [ "$VERBOSE2" = "yes" ] ; then 735 TARFLAGS="vxpf" 736 ZIPFLAGS="" 737 else 738 TARFLAGS="xpf" 739 ZIPFLAGS="q" 740 fi 741 case "$ARCHIVE" in 742 *.zip) 743 (cd $DIR && run unzip $ZIPFLAGS "$ARCHIVE") 744 ;; 745 *.tar) 746 run tar $TARFLAGS "$ARCHIVE" -C $DIR 747 ;; 748 *.tar.gz) 749 run tar z$TARFLAGS "$ARCHIVE" -C $DIR 750 ;; 751 *.tar.bz2) 752 find_pbzip2 753 if [ -n "$PBZIP2" ] ; then 754 run tar --use-compress-prog=pbzip2 -$TARFLAGS "$ARCHIVE" -C $DIR 755 else 756 run tar j$TARFLAGS "$ARCHIVE" -C $DIR 757 fi 758 # remove ._* files by MacOSX to preserve resource forks we don't need 759 find $DIR -name "\._*" -exec rm {} \; 760 ;; 761 *) 762 panic "Cannot unpack archive with unknown extension: $ARCHIVE" 763 ;; 764 esac 765 } 766 767 # Pack a given archive 768 # 769 # $1: archive file path (including extension) 770 # $2: source directory for archive content 771 # $3+: list of files (including patterns), all if empty 772 pack_archive () 773 { 774 local ARCHIVE="$1" 775 local SRCDIR="$2" 776 local SRCFILES 777 local TARFLAGS ZIPFLAGS 778 shift; shift; 779 if [ -z "$1" ] ; then 780 SRCFILES="*" 781 else 782 SRCFILES="$@" 783 fi 784 if [ "`basename $ARCHIVE`" = "$ARCHIVE" ] ; then 785 ARCHIVE="`pwd`/$ARCHIVE" 786 fi 787 mkdir -p `dirname $ARCHIVE` 788 if [ "$VERBOSE2" = "yes" ] ; then 789 TARFLAGS="vcf" 790 ZIPFLAGS="-9r" 791 else 792 TARFLAGS="cf" 793 ZIPFLAGS="-9qr" 794 fi 795 # Ensure symlinks are stored as is in zip files. for toolchains 796 # this can save up to 7 MB in the size of the final archive 797 #ZIPFLAGS="$ZIPFLAGS --symlinks" 798 case "$ARCHIVE" in 799 *.zip) 800 (cd $SRCDIR && run zip $ZIPFLAGS "$ARCHIVE" $SRCFILES) 801 ;; 802 *.tar) 803 (cd $SRCDIR && run tar $TARFLAGS "$ARCHIVE" $SRCFILES) 804 ;; 805 *.tar.gz) 806 (cd $SRCDIR && run tar z$TARFLAGS "$ARCHIVE" $SRCFILES) 807 ;; 808 *.tar.bz2) 809 find_pbzip2 810 if [ -n "$PBZIP2" ] ; then 811 (cd $SRCDIR && run tar --use-compress-prog=pbzip2 -$TARFLAGS "$ARCHIVE" $SRCFILES) 812 else 813 (cd $SRCDIR && run tar j$TARFLAGS "$ARCHIVE" $SRCFILES) 814 fi 815 ;; 816 *) 817 panic "Unsupported archive format: $ARCHIVE" 818 ;; 819 esac 820 } 821 822 # Copy a directory, create target location if needed 823 # 824 # $1: source directory 825 # $2: target directory location 826 # 827 copy_directory () 828 { 829 local SRCDIR="$1" 830 local DSTDIR="$2" 831 if [ ! -d "$SRCDIR" ] ; then 832 panic "Can't copy from non-directory: $SRCDIR" 833 fi 834 log "Copying directory: " 835 log " from $SRCDIR" 836 log " to $DSTDIR" 837 mkdir -p "$DSTDIR" && (cd "$SRCDIR" && 2>/dev/null tar cf - *) | (tar xf - -C "$DSTDIR") 838 fail_panic "Cannot copy to directory: $DSTDIR" 839 } 840 841 # Move a directory, create target location if needed 842 # 843 # $1: source directory 844 # $2: target directory location 845 # 846 move_directory () 847 { 848 local SRCDIR="$1" 849 local DSTDIR="$2" 850 if [ ! -d "$SRCDIR" ] ; then 851 panic "Can't move from non-directory: $SRCDIR" 852 fi 853 log "Move directory: " 854 log " from $SRCDIR" 855 log " to $DSTDIR" 856 mkdir -p "$DSTDIR" && (mv "$SRCDIR"/* "$DSTDIR") 857 fail_panic "Cannot move to directory: $DSTDIR" 858 } 859 860 # This is the same than copy_directory(), but symlinks will be replaced 861 # by the file they actually point to instead. 862 copy_directory_nolinks () 863 { 864 local SRCDIR="$1" 865 local DSTDIR="$2" 866 if [ ! -d "$SRCDIR" ] ; then 867 panic "Can't copy from non-directory: $SRCDIR" 868 fi 869 log "Copying directory (without symlinks): " 870 log " from $SRCDIR" 871 log " to $DSTDIR" 872 mkdir -p "$DSTDIR" && (cd "$SRCDIR" && tar chf - *) | (tar xf - -C "$DSTDIR") 873 fail_panic "Cannot copy to directory: $DSTDIR" 874 } 875 876 # Copy certain files from one directory to another one 877 # $1: source directory 878 # $2: target directory 879 # $3+: file list (including patterns) 880 copy_file_list () 881 { 882 local SRCDIR="$1" 883 local DSTDIR="$2" 884 shift; shift; 885 if [ ! -d "$SRCDIR" ] ; then 886 panic "Cant' copy from non-directory: $SRCDIR" 887 fi 888 log "Copying file: $@" 889 log " from $SRCDIR" 890 log " to $DSTDIR" 891 mkdir -p "$DSTDIR" && (cd "$SRCDIR" && (echo $@ | tr ' ' '\n' | tar cf - -T -)) | (tar xf - -C "$DSTDIR") 892 fail_panic "Cannot copy files to directory: $DSTDIR" 893 } 894 895 # Rotate a log file 896 # If the given log file exist, add a -1 to the end of the file. 897 # If older log files exist, rename them to -<n+1> 898 # $1: log file 899 # $2: maximum version to retain [optional] 900 rotate_log () 901 { 902 # Default Maximum versions to retain 903 local MAXVER="5" 904 local LOGFILE="$1" 905 shift; 906 if [ ! -z "$1" ] ; then 907 local tmpmax="$1" 908 shift; 909 tmpmax=`expr $tmpmax + 0` 910 if [ $tmpmax -lt 1 ] ; then 911 panic "Invalid maximum log file versions '$tmpmax' invalid; defaulting to $MAXVER" 912 else 913 MAXVER=$tmpmax; 914 fi 915 fi 916 917 # Do Nothing if the log file does not exist 918 if [ ! -f "${LOGFILE}" ] ; then 919 return 920 fi 921 922 # Rename existing older versions 923 ver=$MAXVER 924 while [ $ver -ge 1 ] 925 do 926 local prev=$(( $ver - 1 )) 927 local old="-$prev" 928 929 # Instead of old version 0; use the original filename 930 if [ $ver -eq 1 ] ; then 931 old="" 932 fi 933 934 if [ -f "${LOGFILE}${old}" ] ; then 935 mv -f "${LOGFILE}${old}" "${LOGFILE}-${ver}" 936 fi 937 938 ver=$prev 939 done 940 } 941