Bug 1799002 - Part 1: Fix Android builds after Android-Gradle plugin version 7.3.0. r=geckoview-reviewers,m_kato

This commit removes a good deal of complexity around how
`assets/omni.ja` and `libs/*` are packaged into the Android GeckoView
project and ultimately AAR and APK files.

Historically there was a delicate arrangement that had both the
omnijar and the native libraries in Android assets, the latter so
they could be compressed and read by Gecko's own loader
implementation.  As GeckoView (and Android itself!) matured, the
arrangement was normalized: now Gecko libraries are regular Android
libraries with no compression and special loading.  This is why we had
levels of indirection around `syncOmnijarFromDistDir` and
`syncLibsFromDistDir`: we needed fine-grained mappings from locations
to locations.  These delicate mappings are no longer needed and the
whole process can be simplified in the manner of this patch.

By declaring the Android sourcesets (close to) statically, the updated
Android-Gradle plugin version 7.3.0 no longer "misses" content changes
in the relevant directories.

We continue to need the `withGeckoBinaries` product flavours to
support non-builds like linting and generating documentation.

Differential Revision: https://phabricator.services.mozilla.com/D161510
This commit is contained in:
Nick Alexander 2023-04-24 20:11:57 +00:00
parent b7381128ec
commit 4558bdbb48
2 changed files with 19 additions and 98 deletions

View File

@ -134,6 +134,21 @@ android {
manifest.srcFile "${topobjdir}/mobile/android/geckoview/src/main/AndroidManifest_overlay.xml"
}
}
withGeckoBinaries {
assets {
// This should contain only `omni.ja`.
srcDir "${topobjdir}/dist/geckoview/assets"
}
jniLibs {
if (!mozconfig.substs.MOZ_ANDROID_FAT_AAR_ARCHITECTURES) {
srcDir "${topobjdir}/dist/geckoview/lib"
} else {
srcDir "${topobjdir}/dist/fat-aar/output/jni"
}
}
}
}
}

View File

@ -38,7 +38,7 @@ def getNDKDirectory() {
return null
}
// Whether to include compiled artifacts: `libs/**/*.so` and `assets/omni.ja`.
// Whether to include compiled artifacts: `lib/**/*.so` and `assets/omni.ja`.
// Multi-locale packaging wants to include compiled artifacts but *not* rebuild
// them: see also `rootProject.{machStagePackage,geckoBinariesOnlyIf}`.
def hasCompileArtifacts() {
@ -198,111 +198,17 @@ class SyncLibsAndUpdateGenerationID extends DefaultTask {
}
ext.configureVariantWithGeckoBinaries = { variant ->
def omnijarDir = "${topobjdir}/dist/geckoview"
def distDir = "${topobjdir}/dist/geckoview"
def syncOmnijarFromDistDir
if (hasCompileArtifacts()) {
syncOmnijarFromDistDir = task("syncOmnijarFromDistDirFor${variant.name.capitalize()}", type: Sync) {
onlyIf {
if (source.empty) {
throw new StopExecutionException("Required omnijar not found in ${omnijarDir}/{omni.ja,assets/omni.ja}. Have you built and packaged?")
}
return true
}
into("${project.buildDir}/moz.build/src/${variant.name}/omnijar")
from("${omnijarDir}/omni.ja",
"${omnijarDir}/assets/omni.ja") {
// Throw an exception if we find multiple, potentially conflicting omni.ja files.
duplicatesStrategy 'fail'
}
}
}
// For !MOZILLA_OFFICIAL builds, work around an Android-Gradle plugin bug that causes startup
// crashes with local substitution. But -- we want to allow artifact builds that don't have the
// NDK installed. See class comment above.
def shouldUpdateGenerationID = {
if (mozconfig.substs.MOZILLA_OFFICIAL) {
return false
} else if (mozconfig.substs.MOZ_ANDROID_FAT_AAR_ARCHITECTURES) {
return false
} else if (ext.getLlvmBinFolder() == null) {
logger.warn("Could not determine LLVM bin directory.")
logger.warn("Set `ndk.dir` in `${project.topsrcdir}/local.properties` to avoid startup crashes when using `substitute-local-geckoview.gradle`.")
logger.warn("See https://bugzilla.mozilla.org/show_bug.cgi?id=1657190.")
return false
}
return true
}()
def syncLibsFromDistDir = { if (shouldUpdateGenerationID) {
def jarTask = tasks["bundleLibRuntimeToJar${variant.name.capitalize()}"]
def bundleJar = jarTask.outputs.files.find({ it.name == 'classes.jar' })
task("syncLibsAndUpdateGenerationIDFromDistDirFor${variant.name.capitalize()}", type: SyncLibsAndUpdateGenerationID) {
source file("${distDir}/lib")
destinationDir file("${project.buildDir}/moz.build/src/${variant.name}/jniLibs")
// Include the hash of classes.jar as well, so that JVM-only changes don't leave every
// JNI library unchanged and therefore invalidate all of the JNI libraries in a consumer
// doing local substitution.
extraSource bundleJar
dependsOn jarTask
}
} else {
task("syncLibsFromDistDirFor${variant.name.capitalize()}", type: Sync) {
into("${project.buildDir}/moz.build/src/${variant.name}/jniLibs")
from("${distDir}/lib")
}
} }()
syncLibsFromDistDir.onlyIf { task ->
if (!hasCompileArtifacts()) {
// We won't have JNI libraries if we're not compiling and we're not downloading
// artifacts. Such a configuration is used for running lints, generating docs, etc.
return true
}
if (files(task.source).empty) {
throw new StopExecutionException("Required JNI libraries not found in ${task.source}. Have you built and packaged?")
}
return true
}
def syncAssetsFromDistDir = task("syncAssetsFromDistDirFor${variant.name.capitalize()}", type: Sync) {
into("${project.buildDir}/moz.build/src/${variant.name}/assets")
from("${distDir}/assets") {
exclude 'omni.ja'
}
}
if (hasCompileArtifacts()) {
// Local (read, not 'official') builds want to reflect developer changes to
// the omnijar sources, and (when compiling) to reflect developer changes to
// the native binaries. To do this, the Gradle build calls out to the
// moz.build system, which can be re-entrant. Official builds are driven by
// the moz.build system and should never be re-entrant in this way.
if (!mozconfig.substs.MOZILLA_OFFICIAL) {
syncOmnijarFromDistDir.dependsOn rootProject.machStagePackage
syncLibsFromDistDir.dependsOn rootProject.machStagePackage
syncAssetsFromDistDir.dependsOn rootProject.machStagePackage
}
def assetGenTask = tasks.findByName("generate${variant.name.capitalize()}Assets")
def jniLibFoldersTask = tasks.findByName("merge${variant.name.capitalize()}JniLibFolders")
if ((variant.productFlavors*.name).contains('withGeckoBinaries')) {
assetGenTask.dependsOn syncOmnijarFromDistDir
assetGenTask.dependsOn syncAssetsFromDistDir
jniLibFoldersTask.dependsOn syncLibsFromDistDir
android.sourceSets."${variant.name}".assets.srcDir syncOmnijarFromDistDir.destinationDir
android.sourceSets."${variant.name}".assets.srcDir syncAssetsFromDistDir.destinationDir
if (!mozconfig.substs.MOZ_ANDROID_FAT_AAR_ARCHITECTURES) {
android.sourceSets."${variant.name}".jniLibs.srcDir syncLibsFromDistDir.destinationDir
} else {
android.sourceSets."${variant.name}".jniLibs.srcDir "${topobjdir}/dist/fat-aar/output/jni"
}
if (!mozconfig.substs.MOZILLA_OFFICIAL && (variant.productFlavors*.name).contains('withGeckoBinaries')) {
assetGenTask.dependsOn rootProject.machStagePackage
jniLibFoldersTask.dependsOn rootProject.machStagePackage
}
}
}