1#!/usr/bin/env bash 2set -o pipefail 3set -e 4 5############################################################################## 6## 7## Gradle start up script for UN*X 8## 9############################################################################## 10 11# --------- androidx specific code needed for build server. ------------------ 12 13SCRIPT_PATH="$(cd $(dirname $0) && pwd -P)" 14if [ -n "$OUT_DIR" ] ; then 15 mkdir -p "$OUT_DIR" 16 OUT_DIR="$(cd $OUT_DIR && pwd -P)" 17 export TMPDIR="$OUT_DIR/tmp" 18elif [[ $SCRIPT_PATH == /google/cog/* ]] ; then 19 export OUT_DIR="$HOME/androidxout" 20else 21 CHECKOUT_ROOT="$(cd $SCRIPT_PATH/../.. && pwd -P)" 22 export OUT_DIR="$CHECKOUT_ROOT/out" 23fi 24export GRADLE_USER_HOME="$OUT_DIR/.gradle" 25 26ORG_GRADLE_JVMARGS="$(cd $SCRIPT_PATH && grep org.gradle.jvmargs gradle.properties | sed 's/^/-D/')" 27if [ -n "$DIST_DIR" ]; then 28 mkdir -p "$DIST_DIR" 29 DIST_DIR="$(cd $DIST_DIR && pwd -P)" 30 31 # tell Gradle where to put a heap dump on failure 32 ORG_GRADLE_JVMARGS="$(echo $ORG_GRADLE_JVMARGS | sed "s|$| -XX:HeapDumpPath=$DIST_DIR|")" 33 34 # We don't set a default DIST_DIR in an else clause here because Studio doesn't use gradlew 35 # and doesn't set DIST_DIR and we want gradlew and Studio to match 36fi 37 38# unset ANDROID_BUILD_TOP so that Lint doesn't think we're building the platform itself 39unset ANDROID_BUILD_TOP 40# ---------------------------------------------------------------------------- 41 42# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 43 44APP_NAME="Gradle" 45APP_BASE_NAME=`basename "$0"` 46 47# Use the maximum available, or set MAX_FD != -1 to use that value. 48MAX_FD="maximum" 49 50warn ( ) { 51 echo "$*" 52} 53 54die ( ) { 55 echo 56 echo "$*" 57 echo 58 exit 1 59} 60 61# OS specific support (must be 'true' or 'false'). 62cygwin=false 63msys=false 64darwin=false 65case "`uname`" in 66 CYGWIN* ) 67 cygwin=true 68 ;; 69 Darwin* ) 70 darwin=true 71 ;; 72 MINGW* ) 73 msys=true 74 ;; 75esac 76platform_suffix="x86" 77case "$(arch)" in 78 arm64* ) 79 platform_suffix="arm64" 80esac 81# Attempt to set APP_HOME 82# Resolve links: $0 may be a link 83PRG="$0" 84# Need this for relative symlinks. 85while [ -h "$PRG" ] ; do 86 ls=`ls -ld "$PRG"` 87 link=`expr "$ls" : '.*-> \(.*\)$'` 88 if expr "$link" : '/.*' > /dev/null; then 89 PRG="$link" 90 else 91 PRG=`dirname "$PRG"`"/$link" 92 fi 93done 94SAVED="`pwd`" 95cd "`dirname \"$PRG\"`/" >/dev/null 96APP_HOME="`pwd -P`" 97cd "$SAVED" >/dev/null 98 99CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 100 101# --------- androidx specific code needed for lint and java. ------------------ 102 103# Pick the correct fullsdk for this OS. 104if [ $darwin == "true" ]; then 105 plat="darwin" 106else 107 plat="linux" 108fi 109 110# Tests for lint checks default to using sdk defined by this variable. This removes a lot of 111# setup from each lint module. 112export ANDROID_HOME="$APP_HOME/../../prebuilts/fullsdk-$plat" 113# override JAVA_HOME, because CI machines have it and it points to very old JDK 114export ANDROIDX_JDK17="$APP_HOME/../../prebuilts/jdk/jdk17/$plat-$platform_suffix" 115export ANDROIDX_JDK21="$APP_HOME/../../prebuilts/jdk/jdk21/$plat-$platform_suffix" 116export JAVA_HOME=$ANDROIDX_JDK21 117export STUDIO_GRADLE_JDK=$JAVA_HOME 118 119# Warn developers if they try to build top level project without the full checkout 120[ ! -d "$JAVA_HOME" ] && echo "Failed to find: $JAVA_HOME 121 122Typically, this means either: 1231. You are using the standalone AndroidX checkout, e.g. GitHub, which only supports 124 building a subset of projects. See CONTRIBUTING.md for details. 1252. You are using the repo checkout, but the last repo sync failed. Use repo status 126 to check for projects which are partially-synced, e.g. showing ***NO BRANCH***." && exit -1 127 128# ---------------------------------------------------------------------------- 129 130# Determine the Java command to use to start the JVM. 131if [ -n "$JAVA_HOME" ] ; then 132 if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 133 # IBM's JDK on AIX uses strange locations for the executables 134 JAVACMD="$JAVA_HOME/jre/sh/java" 135 else 136 JAVACMD="$JAVA_HOME/bin/java" 137 fi 138 if [ ! -x "$JAVACMD" ] ; then 139 die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 140 141Please set the JAVA_HOME variable in your environment to match the 142location of your Java installation." 143 fi 144else 145 JAVACMD="java" 146 which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 147 148Please set the JAVA_HOME variable in your environment to match the 149location of your Java installation." 150fi 151 152# Increase the maximum file descriptors if we can. 153if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 154 MAX_FD_LIMIT=`ulimit -H -n` 155 if [ $? -eq 0 ] ; then 156 if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 157 MAX_FD="$MAX_FD_LIMIT" 158 fi 159 ulimit -n $MAX_FD 160 if [ $? -ne 0 ] ; then 161 warn "Could not set maximum file descriptor limit: $MAX_FD" 162 fi 163 else 164 warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 165 fi 166fi 167 168# For Darwin, add options to specify how the application appears in the dock 169if $darwin; then 170 GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 171fi 172 173# For Cygwin, switch paths to Windows format before running java 174if $cygwin ; then 175 APP_HOME=`cygpath --path --mixed "$APP_HOME"` 176 CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 177 JAVACMD=`cygpath --unix "$JAVACMD"` 178 179 # We build the pattern for arguments to be converted via cygpath 180 ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 181 SEP="" 182 for dir in $ROOTDIRSRAW ; do 183 ROOTDIRS="$ROOTDIRS$SEP$dir" 184 SEP="|" 185 done 186 OURCYGPATTERN="(^($ROOTDIRS))" 187 # Add a user-defined pattern to the cygpath arguments 188 if [ "$GRADLE_CYGPATTERN" != "" ] ; then 189 OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 190 fi 191 # Now convert the arguments - kludge to limit ourselves to /bin/sh 192 i=0 193 for arg in "$@" ; do 194 CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 195 CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 196 197 if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 198 eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 199 else 200 eval `echo args$i`="\"$arg\"" 201 fi 202 i=$((i+1)) 203 done 204 case $i in 205 (0) set -- ;; 206 (1) set -- "$args0" ;; 207 (2) set -- "$args0" "$args1" ;; 208 (3) set -- "$args0" "$args1" "$args2" ;; 209 (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 210 (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 211 (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 212 (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 213 (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 214 (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 215 esac 216fi 217 218# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 219function splitJvmOpts() { 220 JVM_OPTS=("$@") 221} 222eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 223JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 224 225#TODO: Remove HOME_SYSTEM_PROPERTY_ARGUMENT if https://github.com/gradle/gradle/issues/11433 gets fixed 226HOME_SYSTEM_PROPERTY_ARGUMENT="" 227if [ "$GRADLE_USER_HOME" != "" ]; then 228 HOME_SYSTEM_PROPERTY_ARGUMENT="-Duser.home=$GRADLE_USER_HOME" 229fi 230 231if [[ " ${@} " =~ " --clean " ]]; then 232 cleanCaches=true 233else 234 cleanCaches=false 235fi 236 237if [[ " ${@} " =~ " --no-ci " ]]; then 238 disableCi=true 239else 240 disableCi=false 241fi 242 243# Expand some arguments 244for compact in "--ci" "--strict" "--clean" "--no-ci"; do 245 expanded="" 246 if [ "$compact" == "--ci" ]; then 247 if [ "$disableCi" == "false" ]; then 248 expanded="--strict\ 249 --stacktrace\ 250 -Pandroidx.summarizeStderr\ 251 -Pandroidx.enableAffectedModuleDetection\ 252 -Pandroidx.printTimestamps\ 253 --no-watch-fs\ 254 -Pandroidx.highMemory\ 255 --profile" 256 fi 257 fi 258 if [ "$compact" == "--strict" ]; then 259 expanded="-Pandroidx.validateNoUnrecognizedMessages\ 260 -Pandroidx.verifyUpToDate" 261 if [ "$USE_ANDROIDX_REMOTE_BUILD_CACHE" == "" -o "$USE_ANDROIDX_REMOTE_BUILD_CACHE" == "false" ]; then 262 expanded="$expanded --offline" 263 fi 264 fi 265 # if compact is something else then we parsed the argument above but 266 # still have to remove it (expanded == "") to avoid confusing Gradle 267 268 # check whether this particular compat argument was passed (and therefore needs expansion) 269 if [[ " ${@} " =~ " $compact " ]]; then 270 # Expand an individual argument 271 # Start by making a copy of our list of arguments and iterating through the copy 272 for arg in "$@"; do 273 # Remove this argument from our list of arguments. 274 # By the time we've completed this loop, we will have removed the original copy of 275 # each argument, and potentially re-added a new copy or an expansion of each. 276 shift 277 # Determine whether to expand this argument 278 if [ "$arg" == "$compact" ]; then 279 # Add the expansion to our arguments 280 set -- "$@" $expanded 281 if [ "$expanded" != "" ]; then 282 echo "gradlew expanded '$compact' into '$expanded'" 283 echo 284 fi 285 # We avoid re-adding this argument itself back into the list for two reasons: 286 # 1. This argument might not be directly understood by Gradle 287 # 2. We want to enforce that all behaviors enabled by this flag can be toggled independently, 288 # so we don't want it to be easy to inadvertently check for the presence of this flag 289 # specifically 290 else 291 # Add this argument back into our arguments 292 set -- "$@" "$arg" 293 fi 294 done 295 fi 296done 297 298# workaround for https://github.com/gradle/gradle/issues/18386 299if [[ " ${@} " =~ " --profile " ]]; then 300 mkdir -p reports 301fi 302 303raiseMemory=false 304if [[ " ${@} " =~ " -Pandroidx.highMemory " ]]; then 305 raiseMemory=true 306fi 307if [[ " ${@} " =~ " -Pandroidx.lowMemory " ]]; then 308 if [ "$raiseMemory" == "true" ]; then 309 echo "androidx.lowMemory overriding androidx.highMemory" 310 echo 311 fi 312 raiseMemory=false 313fi 314 315if [ "$raiseMemory" == "true" ]; then 316 # Set the initial heap size to match the max heap size, 317 # by replacing a string like "-Xmx1g" with one like "-Xms1g -Xmx1g" 318 MAX_MEM=32g 319 ORG_GRADLE_JVMARGS="$(echo $ORG_GRADLE_JVMARGS | sed "s/-Xmx\([^ ]*\)/-Xms$MAX_MEM -Xmx$MAX_MEM/")" 320 321 # Increase the compiler cache size: b/260643754 . Remove when updating to JDK 20 ( https://bugs.openjdk.org/browse/JDK-8295724 ) 322 ORG_GRADLE_JVMARGS="$(echo $ORG_GRADLE_JVMARGS | sed "s|$| -XX:ReservedCodeCacheSize=576M|")" 323fi 324 325# check whether the user has requested profiling via yourkit 326yourkitArgPrefix="androidx.profile.yourkitAgentPath" 327yourkitAgentPath="" 328if [[ " ${@}" =~ " -P$yourkitArgPrefix" ]]; then 329 for arg in "$@"; do 330 if echo "$arg" | grep "${yourkitArgPrefix}=" >/dev/null; then 331 yourkitAgentPath="$(echo "$arg" | sed "s/-P${yourkitArgPrefix}=//")" 332 fi 333 done 334 if [ "$yourkitAgentPath" == "" ]; then 335 echo "Error: $yourkitArgPrefix must be set to the path of the YourKit Java agent" >&2 336 exit 1 337 fi 338 if [ ! -e "$yourkitAgentPath" ]; then 339 echo "Error: $yourkitAgentPath does not exist" >&2 340 exit 1 341 fi 342 # add the agent to the path 343 export _JAVA_OPTIONS="$_JAVA_OPTIONS -agentpath:$yourkitAgentPath" 344 # add arguments 345 set -- "$@" --no-daemon --rerun-tasks 346 347 # lots of blank lines because these messages are important 348 echo 349 echo 350 echo 351 echo 352 echo 353 # suggest --clean 354 if [ "$cleanCaches" == "false" ]; then 355 echo "When setting $yourkitArgPrefix you may also want to pass --clean" 356 fi 357 COLOR_YELLOW="\u001B[33m" 358 COLOR_CLEAR="\u001B[0m" 359 360 echo -e "${COLOR_YELLOW}Also be sure to start the YourKit user interface and connect to the appropriate Java process (probably the Gradle Daemon)${COLOR_CLEAR}" 361 echo 362 echo 363 echo 364 echo 365 echo 366fi 367 368if [[ " ${@} " =~ " --scan " ]]; then 369 if [[ " ${@} " =~ " --offline " ]]; then 370 echo "--scan incompatible with --offline" 371 echo "you could try --no-ci" 372 exit 1 373 fi 374fi 375 376function removeCaches() { 377 rm -rf $SCRIPT_PATH/.gradle 378 rm -rf $SCRIPT_PATH/buildSrc/.gradle 379 rm -f $SCRIPT_PATH/local.properties 380 if [ "$GRADLE_USER_HOME" != "" ]; then 381 rm -rf "$GRADLE_USER_HOME" 382 else 383 rm -rf ~/.gradle 384 fi 385 # https://github.com/gradle/gradle/issues/18386 386 rm -rf $SCRIPT_PATH/reports 387 rm -rf $SCRIPT_PATH/build 388 rm -rf $OUT_DIR 389} 390 391# Move any preexisting build scan to make room for a new one 392# After moving a build scan several times it eventually gets deleted 393function rotateBuildScans() { 394 filePrefix="$1" 395 iPlus1="10" 396 for i in $(seq 9 -1 1); do 397 mv "${filePrefix}.${i}.zip" "${filePrefix}.${iPlus1}.zip" 2>/dev/null || true 398 iPlus1=$i 399 done 400 mv ${filePrefix}.zip "${filePrefix}.1.zip" 2>/dev/null || true 401} 402 403function runGradle() { 404 if [ "$TMPDIR" != "" ]; then 405 mkdir -p "$TMPDIR" 406 TMPDIR_ARG="-Djava.io.tmpdir=$TMPDIR" 407 fi 408 409 processOutput=false 410 if [[ " ${@} " =~ " -Pandroidx.validateNoUnrecognizedMessages " ]]; then 411 processOutput=true 412 fi 413 if [[ " ${@} " =~ " -Pandroidx.summarizeStderr " ]]; then 414 processOutput=true 415 fi 416 if [[ "${@} " =~ " -Pandroidx.printTimestamps " ]]; then 417 processOutput=true 418 fi 419 if [ "$processOutput" == "true" ]; then 420 wrapper="$SCRIPT_PATH/development/build_log_processor.sh" 421 else 422 wrapper="" 423 fi 424 425 RETURN_VALUE=0 426 set -- "$@" -Dorg.gradle.projectcachedir="$OUT_DIR/gradle-project-cache" 427 # Disabled in Studio until these errors become shown (b/268380971) or computed more quickly (https://github.com/gradle/gradle/issues/23272) 428 if [[ " ${@} " =~ " --dependency-verification=" ]]; then 429 VERIFICATION_ARGUMENT="" # already specified by caller 430 else 431 VERIFICATION_ARGUMENT=--dependency-verification=strict 432 fi 433 if $wrapper "$JAVACMD" "${JVM_OPTS[@]}" $TMPDIR_ARG -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain $HOME_SYSTEM_PROPERTY_ARGUMENT $TMPDIR_ARG $VERIFICATION_ARGUMENT "$ORG_GRADLE_JVMARGS" "$@"; then 434 RETURN_VALUE=0 435 else 436 # Print AndroidX-specific help message if build fails 437 # Have to do this build-failure detection in gradlew rather than in build.gradle 438 # so that this message still prints even if buildSrc itself fails 439 echo 440 echo For help with unexpected failures, see development/diagnose-build-failure/README.md 441 echo 442 RETURN_VALUE=1 443 fi 444 445 # If the caller specified where to save data, then also save the build scan data 446 if [ "$DIST_DIR" != "" ]; then 447 if [ "$GRADLE_USER_HOME" != "" ]; then 448 scanDir="$GRADLE_USER_HOME/build-scan-data" 449 if [ -e "$scanDir" ]; then 450 if [[ "$DISALLOW_TASK_EXECUTION" != "" ]]; then 451 zipPrefix="$DIST_DIR/scan-up-to-date" 452 else 453 zipPrefix="$DIST_DIR/scan" 454 fi 455 rotateBuildScans "$zipPrefix" 456 zipPath="${zipPrefix}.zip" 457 cd "$GRADLE_USER_HOME/build-scan-data" 458 zip -q -r "$zipPath" . 459 cd - 460 fi 461 fi 462 fi 463 return $RETURN_VALUE 464} 465 466if [ "$cleanCaches" == true ]; then 467 echo "IF ./gradlew --clean FIXES YOUR BUILD; OPEN A BUG." 468 echo "In nearly all cases, it should not be necessary to run a clean build." 469 echo 470 # one case where it is convenient to have a clean build is for double-checking that a build failure isn't due to an incremental build failure 471 # another case where it is convenient to have a clean build is for performance testing 472 # another case where it is convenient to have a clean build is when you're modifying the build and may have introduced some errors but haven't shared your changes yet (at which point you should have fixed the errors) 473 474 echo "Stopping Gradle daemons" 475 runGradle --stop || true 476 echo 477 478 backupDir=~/androidx-build-state-backup 479 ./development/diagnose-build-failure/impl/backup-state.sh "$backupDir" --move # prints that it is saving state into this dir" 480 481 echo "To restore this state later, run:" 482 echo 483 echo " ./development/diagnose-build-failure/impl/restore-state.sh $backupDir" 484 echo 485 echo "Running Gradle" 486 echo 487fi 488 489if [[ "$DISALLOW_TASK_EXECUTION" != "" ]]; then 490 echo "Setting 'DISALLOW_TASK_EXECUTION' directly is forbidden. Did you mean -Pandroidx.verifyUpToDate ?" 491 echo "See TaskUpToDateValidator.java for more information" 492 exit 1 493fi 494 495runGradle "$@" 496# Check whether we were given the "-Pandroidx.verifyUpToDate" argument 497if [[ " ${@} " =~ " -Pandroidx.verifyUpToDate " ]]; then 498 # Re-run Gradle, and find all tasks that are unexpectly out of date 499 if ! DISALLOW_TASK_EXECUTION=true runGradle "$@" --continue; then 500 echo >&2 501 echo "TaskUpToDateValidator's second build failed. To reproduce, try running './gradlew -Pandroidx.verifyUpToDate <failing tasks>'" >&2 502 exit 1 503 fi 504fi 505