Revision control

Copy as Markdown

// This script defines common setup logic for our components, such as depending
// on the correct versions of android dependencies.
// Absent some special need for customization, we expect each project under `/components`
// to apply this script to their build process via:
//
// ```
// apply from: "$rootDir/build-scripts/component-common.gradle"
// ```
import javax.inject.Inject
apply plugin: 'com.android.library'
// When built as part of mozilla-central (mozconfig present), AGP 9 provides
// built-in Kotlin support and rejects this plugin; standalone builds still use
// an older AGP that requires it.
if (!gradle.hasProperty("mozconfig")) {
apply plugin: 'kotlin-android'
}
// Typed task used in the standalone app-services build, where the megazord
// dynamic library is produced by a separate gradle task and only exists when
// generateUniffiBindings runs (not at configuration time).
abstract class GenerateUniffiBindingsCargo extends DefaultTask {
@InputFiles
abstract ConfigurableFileCollection getMegazordNativeFiles()
@InputDirectory
abstract DirectoryProperty getBindgenToolDir()
@Input
abstract Property<String> getCrateName()
@Input
abstract Property<String> getNativeRustTarget()
@Internal
abstract DirectoryProperty getWorkingDirectory()
@OutputDirectory
abstract DirectoryProperty getOutputDir()
@Inject
abstract ExecOperations getExecOperations()
@TaskAction
void run() {
def libraryPath = megazordNativeFiles.asFileTree.matching {
include "${nativeRustTarget.get()}/libmegazord.*"
}.singleFile
if (libraryPath == null) {
throw new GradleException("libmegazord dynamic library path not found")
}
execOperations.exec {
workingDir workingDirectory.get().asFile
commandLine '/usr/bin/env', 'cargo', 'uniffi-bindgen', 'generate',
'--crate', crateName.get(), '--language', 'kotlin',
'--out-dir', outputDir.get().asFile,
'--no-format', libraryPath
}
}
}
android {
compileSdk { version = release(config.compileSdkMajorVersion) { minorApiLevel = config.compileSdkMinorVersion } }
defaultConfig {
ndkVersion config.ndkVersion
minSdkVersion config.minSdkVersion
targetSdkVersion config.targetSdkVersion
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
buildConfigField("String", "LIBRARY_VERSION", "\"${config.componentsVersion}\"")
}
buildFeatures {
buildConfig true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
consumerProguardFiles "$appServicesRootDir/proguard-rules-consumer-jna.pro"
}
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
lint {
lintConfig = file("${project.appServicesRootDir}/components/lint.xml")
}
}
kotlin {
jvmToolchain(rootProject.config.jvmTargetCompatibility)
}
dependencies {
testImplementation platform(libs.junit.bom)
testImplementation libs.junit4
testRuntimeOnly libs.junit.platform.launcher
testRuntimeOnly libs.junit.vintage
testImplementation libs.mockito
testImplementation libs.robolectric
androidTestImplementation libs.androidx.test.espresso.core
androidTestImplementation libs.androidx.test.runner
}
// Pick the publish group id by build context. In m-c, `config` belongs to
// android-components (`config.componentsGroupId` is `org.mozilla.components`),
// so we hardcode `org.mozilla.appservices`. Standalone app-services uses
// `config.componentsGroupId`, which is the only place that appends the
// `.nightly` suffix nightly builds publish under.
ext.appServicesGroupId = gradle.root.hasProperty("mozconfig")
? "org.mozilla.appservices"
: rootProject.config.componentsGroupId
// Shared logic for projects that depend on libmegazord
//
// This ensures that libmegazord will be in the library path so that it can be loaded. It also adds
// the transitive JNA dependency.
ext.dependsOnTheMegazord = {
dependencies {
api project(":full-megazord")
// Add a JNA dependency, which is required by UniFFI.
implementation(libs.jna) {
artifact {
type = "aar"
}
}
}
// 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.
configurations {
megazordNative {
canBeConsumed = false
}
}
dependencies {
megazordNative project("path": ":full-megazord", "configuration": "megazordNative")
implementation project("path": ":full-megazord", "configuration": "libsForTests")
}
}
// Shared logic for projects that use UniFFI-generated bindings
//
// Make sure to also call dependsOnTheMegazord()
ext.configureUniFFIBindgen = { crateName ->
if (gradle.hasProperty("mozconfig")) {
// For now, generated source files are checked into `firefox-main`.
android {
sourceSets.main.kotlin.srcDirs += "${gradle.mozconfig.topsrcdir}/toolkit/components/uniffi-bindgen-gecko-js/android/components/${project.name}/android/src/main"
}
} else {
// This will store the uniffi-bindgen generated files for our component
def uniffiOutDir = layout.buildDirectory.dir("generated/uniffi/")
// In app-services we can't use `Exec` because the megazord target isn't built yet; the task
// resolves the library path from the megazordNative configuration when it runs.
def generateUniffiBindings = tasks.register("generateUniffiBindings", GenerateUniffiBindingsCargo) {
// Qualify every property with `it.` because the `crateName` closure parameter shadows the
// task's crateName property; a bare `crateName.set(...)` would target the String, not the task.
it.megazordNativeFiles.from configurations.getByName("megazordNative")
it.bindgenToolDir.set(file("${project.appServicesRootDir}/tools/embedded-uniffi-bindgen/"))
it.crateName.set(crateName)
it.nativeRustTarget.set(rootProject.ext.nativeRustTarget)
it.workingDirectory.set(project.rootDir)
it.outputDir.set(uniffiOutDir)
}
androidComponents.onVariants(androidComponents.selector().all()) { variant ->
variant.sources.java.addGeneratedSourceDirectory(generateUniffiBindings) { it.outputDir }
}
}
}