|
3 | 3 | import com.itsaky.androidide.build.config.BuildConfig |
4 | 4 | import com.itsaky.androidide.desugaring.utils.JavaIOReplacements.applyJavaIOReplacements |
5 | 5 | import com.itsaky.androidide.plugins.AndroidIDEAssetsPlugin |
| 6 | +import com.itsaky.androidide.plugins.tasks.AddFileToAssetsTask |
6 | 7 | import org.adfa.constants.GRADLE_API_NAME_JAR_BR |
7 | 8 | import org.adfa.constants.GRADLE_API_NAME_JAR_ZIP |
8 | 9 | import org.adfa.constants.GRADLE_DISTRIBUTION_ARCHIVE_NAME |
@@ -204,6 +205,46 @@ android { |
204 | 205 | } |
205 | 206 | } |
206 | 207 |
|
| 208 | +// DoD coverage gate. Two path traps are baked in below; both fail silently rather |
| 209 | +// than erroring, so each is spelled out here to stop the next measurement repeating one. |
| 210 | +// |
| 211 | +// executionData: the root build attaches the jacoco agent to every Test task, but for an |
| 212 | +// Android module the exec lands under outputs/unit_test_code_coverage/<variant>UnitTest/, |
| 213 | +// not build/jacoco/. A report pointed at build/jacoco/ SKIPs and measures nothing. |
| 214 | +// |
| 215 | +// classDirectories: :app runs transformV8DebugClassesWithAsm, so the bytecode the tests |
| 216 | +// executed is NOT tmp/kotlin-classes/v8Debug. That path is right for the quickbuild |
| 217 | +// modules (they run no ASM transform) and wrong here: measured 2026-09-10 it makes 138 |
| 218 | +// classes report "Execution data ... does not match" and count as fully uncovered, which |
| 219 | +// reads as a real coverage hole rather than a misconfiguration. The transformed dirs |
| 220 | +// below give 0 mismatches. |
| 221 | +tasks.register<JacocoReport>("jacocoTestReport") { |
| 222 | + group = "verification" |
| 223 | + description = "JaCoCo line+branch coverage for the v8Debug unit tests." |
| 224 | + dependsOn("testV8DebugUnitTest") |
| 225 | + |
| 226 | + reports { |
| 227 | + xml.required.set(true) |
| 228 | + html.required.set(true) |
| 229 | + } |
| 230 | + |
| 231 | + classDirectories.setFrom( |
| 232 | + fileTree( |
| 233 | + layout.buildDirectory.dir( |
| 234 | + "intermediates/classes/v8Debug/transformV8DebugClassesWithAsm/dirs", |
| 235 | + ), |
| 236 | + ) { |
| 237 | + exclude("**/BuildConfig*") |
| 238 | + }, |
| 239 | + ) |
| 240 | + sourceDirectories.setFrom(files("src/main/java")) |
| 241 | + executionData.setFrom( |
| 242 | + layout.buildDirectory.file( |
| 243 | + "outputs/unit_test_code_coverage/v8DebugUnitTest/testV8DebugUnitTest.exec", |
| 244 | + ), |
| 245 | + ) |
| 246 | +} |
| 247 | + |
207 | 248 | // Sentry gradle plugin config (crash reporting to GlitchTip). |
208 | 249 | sentry { |
209 | 250 | includeProguardMapping = false |
@@ -404,6 +445,7 @@ dependencies { |
404 | 445 | implementation(projects.floatingWindow) |
405 | 446 | implementation(projects.gitCore) |
406 | 447 | implementation(projects.profiler) |
| 448 | + implementation(projects.quickbuild.core) |
407 | 449 |
|
408 | 450 | // This is to build the tooling-api-impl project before the app is built |
409 | 451 | // So we always copy the latest JAR file to assets |
@@ -457,6 +499,69 @@ dependencies { |
457 | 499 | coreLibraryDesugaring(libs.desugar.jdk.libs.v215) |
458 | 500 | } |
459 | 501 |
|
| 502 | +// Quick Build (ADFA-4128): stage the runtime AAR + daemon (jar + runtime classpath) |
| 503 | +// into APK assets, mirroring the LogSender AAR flow in AndroidIDEAssetsPlugin. The |
| 504 | +// artifacts are extracted to <ANDROIDIDE_HOME>/quickbuild/ at session start |
| 505 | +// (QuickBuildArtifactStager). |
| 506 | +evaluationDependsOn(":quickbuild:runtime") |
| 507 | +evaluationDependsOn(":quickbuild:daemon") |
| 508 | + |
| 509 | +val quickBuildDaemonZip = |
| 510 | + tasks.register<Zip>("quickBuildDaemonZip") { |
| 511 | + archiveFileName.set("quickbuild-daemon.zip") |
| 512 | + destinationDirectory.set(layout.buildDirectory.dir("intermediates/quickbuild")) |
| 513 | + val daemonProject = rootProject.project(":quickbuild:daemon") |
| 514 | + dependsOn(daemonProject.tasks.named("daemonJar")) |
| 515 | + from(daemonProject.tasks.named("daemonJar")) |
| 516 | + // The daemon jar's manifest Class-Path names these by file name; they must sit |
| 517 | + // next to the jar after extraction. |
| 518 | + from(daemonProject.configurations.named("runtimeClasspath")) |
| 519 | + // Compose compiler plugin, version-matched to the daemon's compiler; the stable |
| 520 | + // name is the contract EnvironmentQuickBuildPaths.composeCompilerPlugin reads. |
| 521 | + from(daemonProject.configurations.named("composeCompilerPlugin")) { |
| 522 | + rename { "compose-compiler-plugin.jar" } |
| 523 | + } |
| 524 | + } |
| 525 | + |
| 526 | +androidComponents.onVariants { variant -> |
| 527 | + val variantName = variant.name.replaceFirstChar(Char::uppercaseChar) |
| 528 | + val flavorName = variant.flavorName!! |
| 529 | + |
| 530 | + val copyRuntimeAar = |
| 531 | + tasks.register<AddFileToAssetsTask>("copy${variantName}QuickBuildRuntimeAar") { |
| 532 | + val runtimeProject = rootProject.project(":quickbuild:runtime") |
| 533 | + dependsOn( |
| 534 | + runtimeProject.tasks.named( |
| 535 | + "assemble${flavorName.replaceFirstChar(Char::uppercaseChar)}Release", |
| 536 | + ), |
| 537 | + ) |
| 538 | + inputFile.set( |
| 539 | + runtimeProject.layout.buildDirectory.file( |
| 540 | + "outputs/aar/quickbuild-runtime-$flavorName-release.aar", |
| 541 | + ), |
| 542 | + ) |
| 543 | + baseAssetsPath.set("data/common") |
| 544 | + // Flavor-agnostic asset name: the runtime AAR is pure Java, both flavors |
| 545 | + // produce identical bits, and the stager doesn't need to care. |
| 546 | + fileName.set("quickbuild-runtime.aar") |
| 547 | + } |
| 548 | + variant.sources.assets?.addGeneratedSourceDirectory( |
| 549 | + copyRuntimeAar, |
| 550 | + AddFileToAssetsTask::outputDirectory, |
| 551 | + ) |
| 552 | + |
| 553 | + val copyDaemonZip = |
| 554 | + tasks.register<AddFileToAssetsTask>("copy${variantName}QuickBuildDaemonZip") { |
| 555 | + dependsOn(quickBuildDaemonZip) |
| 556 | + inputFile.set(quickBuildDaemonZip.flatMap { it.archiveFile }) |
| 557 | + baseAssetsPath.set("data/common") |
| 558 | + } |
| 559 | + variant.sources.assets?.addGeneratedSourceDirectory( |
| 560 | + copyDaemonZip, |
| 561 | + AddFileToAssetsTask::outputDirectory, |
| 562 | + ) |
| 563 | +} |
| 564 | + |
460 | 565 | tasks.register("downloadDocDb") { |
461 | 566 | doLast { |
462 | 567 | val githubRepo = "appdevforall/OfflineDocumentationTools" |
|
0 commit comments