Revert "Revert "Support for testing different dependency versions""
This reverts commit 4e0409161cc998c8ac8004ff78b6ee404fb37cc2.
Reason for revert: Now that we are pushing the new updated AGP, this OutOfMemory error has a high chance of disappearing, so we are going to test one more time.
Test: ./gradlew bOS
Change-Id: I01b69ca02683a1bfff1dafabb960c344bf73c17b
diff --git a/buildSrc/init.gradle b/buildSrc/init.gradle
index 410952c..7674773 100644
--- a/buildSrc/init.gradle
+++ b/buildSrc/init.gradle
@@ -90,8 +90,10 @@
// Copy instrumentation test APKs and app APKs into the dist dir
// For test apks, they are uploaded only if we have java test sources.
// For regular app apks, they are uploaded only if they have java sources.
+ // Copy only the minDepVersions debug version since that is the publish
+ // flavor.
project.tasks.whenTaskAdded { task ->
- if (task.name.startsWith("packageDebug")) {
+ if (task.name.startsWith("packageMinDepVersionsDebug")) {
// run this task only if we should run it
def testApk = task.name.contains("AndroidTest")
if (testApk) {
@@ -122,7 +124,10 @@
// Exclude media-compat-test-* modules from existing support library
// presubmit tests.
if (fileName.contains("media-compat-test")) {
- fileName.replace("-debug-androidTest", "")
+ fileName
+ .replace(fileName,
+ "minDepVersions-${fileName}")
+ .replace("-minDepVersions-debug-androidTest", "")
} else {
// multiple modules may have the same name so prefix the name with
// the module's path to ensure it is unique.
diff --git a/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
index 948eb00..b1b6f61 100644
--- a/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
@@ -36,11 +36,13 @@
import org.gradle.api.JavaVersion.VERSION_1_8
import org.gradle.api.Plugin
import org.gradle.api.Project
+import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.plugins.JavaLibraryPlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.compile.JavaCompile
+import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.getPlugin
import org.gradle.kotlin.dsl.withType
@@ -157,7 +159,6 @@
private fun Project.configureAndroidCommonOptions(extension: BaseExtension) {
extension.compileSdkVersion(CURRENT_SDK_VERSION)
extension.buildToolsVersion = BUILD_TOOLS_VERSION
-
// Expose the compilation SDK for use as the target SDK in test manifests.
extension.defaultConfig.addManifestPlaceholders(
mapOf("target-sdk-version" to CURRENT_SDK_VERSION))
@@ -177,6 +178,35 @@
project.dependencies.add("annotationProcessor",
project.project(":customerrorprone"))
}
+ project.configurations.all { configuration ->
+ configuration.resolutionStrategy.eachDependency { dep ->
+ val target = dep.target
+ // Enforce the ban on declaring dependencies with version ranges.
+ if (isDependencyRange(target.version)) {
+ throw IllegalArgumentException(
+ "Dependency ${dep.target} declares its version as " +
+ "version range ${dep.target.version} however the use of " +
+ "version ranges is not allowed, please update the " +
+ "dependency to list a fixed version.")
+ }
+ }
+ }
+ }
+ if (project.name != "docs-fake") {
+ // Add another "version" flavor dimension which would have two flavors minDepVersions
+ // and maxDepVersions. Flavor minDepVersions builds the libraries against the specified
+ // versions of their dependencies while maxDepVersions builds the libraries against
+ // the local versions of their dependencies (so for example if library A specifies
+ // androidx.collection:collection:1.2.0 as its dependency then minDepVersions would
+ // build using exactly that version while maxDepVersions would build against
+ // project(":collection") instead.)
+ extension.flavorDimensions("version")
+ extension.productFlavors {
+ it.create("minDepVersions")
+ it.get("minDepVersions").dimension = "version"
+ it.create("maxDepVersions")
+ it.get("maxDepVersions").dimension = "version"
+ }
}
// Use a local debug keystore to avoid build server issues.
@@ -194,6 +224,16 @@
extension.buildTypes.getByName("debug").isTestCoverageEnabled =
!hasProperty("android.injected.invoked.from.ide") &&
!isBenchmark()
+
+ extension.variants.all { variant ->
+ if (variant.flavorName.toLowerCase().contains(
+ "maxdepversions")) {
+ useMaxiumumDependencyVersions(project.configurations)
+ }
+ }
+ // Set the officially published version to be the release version with minimum dependency
+ // versions.
+ extension.defaultPublishConfig(Release.DEFAULT_PUBLISH_CONFIG)
}
private fun Project.configureAndroidLibraryOptions(extension: LibraryExtension) {
@@ -253,3 +293,50 @@
// benchmark convention is to end name with "-benchmark"
return name.endsWith("-benchmark")
}
+
+/**
+ * Goes through all the dependencies in the passed in configurations and finds each dependency
+ * depending on an androidx library, then each of these dependencies is substituted with its
+ * equivalent in the current development project (e.g module("androidx.collection:collection:x.y.z")
+ * becomes project(":collection".) Throws an error if there is a major release conflict between
+ * the two dependency versions.
+ */
+private fun Project.useMaxiumumDependencyVersions(configurations: ConfigurationContainer) {
+ configurations.all { configuration ->
+ configuration.resolutionStrategy.eachDependency { dep ->
+ if (artifactSupportsSemVer(dep.target.group)) {
+ // TODO: support projects having two ':' chars in the name
+ val localDependencyProject = findProject(":${dep.target.name}")
+ if (localDependencyProject != null &&
+ localDependencyProject.version.toString() != "unspecified") {
+ if (localDependencyProject.version().major ==
+ Version(dep.target.version!!).major) {
+ configuration.resolutionStrategy.dependencySubstitution.apply {
+ substitute(module("${dep.target}"))
+ .with(project(":${localDependencyProject.name}"))
+ }
+ } else {
+ throw IllegalArgumentException("The local version for dependency" +
+ " ${localDependencyProject.name} is in major release" +
+ " ${localDependencyProject.version().major}, but the " +
+ "specified dependency's major release is " +
+ "${Version(dep.target.version!!).major}" +
+ ", please update the dependency's version to match " +
+ "that major release as it is required that all libraries at HEAD " +
+ "are compatible with each other at all times")
+ }
+ }
+ }
+ }
+ }
+}
+
+private fun isDependencyRange(version: String?): Boolean {
+ return ((version!!.startsWith("[") || version.startsWith("(")) &&
+ (version.endsWith("]") || version.endsWith(")")) ||
+ version.endsWith("+"))
+}
+
+private fun artifactSupportsSemVer(artifactGroup: String): Boolean {
+ return artifactGroup.startsWith("androidx.")
+}
\ No newline at end of file
diff --git a/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt b/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt
index d2af2b9..560c87c 100644
--- a/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt
@@ -291,9 +291,8 @@
) {
registerPrebuilts(extension)
-
library.libraryVariants.all { variant ->
- if (variant.name == "release") {
+ if (variant.name == Release.DEFAULT_PUBLISH_CONFIG) {
// include R.file generated for prebuilts
rules.filter { it.resolve(extension)?.strategy is Prebuilts }.forEach { rule ->
docsTasks[rule.name]?.include { fileTreeElement ->
diff --git a/buildSrc/src/main/kotlin/androidx/build/Release.kt b/buildSrc/src/main/kotlin/androidx/build/Release.kt
index 7bdf64e..0161039 100644
--- a/buildSrc/src/main/kotlin/androidx/build/Release.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/Release.kt
@@ -174,6 +174,7 @@
@Suppress("MemberVisibilityCanBePrivate")
const val DIFF_TASK_PREFIX = "createDiffArchive"
const val FULL_ARCHIVE_TASK_NAME = "createArchive"
+ const val DEFAULT_PUBLISH_CONFIG = "minDepVersionsRelease"
// lazily created config action params so that we don't keep re-creating them
private var configActionParams: GMavenZipTask.ConfigAction.Params? = null
diff --git a/core/build.gradle b/core/build.gradle
index 5a76b23..6f57be3 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -8,7 +8,7 @@
dependencies {
api(project(":annotation"))
- api(project(":collection"))
+ api("androidx.collection:collection:1.0.0")
api(ARCH_LIFECYCLE_RUNTIME, libs.exclude_annotations_transitive)
api project(':versionedparcelable')
diff --git a/docs-fake/build.gradle b/docs-fake/build.gradle
index aa268d1..e73ba9b 100644
--- a/docs-fake/build.gradle
+++ b/docs-fake/build.gradle
@@ -44,5 +44,5 @@
manifest.srcFile "AndroidManifest.xml"
}
}
- flavorDimensions("library-group")
+ flavorDimensions "library-group"
}
diff --git a/navigation/common/build.gradle b/navigation/common/build.gradle
index e55c040..24fd3eb 100644
--- a/navigation/common/build.gradle
+++ b/navigation/common/build.gradle
@@ -49,7 +49,7 @@
//used by testCompile safe-args-generator
android.libraryVariants.all { variant ->
- def name = variant.buildType.name
+ def name = variant.name
def suffix = name.capitalize()
project.tasks.create(name: "jar${suffix}", type: Jar){
dependsOn variant.javaCompile
diff --git a/navigation/safe-args-generator/build.gradle b/navigation/safe-args-generator/build.gradle
index b2eba0b..2c086b7 100644
--- a/navigation/safe-args-generator/build.gradle
+++ b/navigation/safe-args-generator/build.gradle
@@ -54,7 +54,7 @@
it.classpath = files(classpath.minus(androidJar).plus(androidJar))
}
-tasks.findByName("compileKotlin").dependsOn(":navigation:navigation-common:jarDebug")
+tasks.findByName("compileKotlin").dependsOn(":navigation:navigation-common:jarMinDepVersionsDebug")
supportLibrary {
name = 'Android Navigation TypeSafe Arguments Generator'
diff --git a/persistence/db/build.gradle b/persistence/db/build.gradle
index f8730cb..299502b 100644
--- a/persistence/db/build.gradle
+++ b/persistence/db/build.gradle
@@ -31,7 +31,7 @@
// Used by testCompile in room-compiler
android.libraryVariants.all { variant ->
- def name = variant.buildType.name
+ def name = variant.name
def suffix = name.capitalize()
def jarTask = project.tasks.create(name: "jar${suffix}", type: Jar){
dependsOn variant.javaCompile
diff --git a/room/compiler/build.gradle b/room/compiler/build.gradle
index 76efe9a..6a35f0a 100644
--- a/room/compiler/build.gradle
+++ b/room/compiler/build.gradle
@@ -79,8 +79,8 @@
}
tasks.findByName("compileKotlin").dependsOn(generateAntlrTask)
-tasks.findByName("compileKotlin").dependsOn(":room:room-runtime:jarDebug")
-tasks.findByName("compileKotlin").dependsOn(":sqlite:sqlite:jarDebug")
+tasks.findByName("compileKotlin").dependsOn(":room:room-runtime:jarMinDepVersionsDebug")
+tasks.findByName("compileKotlin").dependsOn(":sqlite:sqlite:jarMinDepVersionsDebug")
supportLibrary {
name = "Android Room Compiler"
diff --git a/room/runtime/build.gradle b/room/runtime/build.gradle
index eb262ed..7e8100d 100644
--- a/room/runtime/build.gradle
+++ b/room/runtime/build.gradle
@@ -52,7 +52,7 @@
// Used by testCompile in room-compiler
android.libraryVariants.all { variant ->
- def name = variant.buildType.name
+ def name = variant.name
def suffix = name.capitalize()
project.tasks.create(name: "jar${suffix}", type: Jar){
dependsOn variant.javaCompile