diff --git a/.github/workflows/npm_release.yml b/.github/workflows/npm_release.yml index 2b35ad81d..4ef2fc038 100644 --- a/.github/workflows/npm_release.yml +++ b/.github/workflows/npm_release.yml @@ -169,9 +169,6 @@ jobs: key: ccache-test-${{ github.sha }} restore-keys: ccache-test- - name: Configure build caches - # no org.gradle.caching here: the SBG AST tests spawn nested `gradlew -b` - # builds that fail with "Build cache controller already set" when the - # build cache is on run: | command -v ccache || sudo apt-get install -y ccache ccache --version @@ -181,7 +178,7 @@ jobs: # identification (the default) would invalidate the whole cache echo "CCACHE_COMPILERCHECK=content" >> $GITHUB_ENV mkdir -p ~/.gradle - printf 'org.gradle.parallel=true\n' >> ~/.gradle/gradle.properties + printf 'org.gradle.parallel=true\norg.gradle.caching=true\n' >> ~/.gradle/gradle.properties - name: Install Dependencies run: | npm install diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 223c41ee9..9c7bdd760 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -141,9 +141,6 @@ jobs: key: ccache-test-${{ github.sha }} restore-keys: ccache-test- - name: Configure build caches - # no org.gradle.caching here: the SBG AST tests spawn nested `gradlew -b` - # builds that fail with "Build cache controller already set" when the - # build cache is on run: | command -v ccache || sudo apt-get install -y ccache ccache --version @@ -153,7 +150,7 @@ jobs: # identification (the default) would invalidate the whole cache echo "CCACHE_COMPILERCHECK=content" >> $GITHUB_ENV mkdir -p ~/.gradle - printf 'org.gradle.parallel=true\n' >> ~/.gradle/gradle.properties + printf 'org.gradle.parallel=true\norg.gradle.caching=true\n' >> ~/.gradle/gradle.properties - name: Install Dependencies run: | npm install diff --git a/build.gradle b/build.gradle index 71f536ec2..bf5baf0d9 100644 --- a/build.gradle +++ b/build.gradle @@ -71,19 +71,18 @@ task createDistDir { def getCCacheVersion = { -> try { - def ccacheVersionOutput = new ByteArrayOutputStream() - exec { + return providers.exec { commandLine "ccache", "--version" - standardOutput = ccacheVersionOutput - } - - return ccacheVersionOutput.toString().trim() + }.standardOutput.asText.get().trim() } catch (all) { return 'CCache not found!' } } task getPackageVersion { + def packageVersion = findProperty("packageVersion") + def preReleaseVersion = findProperty("preReleaseVersion") + doLast { String content = new File("$rootDir/package.json").getText("UTF-8") def jsonSlurper = new JsonSlurper() @@ -93,14 +92,14 @@ task getPackageVersion { println "Using runtime version from package.json '${pVersion}'" - if (project.hasProperty("packageVersion") && packageVersion != "") { + if (packageVersion != null && packageVersion != "") { pVersion += "-" + packageVersion println "Using packageVersion property '${pVersion}'" } - if (project.hasProperty("preReleaseVersion")) { + if (preReleaseVersion != null) { pVersion += "-" + preReleaseVersion println "Adding preReleaseVersion property '${pVersion}' to package version" @@ -115,8 +114,10 @@ task getPackageVersion { } task getCommitVersion { + def gitCommitVersion = findProperty("gitCommitVersion") + doLast { - if (project.hasProperty("gitCommitVersion")) { + if (gitCommitVersion != null) { println "Using commit version property " + gitCommitVersion arVersion = gitCommitVersion } else if ("$System.env.GIT_COMMIT" != "null") { @@ -461,7 +462,7 @@ def getRunTestsBuildArguments = { taskName -> } else { arguments.add("./gradlew") } - arguments += ["-b", "runtests.gradle", taskName] + arguments += ["-p", "runtests", taskName] if (onlyX86) { arguments.add("-PonlyX86") } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 2c3521197..b1b8ef56b 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 09523c0e5..eb84db68d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,9 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip networkTimeout=10000 +retries=0 +retryBackOffMs=500 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index f5feea6d6..249efbb03 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -173,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -206,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a2183..a51ec4f58 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -19,12 +19,12 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -51,7 +51,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,30 +65,18 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/test-app/app/build.gradle b/test-app/app/build.gradle index 9fbc263bf..85368a6ae 100644 --- a/test-app/app/build.gradle +++ b/test-app/app/build.gradle @@ -22,6 +22,7 @@ import groovy.json.JsonSlurper import groovy.xml.XmlSlurper +import com.android.build.api.artifact.SingleArtifact import org.apache.commons.io.FileUtils import javax.inject.Inject @@ -38,7 +39,6 @@ apply plugin: "com.android.application" apply from: "gradle-helpers/BuildToolTask.gradle" apply from: "gradle-helpers/CustomExecutionLogger.gradle" apply from: "gradle-helpers/AnalyticsCollector.gradle" -apply plugin: 'kotlin-android' apply plugin: 'kotlin-parcelize' def onlyX86 = project.hasProperty("onlyX86") @@ -221,10 +221,6 @@ android { applyBeforePluginGradleConfiguration() - kotlinOptions { - jvmTarget = '17' - } - compileSdk computeCompileSdkVersion() buildToolsVersion = computeBuildToolsVersion() @@ -278,29 +274,14 @@ android { setAppIdentifier() applyPluginGradleConfigurations() applyAppGradleConfiguration() +} - def initializeMergedAssetsOutputPath = { -> - android.applicationVariants.configureEach { variant -> - if (variant.buildType.name == project.selectedBuildType) { - def task - if (variant.metaClass.respondsTo(variant, "getMergeAssetsProvider")) { - def provider = variant.getMergeAssetsProvider() - task = provider.get() - } else { - // fallback for older android gradle plugin versions - task = variant.getMergeAssets() - } - for (File file : task.getOutputs().getFiles()) { - if (!file.getPath().contains("${File.separator}incremental${File.separator}")) { - project.ext.mergedAssetsOutputPath = file.getPath() - break - } - } - } - } - } - - initializeMergedAssetsOutputPath() +def selectedVariantCompileClasspaths = [] +androidComponents { + onVariants(selector().withBuildType(project.selectedBuildType)) { variant -> + selectedVariantCompileClasspaths.add(variant.compileClasspath) + project.ext.mergedAssetsOutputPath = variant.artifacts.get(SingleArtifact.ASSETS.INSTANCE) + } } def externalRuntimeExists = !findProject(':runtime').is(null) @@ -567,25 +548,21 @@ class EmptyRunnable implements Runnable { def getMergedAssetsOutputPath() { if (!project.hasProperty("mergedAssetsOutputPath")) { - // mergedAssetsOutputPath not found fallback to the default value for android gradle plugin 3.5.1 - project.ext.mergedAssetsOutputPath = "$projectDir/build/intermediates/merged_assets/" + project.selectedBuildType + "/out" + throw new GradleException("No ${project.selectedBuildType} variant was configured, so there are no merged assets to copy the metadata into.") } - return project.ext.mergedAssetsOutputPath + def mergedAssets = project.ext.mergedAssetsOutputPath + return mergedAssets instanceof Provider ? mergedAssets.get().asFile.path : mergedAssets.toString() } // Discover all jars and dynamically create tasks for the extraction of each of them project.ext.allJars = [] -allprojects { - afterEvaluate { project -> - def buildType = project.selectedBuildType - def jars = [] - def artifactType = Attribute.of('artifactType', String) - android.applicationVariants.configureEach { variant -> - if (variant.buildType.name == buildType) { - variant.getCompileClasspath(null).each { fileDependency -> - processJar(fileDependency, jars) - } - } +afterEvaluate { + def jars = [] + selectedVariantCompileClasspaths.each { compileClasspath -> + // Carries the producer tasks of generated jars (e.g. the compile-time R class). + cleanupAllJars.inputs.files(compileClasspath) + compileClasspath.each { fileDependency -> + processJar(fileDependency, jars) } } } @@ -637,8 +614,9 @@ task 'cleanupAllJars' { outputs.files cleanupAllJarsTimestamp + def allJars = project.ext.allJars doLast { - def allDests = project.ext.allJars*.outputDir*.name + def allDests = allJars*.outputDir*.name def dir = new File(extractedDependenciesDir) if (dir.exists()) { dir.eachDir { @@ -701,15 +679,26 @@ def resolveCompileSdkPlatformName(File sdkDirectory, String compileSdkVersion) { "Install the matching SDK Platform with the Android SDK Manager.") } +def compileSdkPlatformName() { + if (android.compileSdk != null) { + return android.compileSdkMinor ? "android-${android.compileSdk}.${android.compileSdkMinor}" : "android-${android.compileSdk}" + } + if (android.compileSdkPreview != null) { + return "android-${android.compileSdkPreview}" + } + throw new GradleException("compileSdk is not set.") +} + task 'collectAllJars' { dependsOn extractAllJars description = "gathers all paths to jar dependencies before building metadata with them" - def sdkPath = android.sdkDirectory.getAbsolutePath() + def sdkDirectory = androidComponents.sdkComponents.sdkDirectory doFirst { - def platformName = resolveCompileSdkPlatformName(android.sdkDirectory, android.compileSdkVersion) - def androidJar = sdkPath + "/platforms/" + platformName + "/android.jar" + def sdkDir = sdkDirectory.get().asFile + def platformName = resolveCompileSdkPlatformName(sdkDir, compileSdkPlatformName()) + def androidJar = new File(sdkDir, "platforms/" + platformName + "/android.jar").path def allJarPaths = new LinkedList() allJarPaths.add(androidJar) @@ -786,172 +775,33 @@ task buildMetadata(type: BuildToolTask) { inputs.files(tasks.getByPath(':android-metadata-generator:jar')) } - - - android.applicationVariants.all { variant -> - // The generator only reads the selected build type's classes (see doFirst), - // so depending on the other variant's tasks would just force a second full - // app build without affecting the produced metadata. - if (variant.buildType.name != project.ext.selectedBuildType) { - return - } - - def buildTypeName = variant.buildType.name.capitalize() - def mergeShadersTaskName = "merge${buildTypeName}Shaders" - def mergeShadersTask = tasks.findByName(mergeShadersTaskName) - - if (mergeShadersTask) { - dependsOn mergeShadersTask - } - - def compileJavaWithJavacTaskName = "compile${buildTypeName}JavaWithJavac" - def compileJavaWithJavacTask = tasks.findByName(compileJavaWithJavacTaskName) - - - if (compileJavaWithJavacTask) { - dependsOn compileJavaWithJavacTask - } - - def compileKotlinTaskName = "compile${buildTypeName}Kotlin" - def compileKotlinTask = tasks.findByName(compileKotlinTaskName) - - - if (compileKotlinTask) { - dependsOn compileKotlinTask - } - - - def mergeDexTaskName = "mergeDex${buildTypeName}" - def mergeDexTask = tasks.findByName(mergeDexTaskName) - - if (mergeDexTask) { - dependsOn mergeDexTask - } - - def checkDuplicateClassesTaskName = "check${buildTypeName}DuplicateClasses" - def checkDuplicateClassesTask = tasks.findByName(checkDuplicateClassesTaskName) - - if (checkDuplicateClassesTask) { - dependsOn checkDuplicateClassesTask - } - - def generateBuildConfigTaskName = "generate${buildTypeName}BuildConfig" - def generateBuildConfigTask = tasks.findByName(generateBuildConfigTaskName) - - if (generateBuildConfigTask) { - dependsOn generateBuildConfigTask - } - - def dexBuilderTaskName = "dexBuilder${buildTypeName}" - def dexBuilderTask = tasks.findByName(dexBuilderTaskName) - - if (dexBuilderTask) { - dependsOn dexBuilderTask - } - - - def mergeExtDexTaskName = "mergeExtDex${buildTypeName}" - def mergeExtDexTask = tasks.findByName(mergeExtDexTaskName) - - if (mergeExtDexTask) { - dependsOn mergeExtDexTask - } - - def mergeLibDexTaskName = "mergeLibDex${buildTypeName}" - def mergeLibDexTask = tasks.findByName(mergeLibDexTaskName) - - if (mergeLibDexTask) { - dependsOn mergeLibDexTask - } - - def mergeProjectDexTaskName = "mergeProjectDex${buildTypeName}" - def mergeProjectDexTask = tasks.findByName(mergeProjectDexTaskName) - - if (mergeProjectDexTask) { - dependsOn mergeProjectDexTask - } - - def syncLibJarsTaskName = "sync${buildTypeName}LibJars" - def syncLibJarsTask = tasks.findByName(syncLibJarsTaskName) - - if (syncLibJarsTask) { - dependsOn syncLibJarsTask - } - - def mergeJavaResourceTaskName = "merge${buildTypeName}JavaResource" - def mergeJavaResourceTask = tasks.findByName(mergeJavaResourceTaskName) - - if (mergeJavaResourceTask) { - dependsOn mergeJavaResourceTask - } - - def mergeJniLibFoldersTaskName = "merge${buildTypeName}JniLibFolders" - def mergeJniLibFoldersTask = tasks.findByName(mergeJniLibFoldersTaskName) - - if (mergeJniLibFoldersTask) { - dependsOn mergeJniLibFoldersTask - } - - def mergeNativeLibsTaskName = "merge${buildTypeName}NativeLibs" - def mergeNativeLibsTask = tasks.findByName(mergeNativeLibsTaskName) - - if (mergeNativeLibsTask) { - dependsOn mergeNativeLibsTask - } - - def stripDebugSymbolsTaskName = "strip${buildTypeName}DebugSymbols" - def stripDebugSymbolsTask = tasks.findByName(stripDebugSymbolsTaskName) - - if (stripDebugSymbolsTask) { - dependsOn stripDebugSymbolsTask - } - - def validateSigningTaskName = "validateSigning${buildTypeName}" - def validateSigningTask = tasks.findByName(validateSigningTaskName) - - if (validateSigningTask) { - dependsOn validateSigningTask - } - - - def extractProguardFilesTaskName = "extractProguardFiles" - def extractProguardFilesTask = tasks.findByName(extractProguardFilesTaskName) - - if (extractProguardFilesTask) { - dependsOn extractProguardFilesTask - } - - - // def compileArtProfileTaskName = "compile${buildTypeName}ArtProfile" - // def compileArtProfileTask = tasks.findByName(compileArtProfileTaskName) - - // if (compileArtProfileTask) { - // dependsOn compileArtProfileTask - // } - - - def extractNativeSymbolTablesTaskName = "extract${buildTypeName}NativeSymbolTables" - def extractNativeSymbolTablesTask = tasks.findByName(extractNativeSymbolTablesTaskName) - - if (extractNativeSymbolTablesTask) { - dependsOn extractNativeSymbolTablesTask - } - - - // def optimizeResourcesTaskName = "optimize${buildTypeName}Resources" - // def optimizeResourcesTask = tasks.findByName(optimizeResourcesTaskName) - - // if (optimizeResourcesTask) { - // dependsOn optimizeResourcesTask - // } - - def bundleResourcesTaskName = "bundle${buildTypeName}Resources" - def bundleResourcesTask = tasks.findByName(bundleResourcesTaskName) - - if (bundleResourcesTask) { - dependsOn bundleResourcesTask - } - + // The generator only reads the selected build type's classes (see doFirst), so + // the other build types' tasks are left out. Names are matched when the task graph + // is built, since several of these tasks only exist for some configurations. + def buildTypeName = project.ext.selectedBuildType.capitalize() + def metadataInputTaskNames = [ + "merge${buildTypeName}Shaders", + "compile${buildTypeName}JavaWithJavac", + "compile${buildTypeName}Kotlin", + "mergeDex${buildTypeName}", + "check${buildTypeName}DuplicateClasses", + "generate${buildTypeName}BuildConfig", + "dexBuilder${buildTypeName}", + "mergeExtDex${buildTypeName}", + "mergeLibDex${buildTypeName}", + "mergeProjectDex${buildTypeName}", + "sync${buildTypeName}LibJars", + "merge${buildTypeName}JavaResource", + "merge${buildTypeName}JniLibFolders", + "merge${buildTypeName}NativeLibs", + "strip${buildTypeName}DebugSymbols", + "validateSigning${buildTypeName}", + "extractProguardFiles", + "extract${buildTypeName}NativeSymbolTables", + "bundle${buildTypeName}Resources" + ] + dependsOn { + metadataInputTaskNames.findAll { tasks.names.contains(it) } } dependsOn copyMetadataFilters @@ -983,11 +833,19 @@ task buildMetadata(type: BuildToolTask) { inputs.dir(kotlinClassesDir) } + def builtInKotlinClassesDir = layout.buildDirectory.dir("intermediates/built_in_kotlinc").get().asFile + if (builtInKotlinClassesDir.exists()) { + inputs.dir(builtInKotlinClassesDir) + } + outputs.files("$METADATA_OUT_PATH/treeNodeStream.dat", "$METADATA_OUT_PATH/treeStringsStream.dat", "$METADATA_OUT_PATH/treeValueStream.dat") workingDir "$BUILD_TOOLS_PATH" mainClass = "-jar" + def selectedBuildType = project.ext.selectedBuildType + def subprojectBuildDirectories = rootProject.subprojects.collect { it.layout.buildDirectory } + doFirst { // get compiled classes to pass to metadata generator // these need to be called after the classes have compiled @@ -995,12 +853,12 @@ task buildMetadata(type: BuildToolTask) { def classesSubDirs = [] def kotlinClassesSubDirs = [] - def selectedBuildType = project.ext.selectedBuildType + def builtInKotlinClassesDirs = [] - rootProject.subprojects { + subprojectBuildDirectories.each { buildDirectory -> - def projectClassesDir = it.layout.buildDirectory.dir("intermediates/javac").get().asFile - def projectKotlinClassesDir = it.layout.buildDirectory.dir("tmp/kotlin-classes").get().asFile + def projectClassesDir = buildDirectory.dir("intermediates/javac").get().asFile + def projectKotlinClassesDir = buildDirectory.dir("tmp/kotlin-classes").get().asFile if (projectClassesDir.exists()) { def projectClassesSubDirs = projectClassesDir.listFiles() @@ -1019,6 +877,15 @@ task buildMetadata(type: BuildToolTask) { } } } + + // Kotlin compiled by AGP itself lands in //classes. + def builtInKotlinBuildTypeDir = buildDirectory.dir("intermediates/built_in_kotlinc/$selectedBuildType").get().asFile + builtInKotlinBuildTypeDir.listFiles()?.each { compileTaskDir -> + def compiledClassesDir = new File(compileTaskDir, "classes") + if (compiledClassesDir.isDirectory()) { + builtInKotlinClassesDirs.add(compiledClassesDir) + } + } } def generatedClasses = new LinkedList() @@ -1034,6 +901,10 @@ task buildMetadata(type: BuildToolTask) { } } + for (File compiledKotlinDir : builtInKotlinClassesDirs) { + generatedClasses.add(compiledKotlinDir.getAbsolutePath()) + } + def store = new ArrayList() for (String dir : generatedClasses) { listf(dir, store) @@ -1081,12 +952,13 @@ task generateTypescriptDefinitions(type: BuildToolTask) { } def paramz = new ArrayList() + def sdkDirectory = androidComponents.sdkComponents.sdkDirectory workingDir "$BUILD_TOOLS_PATH" mainClass = "-jar" doFirst { - def includeDirs = ["com.android.support", "/platforms/" + resolveCompileSdkPlatformName(android.sdkDirectory, android.compileSdkVersion)] + def includeDirs = ["com.android.support", "/platforms/" + resolveCompileSdkPlatformName(sdkDirectory.get().asFile, compileSdkPlatformName())] delete "$TYPINGS_PATH" @@ -1161,16 +1033,20 @@ copyTypings.onlyIf { generateTypescriptDefinitions.finalizedBy(copyTypings) task 'validateAppIdMatch' { + def expectedAppIdentifier = project.hasProperty("nsApplicationIdentifier") && !project.hasProperty("release") ? project.nsApplicationIdentifier : null + def androidExtension = android + doLast { def lineSeparator = System.getProperty("line.separator") - if (project.hasProperty("nsApplicationIdentifier") && !project.hasProperty("release")) { - if (project.nsApplicationIdentifier != android.defaultConfig.applicationId && android.namespace != appIdentifier) { + if (expectedAppIdentifier != null) { + def actualAppIdentifier = androidExtension.defaultConfig.applicationId + if (expectedAppIdentifier != actualAppIdentifier && androidExtension.namespace != expectedAppIdentifier) { def errorMessage = "${lineSeparator}WARNING: The Application identifier is different from the one inside \"package.json\" file.$lineSeparator" + "NativeScript CLI might not work properly.$lineSeparator" + "Remove applicationId from app.gradle and update the \"nativescript.id\" in package.json.$lineSeparator" + - "Actual: ${android.defaultConfig.applicationId}$lineSeparator" + - "Expected(from \"package.json\"): ${project.nsApplicationIdentifier}$lineSeparator" + "Actual: ${actualAppIdentifier}$lineSeparator" + + "Expected(from \"package.json\"): ${expectedAppIdentifier}$lineSeparator" logger.error(errorMessage) } diff --git a/test-app/app/gradle-helpers/BuildToolTask.gradle b/test-app/app/gradle-helpers/BuildToolTask.gradle index c744f570b..29dbde0e7 100644 --- a/test-app/app/gradle-helpers/BuildToolTask.gradle +++ b/test-app/app/gradle-helpers/BuildToolTask.gradle @@ -1,6 +1,6 @@ import static org.gradle.internal.logging.text.StyledTextOutput.Style -class BuildToolTask extends JavaExec { +abstract class BuildToolTask extends JavaExec { void setOutputs(def logger) { def logFile = new File("$workingDir/${name}.log") if(logFile.exists()) { diff --git a/test-app/build-tools/android-dts-generator b/test-app/build-tools/android-dts-generator index 82e481df9..5fcf61133 160000 --- a/test-app/build-tools/android-dts-generator +++ b/test-app/build-tools/android-dts-generator @@ -1 +1 @@ -Subproject commit 82e481df945ba1221f13a06d374538a2bfd280dd +Subproject commit 5fcf611330bd9eb60d9bb45d5b37251980b127ab diff --git a/test-app/build-tools/android-metadata-generator/build.gradle b/test-app/build-tools/android-metadata-generator/build.gradle index 85ca0723e..4c9c71095 100644 --- a/test-app/build-tools/android-metadata-generator/build.gradle +++ b/test-app/build-tools/android-metadata-generator/build.gradle @@ -45,8 +45,8 @@ compileJava { compileJava.outputs.dir("$rootDir/dist/classes") compileKotlin { - kotlinOptions { - jvmTarget = '17' + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 allWarningsAsErrors = true } } @@ -61,7 +61,7 @@ dependencies { api "org.apache.bcel:bcel:${ns_default_bcel_version}" api "com.google.code.gson:gson:${ns_default_gson_version}" - api group: 'org.jetbrains.kotlin', name: 'kotlin-metadata-jvm', version: "${ns_default_kotlinx_metadata_jvm_version}" + api "org.jetbrains.kotlin:kotlin-metadata-jvm:${ns_default_kotlinx_metadata_jvm_version}" implementation files("./src/libs/dx.jar") testImplementation "junit:junit:${ns_default_junit_version}" diff --git a/test-app/build-tools/static-binding-generator/build.gradle b/test-app/build-tools/static-binding-generator/build.gradle index 42fd71f04..bb3007cae 100644 --- a/test-app/build-tools/static-binding-generator/build.gradle +++ b/test-app/build-tools/static-binding-generator/build.gradle @@ -19,7 +19,7 @@ dependencies { api "org.ow2.asm:asm:${ns_default_asm_version}" api "org.ow2.asm:asm-util:${ns_default_asm_util_version}" api "org.apache.bcel:bcel:${ns_default_bcel_version}" - api group: 'org.json', name: 'json', version: "${ns_default_json_version}" + api "org.json:json:${ns_default_json_version}" api "commons-io:commons-io:${ns_default_commons_io_version}" api "com.google.code.gson:gson:${ns_default_gson_version}" api "com.google.googlejavaformat:google-java-format:${ns_default_google_java_format_version}" diff --git a/test-app/build-tools/static-binding-generator/runtests.gradle b/test-app/build-tools/static-binding-generator/runtests.gradle index d46dd2141..ae3b50e9d 100644 --- a/test-app/build-tools/static-binding-generator/runtests.gradle +++ b/test-app/build-tools/static-binding-generator/runtests.gradle @@ -26,7 +26,7 @@ dependencies { api "org.ow2.asm:asm:${ns_default_asm_version}" api "org.ow2.asm:asm-util:${ns_default_asm_util_version}" api "org.apache.bcel:bcel:${ns_default_bcel_version}" - api group: 'org.json', name: 'json', version: "${ns_default_json_version}" + api "org.json:json:${ns_default_json_version}" api "commons-io:commons-io:${ns_default_commons_io_version}" api "com.google.code.gson:gson:${ns_default_gson_version}" api "com.google.googlejavaformat:google-java-format:${ns_default_google_java_format_version}" diff --git a/test-app/build.gradle b/test-app/build.gradle index 9799ab860..4196ec3f2 100644 --- a/test-app/build.gradle +++ b/test-app/build.gradle @@ -134,10 +134,8 @@ version of the {N} CLI install a previous version of the runtime package - 'tns def computeKotlinVersion = { -> project.hasProperty("kotlinVersion") ? kotlinVersion : "${ns_default_kotlin_version}" } def computeBuildToolsVersion = { -> project.hasProperty("androidBuildToolsVersion") ? androidBuildToolsVersion : "${NS_DEFAULT_ANDROID_BUILD_TOOLS_VERSION}" } - def computeR8Version = { -> project.hasProperty("r8Version") ? r8Version : "${NS_DEFAULT_R8_VERSION}" } def kotlinVersion = computeKotlinVersion() def androidBuildToolsVersion = computeBuildToolsVersion() - def r8Version = computeR8Version() repositories { google() @@ -145,9 +143,7 @@ version of the {N} CLI install a previous version of the runtime package - 'tns } dependencies { classpath "com.android.tools.build:gradle:$androidBuildToolsVersion" - classpath "com.android.tools:r8:$r8Version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" - classpath "org.apache.groovy:groovy-all:4.0.21" } } @@ -157,6 +153,17 @@ allprojects { mavenCentral() } beforeEvaluate { project -> + // Subprojects see the root's extra properties (outLogger, nativescriptDependencies, + // additional_gradle.properties values, ...) as their own, since Gradle no longer + // resolves undeclared properties from the parent project. -P values are left alone + // so they keep precedence in the subproject. + def startProjectProperties = gradle.startParameter.projectProperties + rootProject.ext.properties.each { name, value -> + if (!startProjectProperties.containsKey(name)) { + project.ext.set(name, value) + } + } + if (rootProject.hasProperty("userDefinedGradleProperties")) { rootProject.ext.userDefinedGradleProperties.each { entry -> def propertyName = entry.getKey() diff --git a/test-app/gradle.properties b/test-app/gradle.properties index e58b0da6b..963fd89b0 100644 --- a/test-app/gradle.properties +++ b/test-app/gradle.properties @@ -15,16 +15,13 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. org.gradle.jvmargs=-Xmx16384M -android.enableJetifier=true android.useAndroidX=true # Default versions used throughout the gradle configurations -NS_DEFAULT_BUILD_TOOLS_VERSION=35.0.0 +NS_DEFAULT_BUILD_TOOLS_VERSION=36.0.0 NS_DEFAULT_COMPILE_SDK_VERSION=35 NS_DEFAULT_MIN_SDK_VERSION=21 -NS_DEFAULT_ANDROID_BUILD_TOOLS_VERSION=8.13.2 -# R8 8.x cannot read Kotlin 2.4 metadata (needs 9.1.29+), so the AGP-bundled R8 is overridden. -NS_DEFAULT_R8_VERSION=9.1.43 +NS_DEFAULT_ANDROID_BUILD_TOOLS_VERSION=9.4.1 ns_default_androidx_appcompat_version = 1.7.0 ns_default_androidx_exifinterface_version = 1.3.7 diff --git a/test-app/gradle/wrapper/gradle-wrapper.jar b/test-app/gradle/wrapper/gradle-wrapper.jar index 249e5832f..1b33c55ba 100644 Binary files a/test-app/gradle/wrapper/gradle-wrapper.jar and b/test-app/gradle/wrapper/gradle-wrapper.jar differ diff --git a/test-app/gradle/wrapper/gradle-wrapper.properties b/test-app/gradle/wrapper/gradle-wrapper.properties index c1803733d..7e7d24f6f 100644 --- a/test-app/gradle/wrapper/gradle-wrapper.properties +++ b/test-app/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ -#Tue Feb 11 10:56:28 AST 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/test-app/gradlew b/test-app/gradlew index a69d9cb6c..23d15a936 100755 --- a/test-app/gradlew +++ b/test-app/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +82,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -133,22 +133,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,16 +200,20 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/test-app/gradlew.bat b/test-app/gradlew.bat index f127cfd49..db3a6ac20 100644 --- a/test-app/gradlew.bat +++ b/test-app/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -26,6 +28,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -42,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -56,22 +59,22 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/test-app/runtests.gradle b/test-app/runtests/build.gradle similarity index 74% rename from test-app/runtests.gradle rename to test-app/runtests/build.gradle index aeb6f4951..8d755559d 100644 --- a/test-app/runtests.gradle +++ b/test-app/runtests/build.gradle @@ -1,3 +1,12 @@ +// Standalone build (see settings.gradle next to it) that installs the test app on a +// device and collects the results. Everything runs from the test-app directory, since +// the node tools and the nested gradlew calls resolve paths against the working directory. +def testAppDir = rootDir.parentFile + +tasks.withType(Exec).configureEach { + workingDir = testAppDir +} + def isWinOs = System.properties['os.name'].toLowerCase().contains('windows') def runOnDevice = project.hasProperty("runOnDevice") def runOnDeviceOrEmulator = runOnDevice ? "-d" : "-e" @@ -8,7 +17,7 @@ def selectedAbis = project.hasProperty("abis") ? project.property("abis") : null // task deleteDist(type: Delete) { // doFirst { -// delete "$rootDir/dist" +// delete "$testAppDir/dist" // } // } @@ -17,9 +26,9 @@ task waitForEmulatorToStart(type: Exec) { println "Waiting for emulator to start..." if (isWinOs) { - commandLine "cmd", "/c", "node", "$rootDir\\tools\\make_sure_emulator_is_ready.js", runOnDeviceOrEmulator + commandLine "cmd", "/c", "node", "$testAppDir\\tools\\make_sure_emulator_is_ready.js", runOnDeviceOrEmulator } else { - commandLine "node", "$rootDir/tools/make_sure_emulator_is_ready.js", runOnDeviceOrEmulator + commandLine "node", "$testAppDir/tools/make_sure_emulator_is_ready.js", runOnDeviceOrEmulator } } } @@ -97,7 +106,7 @@ task startInstalledApk(type: Exec) { task createDistFolder { doLast { - def distDir = file("$rootDir/dist") + def distDir = file("$testAppDir/dist") distDir.mkdirs() } } @@ -107,28 +116,28 @@ task waitForUnitTestResultFile(type: Exec) { println "Waiting for tests to finish..." if (isWinOs) { - commandLine "cmd", "/c", "node", "$rootDir\\tools\\try_to_find_test_result_file.js", runOnDeviceOrEmulator + commandLine "cmd", "/c", "node", "$testAppDir\\tools\\try_to_find_test_result_file.js", runOnDeviceOrEmulator } else { - commandLine "node", "$rootDir/tools/try_to_find_test_result_file.js", runOnDeviceOrEmulator + commandLine "node", "$testAppDir/tools/try_to_find_test_result_file.js", runOnDeviceOrEmulator } } } task copyResultToDist(type: Copy) { - from "$rootDir/android_unit_test_results.xml" - into "$rootDir/dist" + from "$testAppDir/android_unit_test_results.xml" + into "$testAppDir/dist" } task deleteRootLevelResult(type: Delete) { - delete "$rootDir/android_unit_test_results.xml" + delete "$testAppDir/android_unit_test_results.xml" } task verifyResults(type: Exec) { doFirst { if (isWinOs) { - commandLine "cmd", "/c", "node", "$rootDir\\tools\\check_if_tests_passed.js", "$rootDir\\dist\\android_unit_test_results.xml" + commandLine "cmd", "/c", "node", "$testAppDir\\tools\\check_if_tests_passed.js", "$testAppDir\\dist\\android_unit_test_results.xml" } else { - commandLine "node", "$rootDir/tools/check_if_tests_passed.js", "$rootDir/dist/android_unit_test_results.xml" + commandLine "node", "$testAppDir/tools/check_if_tests_passed.js", "$testAppDir/dist/android_unit_test_results.xml" } } } diff --git a/test-app/runtests/settings.gradle b/test-app/runtests/settings.gradle new file mode 100644 index 000000000..2c6b7506f --- /dev/null +++ b/test-app/runtests/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'runtests' diff --git a/test-app/runtime/build.gradle b/test-app/runtime/build.gradle index 16a6951e0..8dd0282e2 100644 --- a/test-app/runtime/build.gradle +++ b/test-app/runtime/build.gradle @@ -103,7 +103,6 @@ android { defaultConfig { minSdkVersion NS_DEFAULT_MIN_SDK_VERSION as int - targetSdkVersion NS_DEFAULT_COMPILE_SDK_VERSION as int externalNativeBuild { cmake { @@ -144,10 +143,18 @@ android { targetCompatibility JavaVersion.VERSION_17 } + testOptions { + targetSdk = NS_DEFAULT_COMPILE_SDK_VERSION as int + } + + lint { + targetSdk = NS_DEFAULT_COMPILE_SDK_VERSION as int + } + buildTypes { release { minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } externalNativeBuild { @@ -241,9 +248,6 @@ tasks.configureEach { task -> if (taskName.contains("Strip")) { task.finalizedBy(revertVersionFile) } - if ((taskName == "bundleDebug") || (taskName == "bundleRelease")) { - task.finalizedBy createPackageConfigFileTask(taskName) - } // Do not wire :app:buildMetadata onto runtime tasks: the app declares its own // dependency on it (merge*Assets), and forcing it here drags a full :app build @@ -301,35 +305,3 @@ task revertVersionFile(type: Exec) { repositories { mavenCentral() } - -def createPackageConfigFileTask(taskName) { - def mode = (taskName == "bundleDebug") ? "debug" : "release" - - return tasks.create(name: "packageConfigFileTaskFor${mode}",) { - def sdkDir = android.getSdkDirectory().getAbsolutePath() - doFirst { - def pathToAAR = "${buildDir}/outputs/aar/${project.archivesBaseName}-${mode}.aar" - - if (new File(pathToAAR).exists()) { - def isWinOs = System.properties['os.name'].toLowerCase().contains('windows') - - def aaptCommand = new File(sdkDir, "/build-tools/$project.ext._buildToolsVersion/aapt").getAbsolutePath() - if (isWinOs) { - aaptCommand += ".exe" - } - - def removeCmdParams = new ArrayList([aaptCommand, "remove", pathToAAR, "config.json"]) - exec { - ignoreExitValue = true - workingDir "$projectDir/src/main" - commandLine removeCmdParams.toArray() - } - def addCmdParams = new ArrayList([aaptCommand, "add", pathToAAR, "config.json"]) - exec { - workingDir "$projectDir/src/main" - commandLine addCmdParams.toArray() - } - } - } - } -} \ No newline at end of file