Fix taskcluster breakage from #6524
Build a JAR file with libjnidispatch and libmegazord, targetted at Desktop arches so that devs can run unit tests with it. Export this as a configuration and Maven package. This allows android-components code to run the unit tests and also simplifies the gradle code for our own components. Named this full-megazord-libsForTest, which I think is a bit more clear than full-megazord-forUnitTests.
This commit is contained in:
Родитель
83ad69b756
Коммит
176f82f69d
|
@ -127,7 +127,7 @@ projects:
|
||||||
publications:
|
publications:
|
||||||
- name: full-megazord
|
- name: full-megazord
|
||||||
type: aar
|
type: aar
|
||||||
- name: full-megazord-forUnitTests
|
- name: full-megazord-libsForTests
|
||||||
type: jar
|
type: jar
|
||||||
description: Megazord containing all features
|
description: Megazord containing all features
|
||||||
tooling-nimbus-gradle:
|
tooling-nimbus-gradle:
|
||||||
|
|
|
@ -60,21 +60,11 @@ ext.dependsOnTheMegazord = {
|
||||||
api project(":full-megazord")
|
api project(":full-megazord")
|
||||||
|
|
||||||
// Add a JNA dependency, which is required by UniFFI.
|
// Add a JNA dependency, which is required by UniFFI.
|
||||||
//
|
|
||||||
// The tricky thing is getting the correct libjnidispatch library. Use the AAR version for
|
|
||||||
// normal builds, since that ensures the various Android libraries get packaged correctly when
|
|
||||||
// we build our own AAR. Use the JAR version for tests, since that ensures the tests can load
|
|
||||||
// the native version.
|
|
||||||
implementation(libs.jna) {
|
implementation(libs.jna) {
|
||||||
artifact {
|
artifact {
|
||||||
type = "aar"
|
type = "aar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
testImplementation(libs.jna) {
|
|
||||||
artifact {
|
|
||||||
type = "jar"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configurations are a somewhat mysterious Gradle concept. For our purposes, we can treat them
|
// Configurations are a somewhat mysterious Gradle concept. For our purposes, we can treat them
|
||||||
|
@ -85,33 +75,15 @@ ext.dependsOnTheMegazord = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wire up the megazordNative configuration to the output produced from the `full-megazord` project.
|
|
||||||
dependencies {
|
dependencies {
|
||||||
megazordNative(project("path": ":full-megazord", "configuration": "megazordNative"))
|
megazordNative project("path": ":full-megazord", "configuration": "megazordNative")
|
||||||
|
implementation project("path": ":full-megazord", "configuration": "libsForTests")
|
||||||
}
|
}
|
||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
android.libraryVariants.all { variant ->
|
android.libraryVariants.all { variant ->
|
||||||
def variantName = variant.name.capitalize();
|
def variantName = variant.name.capitalize();
|
||||||
def testTask = tasks["test${variantName}UnitTest"]
|
def testTask = tasks["test${variantName}UnitTest"]
|
||||||
def processTestResTask = tasks["process${variantName}UnitTestJavaRes"]
|
|
||||||
|
|
||||||
// Copy the native libmegazord to the resource dir so that it can be loaded by JNA.
|
|
||||||
// Note: we have to manually copy the library to the output dir ourselves. If we simply
|
|
||||||
// added the megazordNative directory to sourceSets.test.resources.srcDirs, then the
|
|
||||||
// android gradle plugin will refuse to copy it. For details see:
|
|
||||||
//
|
|
||||||
// * https://github.com/mozilla/application-services/pull/6476#issuecomment-2537227576
|
|
||||||
// * https://github.com/mozilla/glean/pull/2680#issuecomment-2056627683
|
|
||||||
def copyNativeMegazord = tasks.register("copy${variantName}NativeMegazord", Copy) {
|
|
||||||
from configurations.getByName("megazordNative")
|
|
||||||
into processTestResTask.destinationDir
|
|
||||||
// Make sure to run after the process java res task, otherwise that one may
|
|
||||||
// overwrite our work.
|
|
||||||
dependsOn(processTestResTask)
|
|
||||||
}
|
|
||||||
|
|
||||||
testTask.dependsOn(copyNativeMegazord)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,10 +102,9 @@ ext.configureUniFFIBindgen = { crateName ->
|
||||||
// Call `uniffi-bindgen` to generate the Kotlin bindings
|
// Call `uniffi-bindgen` to generate the Kotlin bindings
|
||||||
def generateUniffiBindings = tasks.register("generateUniffiBindings") {
|
def generateUniffiBindings = tasks.register("generateUniffiBindings") {
|
||||||
def megazordNative = configurations.getByName("megazordNative")
|
def megazordNative = configurations.getByName("megazordNative")
|
||||||
|
|
||||||
doFirst {
|
doFirst {
|
||||||
def libraryPath = megazordNative.asFileTree.matching {
|
def libraryPath = megazordNative.asFileTree.matching {
|
||||||
include "**/libmegazord.*"
|
include "${nativeRustTarget}/libmegazord.*"
|
||||||
}.singleFile
|
}.singleFile
|
||||||
|
|
||||||
if (libraryPath == null) {
|
if (libraryPath == null) {
|
||||||
|
@ -143,6 +114,7 @@ ext.configureUniFFIBindgen = { crateName ->
|
||||||
workingDir project.rootDir
|
workingDir project.rootDir
|
||||||
commandLine '/usr/bin/env', 'cargo', 'uniffi-bindgen', 'generate', '--library', libraryPath, "--crate", crateName, '--language', 'kotlin', '--out-dir', uniffiOutDir.get()
|
commandLine '/usr/bin/env', 'cargo', 'uniffi-bindgen', 'generate', '--library', libraryPath, "--crate", crateName, '--language', 'kotlin', '--out-dir', uniffiOutDir.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
outputs.dir uniffiOutDir
|
outputs.dir uniffiOutDir
|
||||||
// Re-generate when the native megazord library is rebuilt
|
// Re-generate when the native megazord library is rebuilt
|
||||||
|
|
|
@ -57,11 +57,12 @@ the name of the component and the expected version number of the shared library.
|
||||||
|
|
||||||
## Unit Tests
|
## Unit Tests
|
||||||
|
|
||||||
The full-megazord AAR contains compiled rust code that targets various Android platforms, and is not
|
The full-megazord AAR contains compiled Rust code that targets various Android platforms, and is not
|
||||||
suitable for running on a Desktop development machine. In order to support integration with unittest
|
suitable for running on a Desktop development machine. In order to support integration with unittest
|
||||||
suites such as robolectric, each megazord has a corresponding Java ARchive (JAR) distribution named e.g.
|
suites such as robolectric, each Megazord has a corresponding Java ARchive (JAR) distribution named
|
||||||
`full-megazord-forUnitTests.jar`. This contains the rust code compiled for various Desktop architectures,
|
e.g. `full-megazord-libsForTests.jar`. This contains the compiled Megazord code as well as
|
||||||
and consumers can add it to their classpath when running tests on a Desktop machine.
|
libjnidispatch, targetted at various Desktop architectures. Consumers can add it to their classpath
|
||||||
|
when running tests on a Desktop machine.
|
||||||
|
|
||||||
|
|
||||||
## Gotchas and Rough Edges
|
## Gotchas and Rough Edges
|
||||||
|
|
|
@ -35,25 +35,68 @@ kotlin {
|
||||||
// Configurations are a somewhat mysterious Gradle concept. For our purposes, we can treat them
|
// Configurations are a somewhat mysterious Gradle concept. For our purposes, we can treat them
|
||||||
// sets of files produced by one component and consumed by another.
|
// sets of files produced by one component and consumed by another.
|
||||||
configurations {
|
configurations {
|
||||||
|
// Libraries for unit tests
|
||||||
|
//
|
||||||
|
// This is a JAR file that contains libmegazord and libjnidispatch built for desktop platforms
|
||||||
|
// -- i.e. non-Android. These include linux-x86-64, darwin-x86-64, and darwin-aarch64. These
|
||||||
|
// libraries are needed to run unit tests, since the AAR packages only contain libraries for
|
||||||
|
// Android.
|
||||||
|
//
|
||||||
|
// For libmegazord, we copy the desktop libs from the
|
||||||
|
// [rust-android-gradle plugin](https://github.com/mozilla/rust-android-gradle), which is
|
||||||
|
// configurable via `local.properties`. The official packages are built in taskcluster include
|
||||||
|
// `linux-x86-64` and `darwin-x86-64` and the list is controlled by
|
||||||
|
// taskcluster/kinds/module-build/kind.yml
|
||||||
|
//
|
||||||
|
// For libjnidispatch, we include all libraries included in the official JAR file.
|
||||||
|
consumable("libsForTests")
|
||||||
|
// Stores the JNA jar file
|
||||||
|
jna {
|
||||||
|
canBeConsumed = false
|
||||||
|
canBeResolved = true
|
||||||
|
canBeDeclared = true
|
||||||
|
}
|
||||||
// Native megazord library, this is the one compatible with the user's local machine. We use it
|
// Native megazord library, this is the one compatible with the user's local machine. We use it
|
||||||
// to run unit tests.
|
// to run uniffi-bindgen against.
|
||||||
consumable("megazordNative")
|
consumable("megazordNative")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap the cargoBuild task to copy the native library to an output dir
|
dependencies {
|
||||||
//
|
// Needed so we can copy the libraries into libsForTests.
|
||||||
// This allows it to be piped in to a Gradle configuration.
|
jna(libs.jna) {
|
||||||
def cargoBuildNativeArtifacts = tasks.register("copyNativeMegazord", Copy) {
|
artifact {
|
||||||
from layout.buildDirectory.dir("rustJniLibs/desktop")
|
type = "jar"
|
||||||
into layout.buildDirectory.dir("nativeMegazord")
|
}
|
||||||
|
}
|
||||||
def nativeTarget = rootProject.ext.nativeRustTarget
|
|
||||||
dependsOn tasks["cargoBuild${nativeTarget.capitalize()}"]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract JNI dispatch libraries from the JAR into a directory, so that we can then package them
|
||||||
|
// into our own megazord-desktopLibraries JAR.
|
||||||
|
def extractLibJniDispatch = tasks.register("extractLibJniDispatch", Copy) {
|
||||||
|
from zipTree(configurations.jna.singleFile).matching {
|
||||||
|
include "**/libjnidispatch.*"
|
||||||
|
}
|
||||||
|
into layout.buildDirectory.dir("libjnidispatch").get()
|
||||||
|
}
|
||||||
|
|
||||||
|
def packageLibsForTest = tasks.register("packageLibsForTest", Jar) {
|
||||||
|
archiveBaseName = "full-megazord-libsForTests"
|
||||||
|
|
||||||
|
from extractLibJniDispatch
|
||||||
|
from layout.buildDirectory.dir("rustJniLibs/desktop")
|
||||||
|
dependsOn tasks["cargoBuild${rootProject.ext.nativeRustTarget.capitalize()}"]
|
||||||
|
}
|
||||||
|
|
||||||
|
def copyMegazordNative = tasks.register("copyMegazordNative", Copy) {
|
||||||
|
from layout.buildDirectory.dir("rustJniLibs/desktop")
|
||||||
|
into layout.buildDirectory.dir("megazordNative")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
artifacts {
|
artifacts {
|
||||||
// Connect task output to configurations
|
// Connect task output to the configurations
|
||||||
megazordNative(cargoBuildNativeArtifacts)
|
libsForTests(packageLibsForTest)
|
||||||
|
megazordNative(copyMegazordNative)
|
||||||
}
|
}
|
||||||
|
|
||||||
cargo {
|
cargo {
|
||||||
|
@ -99,3 +142,51 @@ afterEvaluate {
|
||||||
|
|
||||||
apply from: "$rootDir/publish.gradle"
|
apply from: "$rootDir/publish.gradle"
|
||||||
ext.configurePublish()
|
ext.configurePublish()
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
// Publish a second package named `full-megazord-libsForTests` to Maven with the
|
||||||
|
// `libsForTests` output. This contains the same content as our `libsForTests`
|
||||||
|
// configuration. Publishing it allows the android-components code to depend on it.
|
||||||
|
libsForTests(MavenPublication) {
|
||||||
|
artifact tasks['packageLibsForTest']
|
||||||
|
artifact file("${projectDir}/../DEPENDENCIES.md"), {
|
||||||
|
extension "LICENSES.md"
|
||||||
|
}
|
||||||
|
pom {
|
||||||
|
groupId = rootProject.ext.library.groupId
|
||||||
|
artifactId = "${project.ext.artifactId}-libsForTests"
|
||||||
|
description = project.ext.description
|
||||||
|
// For mavenLocal publishing workflow, increment the version number every publish.
|
||||||
|
version = rootProject.ext.library.version + (rootProject.hasProperty('local') ? '-' + rootProject.property('local') : '')
|
||||||
|
packaging = "jar"
|
||||||
|
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name = libLicense
|
||||||
|
url = libLicenseUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
name = 'Sync Team'
|
||||||
|
email = 'sync-team@mozilla.com'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scm {
|
||||||
|
connection = libVcsUrl
|
||||||
|
developerConnection = libVcsUrl
|
||||||
|
url = libUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is never the publication we want to use when publishing a
|
||||||
|
// parent project with us as a child `project()` dependency.
|
||||||
|
alias = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче