Source code

Revision control

Other Tools

1
buildDir "${topobjdir}/gradle/build/mobile/android/geckoview"
2
3
import groovy.json.JsonOutput
4
5
apply plugin: 'com.android.library'
6
apply plugin: 'checkstyle'
7
apply plugin: 'kotlin-android'
8
9
apply from: "${topsrcdir}/mobile/android/gradle/product_flavors.gradle"
10
11
// The SDK binding generation tasks depend on the JAR creation task of the
12
// :annotations project.
13
evaluationDependsOn(':annotations')
14
15
// Non-official versions are like "61.0a1", where "a1" is the milestone.
16
// This simply strips that off, leaving "61.0" in this example.
17
def getAppVersionWithoutMilestone() {
18
return mozconfig.substs.MOZ_APP_VERSION.replaceFirst(/a[0-9]/, "")
19
}
20
21
// This converts MOZ_APP_VERSION into an integer
22
// version code.
23
//
24
// We take something like 58.1.2a1 and come out with 5800102
25
// This gives us 3 digits for the major number, and 2 digits
26
// each for the minor and build number. Beta and Release
27
//
28
// This must be synchronized with _compute_gecko_version(...) in /taskcluster/taskgraph/transforms/task.py
29
def computeVersionCode() {
30
String appVersion = getAppVersionWithoutMilestone()
31
32
// Split on the dot delimiter, e.g. 58.1.1a1 -> ["58, "1", "1a1"]
33
String[] parts = appVersion.split('\\.')
34
35
assert parts.size() == 2 || parts.size() == 3
36
37
// Major
38
int code = Integer.parseInt(parts[0]) * 100000
39
40
// Minor
41
code += Integer.parseInt(parts[1]) * 100
42
43
// Build
44
if (parts.size() == 3) {
45
code += Integer.parseInt(parts[2])
46
}
47
48
return code;
49
}
50
51
def computeVersionNumber() {
52
def appVersion = getAppVersionWithoutMilestone()
53
def parts = appVersion.split('\\.')
54
return parts[0] + "." + parts[1] + "." + getBuildId()
55
}
56
57
// Mimic Python: open(os.path.join(buildconfig.topobjdir, 'buildid.h')).readline().split()[2]
58
def getBuildId() {
59
return file("${topobjdir}/buildid.h").getText('utf-8').split()[2]
60
}
61
62
android {
63
compileSdkVersion project.ext.compileSdkVersion
64
65
useLibrary 'android.test.runner'
66
useLibrary 'android.test.base'
67
useLibrary 'android.test.mock'
68
69
defaultConfig {
70
targetSdkVersion project.ext.targetSdkVersion
71
minSdkVersion project.ext.minSdkVersion
72
manifestPlaceholders = project.ext.manifestPlaceholders
73
74
versionCode computeVersionCode()
75
versionName "${mozconfig.substs.MOZ_APP_VERSION}-${mozconfig.substs.MOZ_UPDATE_CHANNEL}"
76
consumerProguardFiles 'proguard-rules.txt'
77
78
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
79
80
buildConfigField 'String', "GRE_MILESTONE", "\"${mozconfig.substs.GRE_MILESTONE}\""
81
buildConfigField 'String', "MOZ_APP_BASENAME", "\"${mozconfig.substs.MOZ_APP_BASENAME}\"";
82
83
// For the benefit of future archaeologists:
84
// GRE_BUILDID is exactly the same as MOZ_APP_BUILDID unless you're running
85
// on XULRunner, which is never the case on Android.
86
buildConfigField 'String', "MOZ_APP_BUILDID", "\"${getBuildId()}\"";
87
buildConfigField 'String', "MOZ_APP_ID", "\"${mozconfig.substs.MOZ_APP_ID}\"";
88
buildConfigField 'String', "MOZ_APP_NAME", "\"${mozconfig.substs.MOZ_APP_NAME}\"";
89
buildConfigField 'String', "MOZ_APP_VENDOR", "\"${mozconfig.substs.MOZ_APP_VENDOR}\"";
90
buildConfigField 'String', "MOZ_APP_VERSION", "\"${mozconfig.substs.MOZ_APP_VERSION}\"";
91
buildConfigField 'String', "MOZ_APP_DISPLAYNAME", "\"${mozconfig.substs.MOZ_APP_DISPLAYNAME}\"";
92
buildConfigField 'String', "MOZ_APP_UA_NAME", "\"${mozconfig.substs.MOZ_APP_UA_NAME}\"";
93
buildConfigField 'String', "MOZ_UPDATE_CHANNEL", "\"${mozconfig.substs.MOZ_UPDATE_CHANNEL}\"";
94
95
// MOZILLA_VERSION is oddly quoted from autoconf, but we don't have to handle it specially in Gradle.
96
buildConfigField 'String', "MOZILLA_VERSION", "\"${mozconfig.substs.MOZILLA_VERSION}\"";
97
buildConfigField 'String', "OMNIJAR_NAME", "\"${mozconfig.substs.OMNIJAR_NAME}\"";
98
99
// Keep in sync with actual user agent in nsHttpHandler::BuildUserAgent
100
buildConfigField 'String', "USER_AGENT_GECKOVIEW_MOBILE", "\"Mozilla/5.0 (Android \" + android.os.Build.VERSION.RELEASE + \"; Mobile; rv:\" + ${mozconfig.defines.MOZILLA_UAVERSION} + \") Gecko/\" + ${mozconfig.defines.MOZILLA_UAVERSION} + \" Firefox/\" + ${mozconfig.defines.MOZILLA_UAVERSION}";
101
buildConfigField 'String', "USER_AGENT_GECKOVIEW_TABLET", "\"Mozilla/5.0 (Android \" + android.os.Build.VERSION.RELEASE + \"; Tablet; rv:\" + ${mozconfig.defines.MOZILLA_UAVERSION} + \") Gecko/\" + ${mozconfig.defines.MOZILLA_UAVERSION} + \" Firefox/\" + ${mozconfig.defines.MOZILLA_UAVERSION}";
102
103
buildConfigField 'int', 'MIN_SDK_VERSION', mozconfig.substs.MOZ_ANDROID_MIN_SDK_VERSION;
104
105
// Is the underlying compiled C/C++ code compiled with --enable-debug?
106
buildConfigField 'boolean', 'DEBUG_BUILD', mozconfig.substs.MOZ_DEBUG ? 'true' : 'false';
107
108
// See this wiki page for more details about channel specific build defines:
110
// This makes no sense for GeckoView and should be removed as soon as possible.
111
buildConfigField 'boolean', 'RELEASE_OR_BETA', mozconfig.substs.RELEASE_OR_BETA ? 'true' : 'false';
112
// This makes no sense for GeckoView and should be removed as soon as possible.
113
buildConfigField 'boolean', 'NIGHTLY_BUILD', mozconfig.substs.NIGHTLY_BUILD ? 'true' : 'false';
114
// This makes no sense for GeckoView and should be removed as soon as possible.
115
buildConfigField 'boolean', 'MOZ_CRASHREPORTER', mozconfig.substs.MOZ_CRASHREPORTER ? 'true' : 'false';
116
117
// Official corresponds, roughly, to whether this build is performed on
118
// Mozilla's continuous integration infrastructure. You should disable
119
// developer-only functionality when this flag is set.
120
// This makes no sense for GeckoView and should be removed as soon as possible.
121
buildConfigField 'boolean', 'MOZILLA_OFFICIAL', mozconfig.substs.MOZILLA_OFFICIAL ? 'true' : 'false';
122
}
123
124
project.configureProductFlavors.delegate = it
125
project.configureProductFlavors()
126
127
compileOptions {
128
sourceCompatibility JavaVersion.VERSION_1_8
129
targetCompatibility JavaVersion.VERSION_1_8
130
}
131
132
dexOptions {
133
javaMaxHeapSize "6g"
134
}
135
136
lintOptions {
137
abortOnError false
138
}
139
140
sourceSets {
141
main {
142
java {
143
srcDir "${topsrcdir}/mobile/android/geckoview/src/thirdparty/java"
144
145
if (!mozconfig.substs.MOZ_ANDROID_HLS_SUPPORT) {
146
exclude 'com/google/android/exoplayer2/**'
147
exclude 'org/mozilla/gecko/media/GeckoHlsAudioRenderer.java'
148
exclude 'org/mozilla/gecko/media/GeckoHlsPlayer.java'
149
exclude 'org/mozilla/gecko/media/GeckoHlsRendererBase.java'
150
exclude 'org/mozilla/gecko/media/GeckoHlsVideoRenderer.java'
151
exclude 'org/mozilla/gecko/media/Utils.java'
152
}
153
154
if (mozconfig.substs.MOZ_WEBRTC) {
155
srcDir "${topsrcdir}/dom/media/systemservices/android_video_capture/java/src"
156
srcDir "${topsrcdir}/media/webrtc/trunk/webrtc/sdk/android"
157
srcDir "${topsrcdir}/media/webrtc/trunk/webrtc/rtc_base/java"
158
}
159
}
160
161
resources {
162
if (mozconfig.substs.MOZ_ASAN) {
163
// If this is an ASAN build, include a `wrap.sh` for Android 8.1+ devices. See
165
srcDir "${topsrcdir}/mobile/android/geckoview/src/asan/resources"
166
}
167
}
168
169
assets {
170
}
171
}
172
}
173
}
174
175
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) {
176
// Translate Kotlin messages like "w: ..." and "e: ..." into
177
// "...: warning: ..." and "...: error: ...", to make Treeherder understand.
178
def listener = {
179
if (it.startsWith("e: warnings found")) {
180
return
181
}
182
183
if (it.startsWith('w: ') || it.startsWith('e: ')) {
184
def matches = (it =~ /([ew]): (.+): \((\d+), (\d+)\): (.*)/)
185
if (!matches) {
186
logger.quiet "kotlinc message format has changed!"
187
if (it.startsWith('w: ')) {
188
// For warnings, don't continue because we don't want to throw an
189
// exception. For errors, we want the exception so that the new error
190
// message format gets translated properly.
191
return
192
}
193
}
194
def (_, type, file, line, column, message) = matches[0]
195
type = (type == 'w') ? 'warning' : 'error'
196
// Use logger.lifecycle, which does not go through stderr again.
197
logger.lifecycle "$file:$line:$column: $type: $message"
198
}
199
} as StandardOutputListener
200
201
kotlinOptions {
202
allWarningsAsErrors = true
203
}
204
205
doFirst {
206
logging.addStandardErrorListener(listener)
207
}
208
doLast {
209
logging.removeStandardErrorListener(listener)
210
}
211
}
212
213
dependencies {
214
implementation "com.android.support:support-v4:$support_library_version"
215
implementation "com.android.support:palette-v7:$support_library_version"
216
implementation "org.yaml:snakeyaml:1.24:android"
217
218
implementation "android.arch.lifecycle:extensions:$lifecycle_library_version"
219
implementation "android.arch.lifecycle:common-java8:$lifecycle_library_version"
220
221
testImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
222
testImplementation 'junit:junit:4.12'
223
testImplementation 'org.robolectric:robolectric:4.3'
224
testImplementation 'org.mockito:mockito-core:1.10.19'
225
226
androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
227
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
228
androidTestImplementation 'androidx.test:runner:1.1.0'
229
androidTestImplementation 'androidx.test:rules:1.1.0'
230
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
231
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
232
233
androidTestImplementation "com.android.support:support-annotations:$support_library_version"
234
235
androidTestImplementation 'com.koushikdutta.async:androidasync:2.+'
236
}
237
238
apply from: "${topsrcdir}/mobile/android/gradle/with_gecko_binaries.gradle"
239
240
android.libraryVariants.all { variant ->
241
// See the notes in mobile/android/app/build.gradle for details on including
242
// Gecko binaries and the Omnijar.
243
if ((variant.productFlavors*.name).contains('withGeckoBinaries')) {
244
configureVariantWithGeckoBinaries(variant)
245
}
246
247
// Javadoc and Sources JAR configuration cribbed from
249
// informed by
251
// and amended from numerous Stackoverflow posts.
252
def name = variant.name
253
def javadoc = task "javadoc${name.capitalize()}"(type: Javadoc) {
254
description = "Generate Javadoc for build variant $name"
255
destinationDir = new File(destinationDir, variant.baseName)
256
doFirst {
257
classpath = files(variant.javaCompileProvider.get().classpath.files)
258
}
259
260
def results = []
261
def listener = {
262
// Like '/abs/path/to/topsrcdir/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ContentBlocking.java:480: warning: no @return'
263
def matches = (it =~ /(.+):(\d+): (warning|error): (.*)/)
264
if (!matches) {
265
return
266
}
267
def (_, file, line, level, message) = matches[0]
268
results << [path: file, lineno: line, level: level, message: message]
269
} as StandardOutputListener
270
271
doFirst {
272
logging.addStandardErrorListener(listener)
273
}
274
275
doLast {
276
logging.removeStandardErrorListener(listener)
277
278
// We used to treat Javadoc warnings as errors here; now we rely on the
279
// `android-javadoc` linter to fail in the face of Javadoc warnings.
280
def resultsJson = JsonOutput.toJson(results)
281
282
file("$buildDir/reports").mkdirs()
283
file("$buildDir/reports/javadoc-results-${name}.json").write(resultsJson)
284
}
285
286
source = variant.sourceSets.collect({ it.java.srcDirs })
287
exclude '**/R.java', '**/BuildConfig.java'
288
include 'org/mozilla/geckoview/**.java'
289
options.addPathOption('sourcepath', ':').setValue(
290
variant.sourceSets.collect({ it.java.srcDirs }).flatten() +
291
variant.generateBuildConfigProvider.get().sourceOutputDir +
292
variant.aidlCompileProvider.get().sourceOutputDir)
293
294
// javadoc 8 has a bug that requires the rt.jar file from the JRE to be
295
// in the bootclasspath (https://stackoverflow.com/a/30458820).
296
options.bootClasspath = [
297
file("${System.properties['java.home']}/lib/rt.jar")] + android.bootClasspath
298
options.memberLevel = JavadocMemberLevel.PROTECTED
299
options.source = 8
300
// Bug 1555255: don't require a network connection to produce Javadoc.
302
options.linksOffline("https://d.android.com/reference/", "${android.sdkDirectory}/docs/reference");
303
304
options.docTitle = "GeckoView ${mozconfig.substs.MOZ_APP_VERSION} API"
305
options.header = "GeckoView ${mozconfig.substs.MOZ_APP_VERSION} API"
306
options.noTimestamp = true
307
options.noIndex = true
308
options.noQualifiers = ['java.lang']
309
options.tags = ['hide:a:']
310
}
311
312
def javadocJar = task("javadocJar${name.capitalize()}", type: Jar, dependsOn: javadoc) {
313
classifier = 'javadoc'
314
from javadoc.destinationDir
315
}
316
317
// This task is used by `mach android geckoview-docs`.
318
task("javadocCopyJar${name.capitalize()}", type: Copy) {
319
from(javadocJar.destinationDir) {
320
include 'geckoview-*-javadoc.jar'
321
rename { _ -> 'geckoview-javadoc.jar' }
322
}
323
into javadocJar.destinationDir
324
dependsOn javadocJar
325
}
326
327
def sourcesJar = task("sourcesJar${name.capitalize()}", type: Jar) {
328
classifier 'sources'
329
description = "Generate Javadoc for build variant $name"
330
destinationDir = new File(destinationDir, variant.baseName)
331
from files(variant.javaCompileProvider.get().source)
332
}
333
334
task("checkstyle${name.capitalize()}", type: Checkstyle) {
335
classpath = variant.javaCompileProvider.get().classpath
336
configFile file("checkstyle.xml")
337
// TODO: cleanup and include all sources
338
source = ['src/main/java/']
339
include '**/*.java'
340
}
341
}
342
343
android.libraryVariants.all { variant ->
344
if (variant.name == mozconfig.substs.GRADLE_ANDROID_GECKOVIEW_VARIANT_NAME) {
345
configureLibraryVariantWithJNIWrappers(variant, "Generated")
346
}
347
}
348
349
android.libraryVariants.all { variant ->
350
// At this point, the Android-Gradle plugin has created all the Android
351
// tasks and configurations. This is the time for us to declare additional
352
// Glean files to package into AAR files. This packs `metrics.yaml` in the
353
// root of the AAR, sibling to `AndroidManifest.xml` and `classes.jar`. By
354
// default, consumers of the AAR will ignore this file, but consumers that
355
// look for it can find it (provided GeckoView is a `module()` dependency
356
// and not a `project()` dependency.) Under the hood this uses that the
357
// task provided by `packageLibraryProvider` task is a Maven `Zip` task,
358
// and we can simply extend its inputs. See
360
variant.packageLibraryProvider.get().from("${topsrcdir}/toolkit/components/telemetry/geckoview/streaming/metrics.yaml")
361
}
362
363
apply plugin: 'maven-publish'
364
365
version = computeVersionNumber()
366
if (!mozconfig.substs.MOZILLA_OFFICIAL && !mozconfig.substs.MOZ_ANDROID_FAT_AAR_ARCHITECTURES) {
367
// Use -SNAPSHOT versions locally to enable the local GeckoView substitution flow.
368
version = "${version}-SNAPSHOT"
369
}
370
371
publishing {
372
publications {
373
android.libraryVariants.all { variant ->
374
"${variant.name}"(MavenPublication) {
375
pom {
376
groupId = 'org.mozilla.geckoview'
377
378
if (mozconfig.substs.MOZ_UPDATE_CHANNEL == 'release') {
379
// Release artifacts don't specify the channel, for the sake of simplicity.
380
artifactId = 'geckoview'
381
} else {
382
artifactId = "geckoview-${mozconfig.substs.MOZ_UPDATE_CHANNEL}"
383
}
384
385
if (mozconfig.substs.MOZILLA_OFFICIAL && !mozconfig.substs.MOZ_ANDROID_FAT_AAR_ARCHITECTURES) {
386
// In automation, per-architecture artifacts identify
387
// the architecture; multi-architecture artifacts don't.
388
// When building locally, we produce a "skinny AAR" with
389
// one target architecture masquerading as a "fat AAR"
390
// to enable Gradle composite builds to substitute this
391
// project into consumers easily.
392
artifactId = "${artifactId}-${mozconfig.substs.ANDROID_CPU_ARCH}"
393
}
394
396
397
licenses {
398
license {
399
name = 'The Mozilla Public License, v. 2.0'
401
distribution = 'repo'
402
}
403
}
404
405
scm {
406
if (mozconfig.substs.MOZ_INCLUDE_SOURCE_INFO) {
408
connection = "scm::hg::${mozconfig.substs.MOZ_SOURCE_REPO}"
409
url = mozconfig.substs.MOZ_SOURCE_URL
410
tag = mozconfig.substs.MOZ_SOURCE_CHANGESET
411
} else {
412
// Default to mozilla-central.
413
connection = 'scm::hg::https://hg.mozilla.org/mozilla-central/'
415
}
416
}
417
418
// Unfortunately Gradle does not provide a way to expose dependencies for custom
419
// project types like Android plugins. So we need to add them manually to the POM
420
// XML here, or use a plugin that achieves the same (like
422
// manually since our dependencies are simple and plugins increase our complexity
423
// surface. This workaround can be removed after this issue is fixed:
425
withXml {
426
def dependenciesNode = asNode().appendNode('dependencies')
427
428
configurations.getByName("implementation").dependencies.each {
429
def dependencyNode = dependenciesNode.appendNode('dependency')
430
dependencyNode.appendNode('groupId', it.group)
431
dependencyNode.appendNode('artifactId', it.name)
432
dependencyNode.appendNode('version', it.version)
433
}
434
}
435
}
436
437
artifact tasks["bundle${variant.name.capitalize()}Aar"]
438
439
// Javadoc and sources for developer ergononomics.
440
artifact tasks["javadocJar${variant.name.capitalize()}"]
441
artifact tasks["sourcesJar${variant.name.capitalize()}"]
442
}
443
}
444
}
445
repositories {
446
maven {
447
url = "${project.buildDir}/maven"
448
}
449
}
450
}
451
452
// This is all related to the withGeckoBinaries approach; see
453
// mobile/android/gradle/with_gecko_binaries.gradle.
454
afterEvaluate {
455
// The bundle tasks are only present when the particular configuration is
456
// being built, so this task might not exist. (This is due to the way the
457
// Android Gradle plugin defines things during configuration.)
458
def bundleWithGeckoBinaries = tasks.findByName('bundleWithGeckoBinariesReleaseAar')
459
if (!bundleWithGeckoBinaries) {
460
return
461
}
462
463
// Remove default configuration, which is the release configuration, when
464
// we're actually building withGeckoBinaries. This makes `gradle install`
465
// install the withGeckoBinaries artifacts, not the release artifacts (which
466
// are withoutGeckoBinaries and not suitable for distribution.)
467
def Configuration archivesConfig = project.getConfigurations().getByName('archives')
468
archivesConfig.artifacts.removeAll { it.extension.equals('aar') }
469
470
// For now, ensure Kotlin is only used in tests.
471
android.sourceSets.all { sourceSet ->
472
if (sourceSet.name.startsWith('test') || sourceSet.name.startsWith('androidTest')) {
473
return
474
}
475
(sourceSet.java.srcDirs + sourceSet.kotlin.srcDirs).each {
476
if (!fileTree(it, { include '**/*.kt' }).empty) {
477
throw new GradleException("Kotlin used in non-test directory ${it.path}")
478
}
479
}
480
}
481
}
482
483
// Bug 1353055 - Strip 'vars' debugging information to agree with moz.build.
484
apply from: "${topsrcdir}/mobile/android/gradle/debug_level.gradle"
485
android.libraryVariants.all configureVariantDebugLevel
486
487
// There's nothing specific to the :geckoview project here -- this just needs to
488
// be somewhere where the Android plugin is available so that we can fish the
489
// path to "android.jar".
490
task("generateSDKBindings", type: JavaExec) {
491
classpath project(':annotations').jar.archivePath
492
classpath project(':annotations').compileJava.classpath
493
494
// To use the lint APIs: "Lint must be invoked with the System property
495
// com.android.tools.lint.bindir pointing to the ANDROID_SDK tools
496
// directory"
497
systemProperties = [
498
'com.android.tools.lint.bindir': "${android.sdkDirectory}/tools",
499
]
500
501
main = 'org.mozilla.gecko.annotationProcessors.SDKProcessor'
502
// We only want to generate bindings for the main framework JAR,
503
// but not any of the additional android.test libraries.
504
args android.bootClasspath.findAll { it.getName().startsWith('android.jar') }
505
args 16
506
args "${topobjdir}/widget/android/bindings"
507
508
// Configure the arguments at evaluation-time, not at configuration-time.
509
doFirst {
510
// From -Pgenerate_sdk_bindings_args=... on command line; missing in
511
// `android-gradle-dependencies` toolchain task.
512
if (project.hasProperty('generate_sdk_bindings_args')) {
513
args project.generate_sdk_bindings_args.split(';')
514
}
515
}
516
517
workingDir "${topsrcdir}/widget/android/bindings"
518
519
dependsOn project(':annotations').jar
520
}
521
522
apply plugin: 'org.mozilla.apilint'
523
524
apiLint {
525
// TODO: Change this to `org` after hiding org.mozilla.gecko
526
packageFilter = 'org.mozilla.geckoview'
527
changelogFileName = 'src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md'
528
skipClassesRegex = ['^org.mozilla.geckoview.BuildConfig$']
529
lintFilters = ['GV']
530
allowedPackages = [
531
'java',
532
'android',
533
'org.json',
534
'org.mozilla.geckoview',
535
]
536
}