Skip to content

Commit b6f5f7c

Browse files
authored
build: AGP 8.13.2 + R8 9.1.43, and drop Gradle syntax deprecated for 9.0/10.0 (#2050)
* build: drop Gradle syntax deprecated for 9.0/10.0 - Assign DSL properties with `prop = value` instead of the Groovy space-assignment form (namespace, ndkVersion, cmake version/path, signingConfig, description, standardOutput/errorOutput, ignoreExitValue). - Replace the gradle.useLogger() failure logger with a BuildService listening for task completion events; it prints the same styled failure summary at the end of the build and still skips failures of BuildToolTask tasks, which log their own errors. - Run the SBG AST test builds with `-p` instead of `-b`: the static-binding-generator settings.gradle now selects runtests.gradle as its build file, and runtests.gradle uses mainClass instead of main. * build: AGP 8.13.2 with R8 9.1.43 so D8 can read Kotlin 2.4 metadata The Kotlin version moved to 2.4.10 while AGP stayed on 8.12.1, whose bundled R8 (8.12.14) predates Kotlin 2.4 metadata. Every dex step then logs "An error occurred when parsing kotlin metadata" once per Kotlin stdlib class, about a thousand lines per build. Kotlin 2.4 needs R8 9.1.29 or newer, which no 8.x AGP bundles, so R8 is pinned on the buildscript classpath the way the AGP/Kotlin compatibility docs describe, and AGP moves to the last 8.x release. Both are overridable per project like the existing versions.
1 parent 1e7fc7a commit b6f5f7c

10 files changed

Lines changed: 69 additions & 54 deletions

File tree

‎build.gradle‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ createNpmPackage.dependsOn(copyReadme)
427427
task createPackage {
428428
println "CCache version: " + getCCacheVersion()
429429

430-
description "Builds the NativeScript Android cleanBuildArtefactsApp Package using an application project template."
430+
description = "Builds the NativeScript Android cleanBuildArtefactsApp Package using an application project template."
431431
dependsOn createNpmPackage
432432
println "Creating NativeScript Android Package"
433433
}

‎test-app/app/build.gradle‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ def computeNamespace = { ->
217217
}
218218

219219
android {
220-
namespace computeNamespace()
220+
namespace = computeNamespace()
221221

222222
applyBeforePluginGradleConfiguration()
223223

@@ -271,7 +271,7 @@ android {
271271
}
272272
buildTypes {
273273
release {
274-
signingConfig signingConfigs.release
274+
signingConfig = signingConfigs.release
275275
}
276276
}
277277

@@ -703,7 +703,7 @@ def resolveCompileSdkPlatformName(File sdkDirectory, String compileSdkVersion) {
703703

704704
task 'collectAllJars' {
705705
dependsOn extractAllJars
706-
description "gathers all paths to jar dependencies before building metadata with them"
706+
description = "gathers all paths to jar dependencies before building metadata with them"
707707

708708
def sdkPath = android.sdkDirectory.getAbsolutePath()
709709

@@ -964,7 +964,7 @@ task buildMetadata(type: BuildToolTask) {
964964
//buildMetadata.finalizedBy(copyMetadata)
965965
finalizedBy copyMetadata
966966

967-
description "builds metadata with provided jar dependencies"
967+
description = "builds metadata with provided jar dependencies"
968968

969969
inputs.files("$MDG_JAVA_DEPENDENCIES")
970970

‎test-app/app/gradle-helpers/BuildToolTask.gradle‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ class BuildToolTask extends JavaExec {
66
if(logFile.exists()) {
77
logFile.delete()
88
}
9-
standardOutput new FileOutputStream(logFile)
10-
errorOutput new FailureOutputStream(logger, logFile)
9+
standardOutput = new FileOutputStream(logFile)
10+
errorOutput = new FailureOutputStream(logger, logFile)
1111
}
1212
}
1313

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,60 @@
1+
import org.gradle.api.services.BuildService
2+
import org.gradle.api.services.BuildServiceParameters
3+
import org.gradle.build.event.BuildEventsListenerRegistry
4+
import org.gradle.internal.logging.text.StyledTextOutput
15
import org.gradle.internal.logging.text.StyledTextOutputFactory
6+
import org.gradle.tooling.events.FinishEvent
7+
import org.gradle.tooling.events.OperationCompletionListener
8+
import org.gradle.tooling.events.task.TaskFailureResult
9+
import org.gradle.tooling.events.task.TaskFinishEvent
210

311
import static org.gradle.internal.logging.text.StyledTextOutput.Style
4-
def outLogger = services.get(StyledTextOutputFactory).create("colouredOutputLogger")
5-
6-
class CustomExecutionLogger extends BuildAdapter implements TaskExecutionListener {
7-
private logger
8-
private failedTask
912

10-
CustomExecutionLogger(passedLogger) {
11-
logger = passedLogger
12-
}
13+
abstract class CustomExecutionLogger implements BuildService<BuildServiceParameters.None>, OperationCompletionListener, AutoCloseable {
14+
// BuildToolTask already logs its own errors; its failures are not repeated here.
15+
final Set<String> selfReportingTaskPaths = Collections.synchronizedSet(new HashSet<String>())
16+
private final List<org.gradle.tooling.Failure> failures = Collections.synchronizedList(new ArrayList<org.gradle.tooling.Failure>())
1317

14-
void buildStarted(Gradle gradle) {
15-
failedTask = null
16-
}
18+
// StyledTextOutputFactory cannot be injected into a BuildService, so the output is handed over from the script.
19+
StyledTextOutput output
1720

18-
void beforeExecute(Task task) {
19-
}
20-
21-
void afterExecute(Task task, TaskState state) {
22-
def failure = state.getFailure()
23-
if(failure) {
24-
failedTask = task
21+
@Override
22+
void onFinish(FinishEvent event) {
23+
if (event instanceof TaskFinishEvent && event.result instanceof TaskFailureResult) {
24+
if (!selfReportingTaskPaths.contains(event.descriptor.taskPath)) {
25+
failures.addAll(event.result.failures)
26+
}
2527
}
2628
}
2729

28-
void buildFinished(BuildResult result) {
29-
def failure = result.getFailure()
30-
if(failure) {
31-
if(failedTask && (failedTask.getClass().getName().contains("BuildToolTask"))) {
32-
// the error from this task is already logged
33-
return
34-
}
35-
36-
println ""
37-
logger.withStyle(Style.FailureHeader).println failure.getMessage()
30+
// Build services are closed once all tasks have finished, which makes close() the end-of-build hook.
31+
@Override
32+
void close() {
33+
if (failures.isEmpty() || output == null) {
34+
return
35+
}
36+
failures.each { failure ->
37+
output.println()
38+
output.withStyle(Style.FailureHeader).println failure.message
3839

39-
def causeException = failure.getCause()
40-
while (causeException != null) {
41-
failure = causeException
42-
causeException = failure.getCause()
40+
def rootCause = failure
41+
while (!rootCause.causes.isEmpty()) {
42+
rootCause = rootCause.causes[0]
4343
}
44-
if(failure != causeException) {
45-
logger.withStyle(Style.Failure).println failure.getMessage()
44+
if (rootCause != failure) {
45+
output.withStyle(Style.Failure).println rootCause.message
4646
}
47-
println ""
47+
output.println()
4848
}
4949
}
5050
}
5151

52-
gradle.useLogger(new CustomExecutionLogger(outLogger))
52+
def customExecutionLogger = gradle.sharedServices.registerIfAbsent("nsCustomExecutionLogger", CustomExecutionLogger) {}
53+
services.get(BuildEventsListenerRegistry).onTaskCompletion(customExecutionLogger)
54+
55+
def outLogger = services.get(StyledTextOutputFactory).create("colouredOutputLogger")
56+
gradle.taskGraph.whenReady { graph ->
57+
customExecutionLogger.get().output = outLogger
58+
def selfReporting = graph.allTasks.findAll { it.getClass().getName().contains("BuildToolTask") }*.path
59+
customExecutionLogger.get().selfReportingTaskPaths.addAll(selfReporting)
60+
}

‎test-app/build-tools/jsparser/tests/specs/ast-parser-tests.spec.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ const exec = require("child_process").exec,
33
fs = require("fs"),
44
prefix = path.resolve(__dirname, "../cases/"),
55
sbgBindingOutoutFile = path.resolve(__dirname, "../../../sbg-bindings.txt"),
6-
testsGradleFile = path.resolve(__dirname, "../../../static-binding-generator/runtests.gradle"),
6+
sbgProjectDir = path.resolve(__dirname, "../../../static-binding-generator"),
77
gradleExecutable = path.resolve(__dirname, "../../../../../gradlew");
88

99
function execGradle(inputPath, generatedJavaClassesRoot, callback) {
10-
const command = `${gradleExecutable} -b ${testsGradleFile} -PappRoot=${inputPath} -PgeneratedJavaClassesRoot=${generatedJavaClassesRoot}`;
10+
const command = `${gradleExecutable} -p ${sbgProjectDir} -PappRoot=${inputPath} -PgeneratedJavaClassesRoot=${generatedJavaClassesRoot}`;
1111
const options = {
1212
cwd: path.dirname(gradleExecutable)
1313
};

‎test-app/build-tools/static-binding-generator/runtests.gradle‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ task prepareInputFiles {
7676
task runSbg(type: JavaExec, dependsOn: 'prepareInputFiles') {
7777
classpath = files('build/libs/static-binding-generator.jar', '../')
7878
workingDir = "../"
79-
main = "org.nativescript.staticbindinggenerator.Main"
79+
mainClass = "org.nativescript.staticbindinggenerator.Main"
8080
}
8181
java {
8282
sourceCompatibility = JavaVersion.VERSION_17
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
// empty file to avoid using settings.gradle file from test-app
1+
// Only read when this directory is built standalone (`gradlew -p`, as the jsparser tests do);
2+
// as a test-app subproject, test-app's settings and build.gradle apply instead.
3+
rootProject.buildFileName = 'runtests.gradle'

‎test-app/build.gradle‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,18 @@ version of the {N} CLI install a previous version of the runtime package - 'tns
134134

135135
def computeKotlinVersion = { -> project.hasProperty("kotlinVersion") ? kotlinVersion : "${ns_default_kotlin_version}" }
136136
def computeBuildToolsVersion = { -> project.hasProperty("androidBuildToolsVersion") ? androidBuildToolsVersion : "${NS_DEFAULT_ANDROID_BUILD_TOOLS_VERSION}" }
137+
def computeR8Version = { -> project.hasProperty("r8Version") ? r8Version : "${NS_DEFAULT_R8_VERSION}" }
137138
def kotlinVersion = computeKotlinVersion()
138139
def androidBuildToolsVersion = computeBuildToolsVersion()
140+
def r8Version = computeR8Version()
139141

140142
repositories {
141143
google()
142144
mavenCentral()
143145
}
144146
dependencies {
145147
classpath "com.android.tools.build:gradle:$androidBuildToolsVersion"
148+
classpath "com.android.tools:r8:$r8Version"
146149
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
147150
classpath "org.apache.groovy:groovy-all:4.0.21"
148151
}

‎test-app/gradle.properties‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ android.useAndroidX=true
2222
NS_DEFAULT_BUILD_TOOLS_VERSION=35.0.0
2323
NS_DEFAULT_COMPILE_SDK_VERSION=35
2424
NS_DEFAULT_MIN_SDK_VERSION=21
25-
NS_DEFAULT_ANDROID_BUILD_TOOLS_VERSION=8.12.1
25+
NS_DEFAULT_ANDROID_BUILD_TOOLS_VERSION=8.13.2
26+
# R8 8.x cannot read Kotlin 2.4 metadata (needs 9.1.29+), so the AGP-bundled R8 is overridden.
27+
NS_DEFAULT_R8_VERSION=9.1.43
2628

2729
ns_default_androidx_appcompat_version = 1.7.0
2830
ns_default_androidx_exifinterface_version = 1.3.7

‎test-app/runtime/build.gradle‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ base {
8080
}
8181

8282
android {
83-
namespace "com.tns.android_runtime"
83+
namespace = "com.tns.android_runtime"
8484

8585
compileSdk NS_DEFAULT_COMPILE_SDK_VERSION as int
8686
buildToolsVersion = NS_DEFAULT_BUILD_TOOLS_VERSION as String
@@ -96,9 +96,9 @@ android {
9696
}
9797

9898
if (hasNdkVersion) {
99-
ndkVersion project.ndkVersion
99+
ndkVersion = project.ndkVersion
100100
} else {
101-
ndkVersion defaultNdkVersion
101+
ndkVersion = defaultNdkVersion
102102
}
103103

104104
defaultConfig {
@@ -152,8 +152,8 @@ android {
152152
}
153153
externalNativeBuild {
154154
cmake {
155-
version "3.31.6"
156-
path "CMakeLists.txt"
155+
version = "3.31.6"
156+
path = "CMakeLists.txt"
157157
}
158158
}
159159

@@ -320,7 +320,7 @@ def createPackageConfigFileTask(taskName) {
320320

321321
def removeCmdParams = new ArrayList<String>([aaptCommand, "remove", pathToAAR, "config.json"])
322322
exec {
323-
ignoreExitValue true
323+
ignoreExitValue = true
324324
workingDir "$projectDir/src/main"
325325
commandLine removeCmdParams.toArray()
326326
}

0 commit comments

Comments
 (0)