1 #!/bin/bash 2 3 # This script is used to rebuild all emulator binaries from sources 4 # and package them for easier distribution. 5 6 set -e 7 export LANG=C 8 export LC_ALL=C 9 10 PROGDIR=$(dirname "$0") 11 PROGNAME=$(basename "$0") 12 13 panic () { 14 echo "ERROR: $@" 15 exit 1 16 } 17 18 VERBOSE=1 19 20 # Dump a message if VERBOSE is greater or equal to $1 21 # $1: level 22 # $2+: Message to print. 23 dump_n () { 24 local LEVEL=$1 25 shift 26 if [ "$VERBOSE" -ge "$LEVEL" ]; then 27 printf "%s\n" "$@" 28 fi 29 } 30 31 # Dump a message at VERBOSE level 1 (the default one). 32 dump () { 33 dump_n 1 "$@" 34 } 35 36 # Dump a message at VERBOSE level 2 (if --verbose was used). 37 log () { 38 dump_n 2 "$@" 39 } 40 41 # Run a command, dump its output depending on VERBOSE level, i.e.: 42 # 0 -> Don't display anything. 43 # 1 -> Display error messages only. 44 # 2 -> Display the command, its output and error. 45 run () { 46 case $VERBOSE in 47 0) 48 "$@" >/dev/null 2>&1 49 ;; 50 1) 51 "$@" >/dev/null 52 ;; 53 *) 54 echo "COMMAND: $@" 55 "$@" 56 ;; 57 esac 58 } 59 60 # Same as 'run', but slightly more quiet: 61 # 0 or 1 -> Don't display anything 62 # 2 -> Diplay the command, its output and error. 63 run2 () { 64 case $VERBOSE in 65 0|1) 66 "$@" >/dev/null 2>&1 67 ;; 68 2) 69 echo "COMMAND: $@" 70 "$@" >/dev/null 2>&1 71 ;; 72 *) 73 echo "COMMAND: $@" 74 "$@" 75 ;; 76 esac 77 } 78 79 # $1: Source directory. 80 # $2: Destination directory. 81 # $3: List of files to copy, relative to $1 (if empty, all files will be copied). 82 copy_directory_files () { 83 local SRCDIR DSTDIR FILES 84 SRCDIR=$1 85 DSTDIR=$2 86 shift; shift; 87 FILES="$@" 88 89 mkdir -p "$DSTDIR" || panic "Cannot create destination directory: $DSTDIR" 90 (cd $SRCDIR && tar cf - $FILES) | (cd $DSTDIR && tar xf -) 91 } 92 93 # $1: Source directory (must be a git checkout). 94 # $2: Destination directory. 95 copy_directory_git_files () { 96 local SRCDIR DSTDIR FILES 97 SRCDIR=$1 98 DSTDIR=$2 99 log "Copying git sources from $SRCDIR to $DSTDIR" 100 # The list of names can contain spaces, so put them in a file to avoid 101 # any issues. 102 TMP_FILE_LIST=$(mktemp) 103 (cd $SRCDIR && git ls-files) > $TMP_FILE_LIST 104 mkdir -p "$DSTDIR" || panic "Cannot create destination directory: $DSTDIR" 105 (cd $SRCDIR && tar cf - -T $TMP_FILE_LIST) | (cd $DSTDIR && tar xf -) 106 rm -f $TMP_FILE_LIST 107 } 108 109 # Convert a comma-separated list into a space-separated one. 110 commas_to_spaces () { 111 printf "%s" "$@" | tr ',' ' ' 112 } 113 114 # Rebuild Darwin binaries remotely through SSH 115 # $1: Host name. 116 # $2: Source package file. 117 build_darwin_binaries_on () { 118 local HOST PKG_FILE PKG_FILE_BASENAME DST_DIR TARFLAGS 119 HOST=$1 120 PKG_FILE=$2 121 122 # The package file is ....../something-darwin.tar.bz2 123 # And should unpack to a single directory named 'something/' 124 # so extract the prefix from the package name. 125 PKG_FILE_BASENAME=$(basename "$PKG_FILE") 126 PKG_FILE_PREFIX=${PKG_FILE_BASENAME%%-sources.tar.bz2} 127 if [ "$PKG_FILE_PREFIX" = "$PKG_FILE_BASENAME" ]; then 128 # Sanity check. 129 panic "Can't get package prefix from $PKG_FILE_BASENAME" 130 fi 131 132 # Where to do the work on the remote host. 133 DST_DIR=/tmp/android-emulator-build 134 135 if [ "$VERBOSE" -ge 3 ]; then 136 TARFLAGS="v" 137 fi 138 dump "Copying sources to Darwin host: $HOST" 139 run ssh $HOST "mkdir -p $DST_DIR && rm -rf $DST_DIR/$PKG_FILE_BASENAME" 140 cat "$PKG_FILE" | ssh $HOST "cd $DST_DIR && tar x${TARGFLAGS}f -" 141 142 dump "Rebuilding Darwin binaries remotely." 143 run ssh $HOST "bash -l -c \"cd $DST_DIR/$PKG_FILE_PREFIX/qemu && ./android-rebuild.sh $REBUILD_FLAGS\"" || 144 panic "Can't rebuild binaries on Darwin, use --verbose to see why!" 145 146 dump "Retrieving Darwin binaries from: $HOST" 147 rm -rf objs/* 148 run scp $HOST:$DST_DIR/$PKG_FILE_PREFIX/qemu/objs/emulator* objs/ 149 run scp -r $HOST:$DST_DIR/$PKG_FILE_PREFIX/qemu/objs/lib objs/lib 150 # TODO(digit): Retrieve PC BIOS files. 151 run ssh $HOST rm -rf $DST_DIR/$PKG_FILE_PREFIX 152 } 153 154 # Extract the git commit SHA1 of a given directory, and put its value 155 # in a destination variable. If the target directory is not the root 156 # of a git checkout, abort. 157 # $1: Destination variable name. 158 # $2: Git directory. 159 # Example: extract_commit_description GTEST_DESC "$GTEST_DIR" 160 extract_git_commit_description () { 161 local VARNAME GIT_DIR SHA1 162 VARNAME=$1 163 GIT_DIR=$2 164 # Extract the commit description, then escape (') characters in it. 165 SHA1=$(cd $GIT_DIR && git log --oneline -1 .) || \ 166 panic "Not a Git directory: $GIT_DIR" 167 168 SHA1=$(printf "%s" "$SHA1" | sed -e "s/'/\\'/g") 169 eval $VARNAME=\'$SHA1\' 170 } 171 172 # Defaults. 173 DEFAULT_REVISION=$(date +%Y%m%d) 174 DEFAULT_PKG_PREFIX=android-emulator 175 DEFAULT_PKG_DIR=/tmp 176 DEFAULT_DARWIN_SSH=$ANDROID_EMULATOR_DARWIN_SSH 177 178 case $(uname -s) in 179 Linux) 180 DEFAULT_SYSTEMS="linux,windows" 181 HOST_SYSTEM=linux 182 ;; 183 Darwin) 184 DEFAULT_SYSTEMS="darwin" 185 HOST_SYSTEM=darwin 186 ;; 187 *) 188 panic "Unsupported system! This can only run on Linux and Darwin." 189 esac 190 191 # Command-line parsing. 192 DO_HELP= 193 OPT_COPY_PREBUILTS= 194 OPT_DARWIN_SSH= 195 OPT_PKG_DIR= 196 OPT_PKG_PREFIX= 197 OPT_REVISION= 198 OPT_SOURCES= 199 OPT_SYSTEM= 200 201 for OPT; do 202 case $OPT in 203 --help|-?) 204 DO_HELP=true 205 ;; 206 --copy-prebuilts=*) 207 OPT_COPY_PREBUILTS=${OPT##--copy-prebuilts=} 208 ;; 209 --darwin-ssh=*) 210 OPT_DARWIN_SSH=${OPT##--darwin-ssh=} 211 ;; 212 --package-dir=*) 213 OPT_PKG_DIR=${OPT##--package-dir=} 214 ;; 215 --package-prefix=*) 216 OPT_PKG_PREFIX=${OPT##--package-prefix=} 217 ;; 218 --quiet) 219 VERBOSE=$(( $VERBOSE - 1 )) 220 ;; 221 --sources) 222 OPT_SOURCES=true 223 ;; 224 --revision=*) 225 OPT_REVISION=${OPT##--revision=} 226 ;; 227 --system=*) 228 OPT_SYSTEM=${OPT##--system=} 229 ;; 230 --verbose) 231 VERBOSE=$(( $VERBOSE + 1 )) 232 ;; 233 -*) 234 panic "Unsupported option '$OPT', see --help." 235 ;; 236 *) 237 panic "Unsupported parameter '$OPT', see --help." 238 esac 239 done 240 241 if [ "$DO_HELP" ]; then 242 cat <<EOF 243 Usage: $PROGNAME [options] 244 245 Rebuild the emulator binaries from source and package them into tarballs 246 for easier distribution. 247 248 New packages are placed by default at $DEFAULT_PKG_DIR 249 Use --package-dir=<path> to use another output directory. 250 251 Packages names are prefixed with $DEFAULT_PKG_PREFIX-<revision>, where 252 the <revision> is the current ISO date by default. You can use 253 --package-prefix=<prefix> and --revision=<revision> to change this. 254 255 Binary packages will include the OpenGLES emulation libraries if they can 256 be found in your current workspace, not otherwise. 257 258 Use --sources option to also generate a source tarball. 259 260 Use --darwin-ssh=<host> to build perform a remote build of the Darwin 261 binaries on a remote host through ssh. Note that this forces --sources 262 as well. You can also define ANDROID_EMULATOR_DARWIN_SSH in your 263 environment to setup a default value for this option. 264 265 Use --copy-prebuilts=<path> to specify the path of an AOSP workspace/checkout, 266 and to copy 64-bit prebuilt binaries to <path>/prebuilts/android-emulator/ 267 for both Linux and Darwin platforms. This option requires the use of 268 --darwin-ssh=<host> or ANDROID_EMULATOR_DARWIN_SSH to build the Darwin 269 binaries. 270 271 Valid options (defaults are inside brackets): 272 --help | -? Print this message. 273 --package-dir=<path> Change package output directory [$DEFAULT_PKG_DIR]. 274 --revision=<name> Change revision [$DEFAULT_REVISION]. 275 --sources Also create sources package. 276 --system=<list> Specify host system list [$DEFAULT_SYSTEMS]. 277 --copy-prebuilts=<path> Copy 64-bit Linux and Darwin binaries to 278 <path>/prebuilts/android-emulator/ 279 280 EOF 281 exit 0 282 fi 283 284 if [ "$OPT_PKG_PREFIX" ]; then 285 PKG_PREFIX=$OPT_PKG_PREFIX 286 else 287 PKG_PREFIX=$DEFAULT_PKG_PREFIX 288 log "Auto-config: --package-prefix=$PKG_PREFIX" 289 fi 290 291 if [ "$OPT_REVISION" ]; then 292 PKG_REVISION=$OPT_REVISION 293 else 294 PKG_REVISION=$DEFAULT_REVISION 295 log "Auto-config: --revision=$PKG_REVISION" 296 fi 297 298 if [ "$OPT_PKG_DIR" ]; then 299 PKG_DIR=$OPT_PKG_DIR 300 mkdir -p "$PKG_DIR" || panic "Can't create directory: $PKG_DIR" 301 else 302 PKG_DIR=$DEFAULT_PKG_DIR 303 log "Auto-config: --package-dir=$PKG_DIR" 304 fi 305 306 if [ "$OPT_SYSTEM" ]; then 307 SYSTEMS=$(commas_to_spaces $OPT_SYSTEM) 308 else 309 SYSTEMS=$(commas_to_spaces $DEFAULT_SYSTEMS) 310 log "Auto-config: --system=$SYSTEMS" 311 fi 312 313 if [ -z "$OPT_DARWIN_SSH" ]; then 314 DARWIN_SSH=$DEFAULT_DARWIN_SSH 315 if [ "$DARWIN_SSH" ]; then 316 log "Auto-config: --darwin-ssh=$DARWIN_SSH (from environment)." 317 fi 318 else 319 DARWIN_SSH=$OPT_DARWIN_SSH 320 fi 321 322 if [ "$DARWIN_SSH" ]; then 323 if [ -z "$OPT_SOURCES" ]; then 324 OPT_SOURCES=true 325 log "Auto-config: --sources (remote Darwin build)." 326 fi 327 SYSTEMS="$SYSTEMS darwin" 328 fi 329 330 if [ "$OPT_COPY_PREBUILTS" ]; then 331 if [ -z "$DARWIN_SSH" ]; then 332 panic "The --copy-prebuilts=<dir> option requires --darwin-ssh=<host>." 333 fi 334 TARGET_AOSP=$OPT_COPY_PREBUILTS 335 if [ ! -f "$TARGET_AOSP/build/envsetup.sh" ]; then 336 panic "Not an AOSP checkout / workspace: $TARGET_AOSP" 337 fi 338 TARGET_PREBUILTS_DIR=$TARGET_AOSP/prebuilts/android-emulator 339 mkdir -p "$TARGET_PREBUILTS_DIR" 340 fi 341 342 case $VERBOSE in 343 0|1) 344 REBUILD_FLAGS="" 345 ;; 346 2) 347 REBUILD_FLAGS="--verbose" 348 ;; 349 *) 350 REBUILD_FLAGS="--verbose --verbose" 351 ;; 352 esac 353 354 # Remove duplicates. 355 SYSTEMS=$(echo "$SYSTEMS" | tr ' ' '\n' | sort -u | tr '\n' ' ') 356 log "Building for the following systems: $SYSTEMS" 357 358 # Default build directory. 359 TEMP_BUILD_DIR=/tmp/$USER-qemu-package-binaries 360 361 # Ensure the build directory is removed when the script exits or is 362 # interrupted. 363 clean_exit () { 364 if [ -n "$TEMP_BUILD_DIR" -a -d "$TEMP_BUILD_DIR" ]; then 365 rm -rf "$TEMP_BUILD_DIR" 366 fi 367 exit $? 368 } 369 370 trap "clean_exit 0" EXIT 371 trap "clean_exit \$?" QUIT HUP INT 372 373 # Do some sanity checks to verify that the current source directory 374 # doesn't have unchecked files and other bad things lingering. 375 376 # Assume this script is under distrib/ 377 QEMU_DIR=$(cd "$PROGDIR"/.. && pwd -P) 378 log "Found emulator directory: $QEMU_DIR" 379 380 cd $QEMU_DIR 381 if [ ! -d "$QEMU_DIR"/.git ]; then 382 panic "This directory must be a checkout of \$AOSP/platform/external/qemu!" 383 fi 384 UNCHECKED_FILES=$(git ls-files -o -x objs/ -x images/emulator_icon.o) 385 if [ "$UNCHECKED_FILES" ]; then 386 echo "ERROR: There are unchecked files in the current directory!" 387 echo "Please remove them:" 388 echo "$UNCHECKED_FILES" 389 exit 1 390 fi 391 392 extract_git_commit_description QEMU_GIT_COMMIT "$QEMU_DIR" 393 GTEST_DIR=$(dirname $QEMU_DIR)/gtest 394 if [ ! -d "$GTEST_DIR" ]; then 395 panic "Cannot find GoogleTest source directory: $GTEST_DIR" 396 fi 397 log "Found GoogleTest directory: $GTEST_DIR" 398 extract_git_commit_description GTEST_GIT_COMMIT "$GTEST_DIR" 399 400 EMUGL_DIR=$QEMU_DIR/../../sdk/emulator/opengl 401 if [ ! -d "$EMUGL_DIR" ]; then 402 panic "Cannot find GPU emulation source directory: $EMUGL_DIR" 403 fi 404 log "Found GPU emulation directory: $EMUGL_DIR" 405 extract_git_commit_description EMUGL_GIT_COMMIT "$EMUGL_DIR" 406 407 SOURCES_PKG_FILE= 408 if [ "$OPT_SOURCES" ]; then 409 BUILD_DIR=$TEMP_BUILD_DIR/sources/$PKG_PREFIX-$PKG_REVISION 410 PKG_NAME="$PKG_REVISION-sources" 411 dump "[$PKG_NAME] Copying GoogleTest source files." 412 copy_directory_git_files "$GTEST_DIR" "$BUILD_DIR"/gtest 413 414 dump "[$PKG_NAME] Copying Emulator source files." 415 copy_directory_git_files "$QEMU_DIR" "$BUILD_DIR"/qemu 416 417 dump "[$PKG_NAME] Copying GPU emulation library sources." 418 copy_directory_git_files "$EMUGL_DIR" "$BUILD_DIR"/opengl 419 420 dump "[$PKG_NAME] Generating README file." 421 cat > "$BUILD_DIR"/README <<EOF 422 This directory contains the sources of the Android emulator. 423 Use './rebuild.sh' to rebuild the binaries from scratch. 424 EOF 425 426 dump "[$PKG_NAME] Generating rebuild script." 427 cat > "$BUILD_DIR"/rebuild.sh <<EOF 428 #!/bin/sh 429 430 # Auto-generated script used to rebuild the Android emulator binaries 431 # from sources. Note that this does not include the GLES emulation 432 # libraries. 433 434 cd \$(dirname "\$0") && 435 (cd qemu && ./android-rebuild.sh --ignore-audio) && 436 mkdir -p bin/ && 437 cp -rfp qemu/objs/emulator* bin/ && 438 echo "Emulator binaries are under \$(pwd -P)/bin/" 439 echo "IMPORTANT: The GLES emulation libraries must be copied to:" 440 echo " \$(pwd -P)/bin/lib" 441 EOF 442 443 chmod +x "$BUILD_DIR"/rebuild.sh 444 445 PKG_FILE=$PKG_DIR/$PKG_PREFIX-$PKG_REVISION-sources.tar.bz2 446 SOURCES_PKG_FILE=$PKG_FILE 447 dump "[$PKG_NAME] Creating tarball..." 448 (run cd "$BUILD_DIR"/.. && run tar cjf "$PKG_FILE" $PKG_PREFIX-$PKG_REVISION) 449 fi 450 451 for SYSTEM in $SYSTEMS; do 452 PKG_NAME="$PKG_REVISION-$SYSTEM" 453 dump "[$PKG_NAME] Rebuilding binaries from sources." 454 run cd $QEMU_DIR 455 case $SYSTEM in 456 $HOST_SYSTEM) 457 run ./android-rebuild.sh $REBUILD_FLAGS || panic "Use ./android-rebuild.sh to see why." 458 ;; 459 darwin) 460 if [ -z "$DARWIN_SSH" ]; then 461 # You can only rebuild Darwin binaries on non-Darwin systems 462 # by using --darwin-ssh=<host>. 463 panic "You can only rebuild Darwin binaries with --darwin-ssh" 464 fi 465 if [ -z "$SOURCES_PKG_FILE" ]; then 466 panic "You must use --sources to build Darwin binaries through ssh" 467 fi 468 build_darwin_binaries_on "$DARWIN_SSH" "$SOURCES_PKG_FILE" 469 ;; 470 windows) 471 if [ "$HOST_SYSTEM" != "linux" ]; then 472 panic "Windows binaries can only be rebuilt on Linux!" 473 fi 474 run ./android-rebuild.sh --mingw $REBUILD_FLAGS || panic "Use ./android-rebuild.sh --mingw to see why." 475 ;; 476 *) 477 panic "Can't rebuild $SYSTEM binaries on $HOST_SYSTEM for now!" 478 ;; 479 esac 480 481 dump "[$PKG_NAME] Copying emulator binaries." 482 TEMP_PKG_DIR=$TEMP_BUILD_DIR/$SYSTEM/$PKG_PREFIX-$PKG_REVISION 483 run mkdir -p "$TEMP_PKG_DIR"/tools 484 485 run cp -p objs/emulator* "$TEMP_PKG_DIR"/tools 486 if [ -d "objs/lib" ]; then 487 dump "[$PKG_NAME] Copying GLES emulation libraries." 488 run mkdir -p "$TEMP_PKG_DIR"/tools/lib 489 run2 cp -rp objs/lib/* "$TEMP_PKG_DIR"/tools/lib/ 490 fi 491 492 dump "[$PKG_NAME] Creating README file." 493 cat > $TEMP_PKG_DIR/README <<EOF 494 This directory contains Android emulator binaries. You can use them directly 495 by defining ANDROID_SDK_ROOT in your environment, then call tools/emulator 496 with the usual set of options. 497 498 To install them directly into your SDK, copy them with: 499 500 cp -r tools/* \$ANDROID_SDK_ROOT/tools/ 501 EOF 502 503 dump "[$PKG_NAME] Copying license files." 504 mkdir -p "$TEMP_PKG_DIR"/licenses/ 505 cp COPYING COPYING.LIB "$TEMP_PKG_DIR"/licenses/ 506 507 dump "[$PKG_NAME] Creating tarball." 508 PKG_FILE=$PKG_DIR/$PKG_PREFIX-$PKG_REVISION-$SYSTEM.tar.bz2 509 (run cd "$TEMP_BUILD_DIR"/$SYSTEM && run tar cjf $PKG_FILE $PKG_PREFIX-$PKG_REVISION) 510 done 511 512 if [ "$OPT_COPY_PREBUILTS" ]; then 513 for SYSTEM in linux darwin; do 514 SRC_DIR="$TEMP_BUILD_DIR"/$SYSTEM/$PKG_PREFIX-$PKG_REVISION 515 DST_DIR=$TARGET_PREBUILTS_DIR/$SYSTEM-x86_64 516 dump "[$SYSTEM-x86_64] Copying emulator binaries into $DST_DIR" 517 run mkdir -p "$DST_DIR" || panic "Could not create directory: $DST_DIR" 518 case $SYSTEM in 519 linux) DLLEXT=.so;; 520 darwin) DLLEXT=.dylib;; 521 *) panic "Unsupported prebuilt system: $SYSTEM";; 522 esac 523 FILES="emulator" 524 for ARCH in arm x86 mips; do 525 FILES="$FILES emulator64-$ARCH" 526 done 527 for LIB in OpenglRender EGL_translator GLES_CM_translator GLES_V2_translator; do 528 FILES="$FILES lib/lib64$LIB$DLLEXT" 529 done 530 (run cd "$SRC_DIR/tools" && tar cf - $FILES) | (cd $DST_DIR && tar xf -) || 531 panic "Could not copy binaries to $DST_DIR" 532 done 533 cat > $TARGET_PREBUILTS_DIR/README <<EOF 534 This directory contains prebuilt emulator binaries that were generated by 535 running the following command on a 64-bit Linux machine: 536 537 external/qemu/distrib/package-release.sh \\ 538 --darwin-ssh=<host> \\ 539 --copy-prebuilts=<path> 540 541 Where <host> is the host name of a Darwin machine, and <path> is the root 542 path of this AOSP repo workspace. 543 544 Below is the list of specific commits for each input directory used: 545 546 external/gtest $GTEST_GIT_COMMIT 547 external/qemu $QEMU_GIT_COMMIT 548 sdk/emulator/opengl $EMUGL_GIT_COMMIT 549 550 EOF 551 fi 552 553 dump "Done. See $PKG_DIR" 554 ls -lh "$PKG_DIR"/$PKG_PREFIX-$PKG_REVISION* 555