Merge "Add minimal gradle.properties to playground buidls" into androidx-master-dev
diff --git a/buildSrc/src/main/kotlin/androidx/build/AndroidXRootPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/AndroidXRootPlugin.kt
index 1a011b5..1c47c0b 100644
--- a/buildSrc/src/main/kotlin/androidx/build/AndroidXRootPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/AndroidXRootPlugin.kt
@@ -24,6 +24,7 @@
 import androidx.build.gradle.isRoot
 import androidx.build.jacoco.Jacoco
 import androidx.build.license.CheckExternalDependencyLicensesTask
+import androidx.build.playground.VerifyPlaygroundGradlePropertiesTask
 import androidx.build.studio.StudioTask.Companion.registerStudioTask
 import androidx.build.uptodatedness.TaskUpToDateValidator
 import com.android.build.gradle.api.AndroidBasePlugin
@@ -76,6 +77,10 @@
             tasks.register(AndroidXPlugin.CREATE_LIBRARY_BUILD_INFO_FILES_TASK)
         )
 
+        VerifyPlaygroundGradlePropertiesTask.createIfNecessary(project)?.let {
+            buildOnServerTask.dependsOn(it)
+        }
+
         extra.set("versionChecker", GMavenVersionChecker(logger))
         val createArchiveTask = Release.getGlobalFullZipTask(this)
         buildOnServerTask.dependsOn(createArchiveTask)
diff --git a/buildSrc/src/main/kotlin/androidx/build/playground/VerifyPlaygroundGradlePropertiesTask.kt b/buildSrc/src/main/kotlin/androidx/build/playground/VerifyPlaygroundGradlePropertiesTask.kt
new file mode 100644
index 0000000..8721a8f0
--- /dev/null
+++ b/buildSrc/src/main/kotlin/androidx/build/playground/VerifyPlaygroundGradlePropertiesTask.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.build.playground
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.GradleException
+import org.gradle.api.Project
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.tasks.InputFile
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.TaskAction
+import org.gradle.api.tasks.TaskProvider
+import java.io.File
+import java.util.Properties
+
+/**
+ * Compares the properties file for playground projects with the main androidx properties file
+ * to ensure playgrounds do not define any property in their own build that conflicts with the
+ * main build.
+ */
+@Suppress("UnstableApiUsage") // for fileProperty
+abstract class VerifyPlaygroundGradlePropertiesTask : DefaultTask() {
+    @get:InputFile
+    abstract val androidxProperties: RegularFileProperty
+
+    @get:InputFile
+    abstract val playgroundProperties: RegularFileProperty
+
+    @get:OutputFile
+    abstract val outputFile: RegularFileProperty
+
+    @TaskAction
+    fun compareProperties() {
+        val rootProperties = loadPropertiesFile(androidxProperties.get().asFile)
+        val playgroundProperties = loadPropertiesFile(playgroundProperties.get().asFile)
+        validateProperties(rootProperties, playgroundProperties)
+    }
+
+    private fun validateProperties(
+        rootProperties: Properties,
+        playgroundProperties: Properties
+    ) {
+        // ensure we don't define properties that do not match the root file
+        // this includes properties that are not defined in the root androidx build as they might
+        // be properties which can alter the build output. We might consider whitelisting certain
+        // properties in the future if necessary.
+        playgroundProperties.forEach {
+            val rootValue = rootProperties[it.key]
+            if (rootValue != it.value) {
+                throw GradleException(
+                    """
+                    ${it.key} is defined as ${it.value} in playground properties but
+                    it does not match the value defined in root properties file ($rootValue).
+                    Having inconsistent properties in playground projects might trigger wrong
+                    compilation output in the main AndroidX build, thus not allowed.
+                    """.trimIndent()
+                )
+            }
+        }
+        // put the success into an output so that task can be up to date.
+        outputFile.get().asFile.writeText("valid", Charsets.UTF_8)
+    }
+
+    private fun loadPropertiesFile(file: File) = file.inputStream().use { inputStream ->
+        Properties().apply {
+            load(inputStream)
+        }
+    }
+
+    companion object {
+        private const val TASK_NAME = "verifyPlaygroundGradleProperties"
+
+        /**
+         * Creates the task to verify playground properties if an only if we have the
+         * playground-common folder to check against.
+         */
+        fun createIfNecessary(
+            project: Project
+        ): TaskProvider<VerifyPlaygroundGradlePropertiesTask>? {
+            return if (project.projectDir.resolve("playground-common").exists()) {
+                project.tasks.register(
+                    TASK_NAME,
+                    VerifyPlaygroundGradlePropertiesTask::class.java
+                ) {
+                    it.androidxProperties.set(
+                        project.layout.projectDirectory.file("gradle.properties")
+                    )
+                    it.playgroundProperties.set(
+                        project.layout.projectDirectory.file(
+                            "playground-common/androidx-shared.properties"
+                        )
+                    )
+                    it.outputFile.set(
+                        project.layout.buildDirectory.file("playgroundPropertiesValidation.out")
+                    )
+                }
+            } else {
+                null
+            }
+        }
+    }
+}
diff --git a/playground-common/README.md b/playground-common/README.md
index 59bd21f..99fb098 100644
--- a/playground-common/README.md
+++ b/playground-common/README.md
@@ -41,6 +41,21 @@
 method or filter projects from the main AndroidX settings gradle file using the
 `selectProjectsFromAndroidX` method.
 
+### Properties
+When a `gradle.properties` file shows up under a sub project, main AndroidX build ends up
+reading it. For this reason, we can only keep a minimal `gradle.properties` file in these
+sub modules that also support playground setup.
+
+We cannot avoid creating `gradle.properties` as certain properties (e.g. `useAndroidX`) are
+read at configuration time and we cannot set it dynamically.
+
+Properties that will be set dynamically are kept in `playground.properties` file while
+shared properties are kept in `androidx-shared.properties` file.
+The dynamic properties are read in the `playground-include-settings.gradle` file and set
+on each project.
+
+There is a `VerifyPlaygroundGradlePropertiesTask` task that validates the contents of
+`androidx-shared.properties` file as part of the main AndroidX build.
 ### Optional Dependencies
 Even though sub-projects usually declare exact coordinates for their dependencies,
 for tests, it is a common practice to declare `project` dependencies. To avoid needing
diff --git a/playground-common/androidx-shared.properties b/playground-common/androidx-shared.properties
new file mode 100644
index 0000000..606adab
--- /dev/null
+++ b/playground-common/androidx-shared.properties
@@ -0,0 +1,33 @@
+#
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Properties that are copied from main properties file
+# We set playground properties in two steps:
+# * This file is linked into gradle.properties under the project and limited to
+#   just copying properties from the androidx properties file without any change.
+#   Its integrity is validated as part of the buildOnServer task in AndroidX.
+#   (validatePlaygroundGradleProperties task)
+# * Additional settings are in playground.properties which are loaded dynamically
+# This separation is necessary to ensure gradle can read certain properties
+# at configuration time.
+
+android.useAndroidX=true
+# Disable features we do not use
+android.defaults.buildfeatures.aidl=false
+android.defaults.buildfeatures.buildconfig=false
+android.defaults.buildfeatures.renderscript=false
+android.defaults.buildfeatures.resvalues=false
+android.defaults.buildfeatures.shaders=false
diff --git a/playground-common/playground.properties b/playground-common/playground.properties
index 86cffc9..d02bbef 100644
--- a/playground-common/playground.properties
+++ b/playground-common/playground.properties
@@ -14,15 +14,6 @@
 # limitations under the License.
 #
 
-# Project-wide Gradle settings.
-# IDE (e.g. Android Studio) users:
-# Gradle settings configured through the IDE *will override*
-# any settings specified in this file.
-# For more details on how to configure your build environment visit
-# http://www.gradle.org/docs/current/userguide/build_environment.html
-# Specifies the JVM arguments used for the daemon process.
-# The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx2048m
 # When configured, Gradle will run in incubating parallel mode.
 # This option should only be used with decoupled projects. More details, visit
 # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
@@ -30,10 +21,8 @@
 # AndroidX package structure to make it clearer which packages are bundled with the
 # Android operating system, and which are packaged with your app"s APK
 # https://developer.android.com/topic/libraries/support-library/androidx-rn
-android.useAndroidX=true
-# Automatically convert third-party libraries to use AndroidX
-android.enableJetifier=true
 # Kotlin code style for this project: "official" or "obsolete":
+org.gradle.jvmargs=-Xmx2048m
 kotlin.code.style=official
 # Disable docs
 androidx.enableDocumentation=false
@@ -43,10 +32,3 @@
 androidx.playground.metalavaBuildId=6604778
 androidx.playground.dokkaBuildId=6656073
 androidx.studio.type=playground
-
-# Disable features we do not use
-android.defaults.buildfeatures.aidl=false
-android.defaults.buildfeatures.buildconfig=false
-android.defaults.buildfeatures.renderscript=false
-android.defaults.buildfeatures.resvalues=false
-android.defaults.buildfeatures.shaders=false
diff --git a/playground-common/setup-playground.sh b/playground-common/setup-playground.sh
index 650ae3d..ee41940 100755
--- a/playground-common/setup-playground.sh
+++ b/playground-common/setup-playground.sh
@@ -17,6 +17,8 @@
 ln -s "${PLAYGROUND_REL_PATH}/gradlew" gradlew
 rm -rf gradlew.bat
 ln -s "${PLAYGROUND_REL_PATH}/gradlew.bat" gradlew.bat
+rm -rf gradle.properties
+ln -s "${PLAYGROUND_REL_PATH}/androidx-shared.properties" gradle.properties
 
 ANDROIDX_IDEA_DIR="${PLAYGROUND_REL_PATH}/../.idea"
 
diff --git a/playground/gradle.properties b/playground/gradle.properties
new file mode 120000
index 0000000..d952fb0
--- /dev/null
+++ b/playground/gradle.properties
@@ -0,0 +1 @@
+../playground-common/androidx-shared.properties
\ No newline at end of file
diff --git a/room/gradle.properties b/room/gradle.properties
new file mode 120000
index 0000000..d952fb0
--- /dev/null
+++ b/room/gradle.properties
@@ -0,0 +1 @@
+../playground-common/androidx-shared.properties
\ No newline at end of file
diff --git a/work/gradle.properties b/work/gradle.properties
new file mode 120000
index 0000000..d952fb0
--- /dev/null
+++ b/work/gradle.properties
@@ -0,0 +1 @@
+../playground-common/androidx-shared.properties
\ No newline at end of file