Move outDir set up to settings.gradle

Our previous setup was using subproject {} which violates project
isolation. The new approach is to use getGradle.beforeProject {}
to achieve the same affect and still be compatible with project
isolation.

Also add workaround to code generating projects that require reaching
to buildDir of other projects before these projects are configured.

Test: ./gradlew tasks -> output still in out directory like expected
Change-Id: I3b3a2f5584827bcc74cf662127c77f06ae7c8b55
diff --git a/appsearch/compiler/build.gradle b/appsearch/compiler/build.gradle
index 274830c..f5a982c 100644
--- a/appsearch/compiler/build.gradle
+++ b/appsearch/compiler/build.gradle
@@ -31,7 +31,11 @@
 
     // For testing, add in the compiled classes from appsearch to get access to annotations.
     testImplementation fileTree(
-            dir: "${new File(project(":appsearch:appsearch").buildDir, "libJar")}",
+            dir: provider {
+                // Wrapping in a provider as a workaround as we access buildDir before this project is configured
+                // Replace with AGP API once it is added b/228109260
+                "${new File(project(":appsearch:appsearch").buildDir, "libJar")}"
+            },
             include : "*.jar"
     )
     testImplementation(libs.googleCompileTesting)
diff --git a/build.gradle b/build.gradle
index 99a5690..3a6b8e5 100644
--- a/build.gradle
+++ b/build.gradle
@@ -23,7 +23,5 @@
 }
 
 apply from: "buildSrc/dependencies.gradle"
-apply from: "buildSrc/out.gradle"
-init.chooseOutDir()
 
 apply plugin: AndroidXRootPlugin
diff --git a/buildSrc/out.gradle b/buildSrc/out.gradle
index be42e80..0ca9069 100644
--- a/buildSrc/out.gradle
+++ b/buildSrc/out.gradle
@@ -14,25 +14,34 @@
  * limitations under the License.
  */
 
+import groovy.lang.Tuple;
+
 def init = new Properties()
 ext.init = init
 
-def chooseOutDir(subdir = "") {
+def getOutDir(subdir = "") {
     /*
      * The OUT_DIR is a temporary directory you can use to put things during the build.
      */
     def outDir = System.env.OUT_DIR
+    def buildSrcOut
     if (outDir == null) {
         def checkoutRoot = System.getProperty("CHECKOUT_ROOT")
         if (checkoutRoot == null) {
             checkoutRoot = new File("${buildscript.sourceFile.parent}/../../..")
         }
         outDir = new File("${checkoutRoot}/out${subdir}")
-        project.ext.buildSrcOut = new File("${checkoutRoot}/out/buildSrc")
+        buildSrcOut = new File("${checkoutRoot}/out/buildSrc")
     } else {
         outDir = new File(outDir)
-        project.ext.buildSrcOut = new File("${outDir}/buildSrc")
+        buildSrcOut = new File("${outDir}/buildSrc")
     }
+    return new Tuple(outDir, buildSrcOut)
+}
+
+def chooseOutDir(subdir = "") {
+    def (outDir, buildSrcOut) = getOutDir(subdir)
+    project.ext.buildSrcOut = buildSrcOut
     project.ext.outDir = outDir
     buildDir = new File(outDir, "$project.name/build")
                 .getCanonicalFile()
@@ -42,4 +51,5 @@
     }
 }
 
+ext.init.getOutDir = this.&getOutDir
 ext.init.chooseOutDir = this.&chooseOutDir
diff --git a/hilt/hilt-compiler/build.gradle b/hilt/hilt-compiler/build.gradle
index c105976..9494a98 100644
--- a/hilt/hilt-compiler/build.gradle
+++ b/hilt/hilt-compiler/build.gradle
@@ -39,7 +39,11 @@
     testImplementation(libs.googleCompileTesting)
     testImplementation(libs.hiltCore)
     testImplementation(fileTree(
-            dir: "${new File(project(":hilt:hilt-work").buildDir, "libJar")}",
+            dir: provider {
+                // Replace with AGP API once it is added b/228109260
+                // Wrapping in a provider as a workaround as we access buildDir before this project is configured
+                "${new File(project(":hilt:hilt-work").buildDir, "libJar")}"
+            },
             include : "*.jar"))
     testImplementation(fileTree(
             dir: "${SdkHelperKt.getSdkPath(project)}/platforms/$SupportConfig.COMPILE_SDK_VERSION/",
diff --git a/navigation/navigation-safe-args-generator/build.gradle b/navigation/navigation-safe-args-generator/build.gradle
index 5327a64..dda3c51 100644
--- a/navigation/navigation-safe-args-generator/build.gradle
+++ b/navigation/navigation-safe-args-generator/build.gradle
@@ -38,11 +38,19 @@
             include : "android.jar"
     ))
     testImplementation(fileTree(
-            dir: "${new File(project(":navigation:navigation-common").buildDir, "libJar")}",
+            dir: provider {
+                // Wrapping in a provider as a workaround as we access buildDir before this project is configured
+                // Replace with AGP API once it is added b/228109260
+                "${new File(project(":navigation:navigation-common").buildDir, "libJar")}"
+            },
             include : "*.jar"
     ))
     testImplementation(fileTree(
-            dir: "${new File(project(":lifecycle:lifecycle-viewmodel-savedstate").buildDir, "libJar")}",
+            dir: provider {
+                // Wrapping in a provider as a workaround as we access buildDir before this project is configured
+                // Replace with AGP API once it is added b/228109260
+                "${new File(project(":lifecycle:lifecycle-viewmodel-savedstate").buildDir, "libJar")}"
+            },
             include : "*.jar"
     ))
 }
diff --git a/room/room-compiler/build.gradle b/room/room-compiler/build.gradle
index 8e4ae16..5c8afcd 100644
--- a/room/room-compiler/build.gradle
+++ b/room/room-compiler/build.gradle
@@ -114,11 +114,19 @@
             include : "android.jar"
     ))
     testImplementation(fileTree(
-            dir: "${new File(project(":room:room-runtime").buildDir, "intermediates/runtime_library_classes_jar/release/")}",
+            dir: provider {
+                // Wrapping in a provider as we access buildDir before this project is configured
+                // Replace with AGP API once it is added b/228109260
+                "${new File(project(":room:room-runtime").buildDir, "intermediates/runtime_library_classes_jar/release/")}"
+            },
             include : "*.jar"
     ))
     testImplementation(fileTree(
-            dir: "${new File(project(":sqlite:sqlite").buildDir, "libJar")}",
+            dir: provider {
+                // Wrapping in a provider as we access buildDir before this project is configured
+                // Replace with AGP API once it is added b/228109260
+                "${new File(project(":sqlite:sqlite").buildDir, "libJar")}"
+            },
             include : "*.jar"
     ))
     testImplementation(project(":internal-testutils-common"))
diff --git a/settings.gradle b/settings.gradle
index 4bd16f4a..e7727e3 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -33,12 +33,19 @@
 ).absolutePath
 def rootProjectRepositories
 
+apply from: "buildSrc/out.gradle"
+def (outDir, buildSrcOut) = init.getOutDir()
+
 getGradle().beforeProject {
     // Migrate to dependencyResolutionManagement.repositories when
     // https://github.com/gradle/gradle/issues/17295 is fixed
     if (it.path == ":") {
         repos.addMavenRepositories(it.repositories)
         rootProjectRepositories = it.repositories
+
+        // Set buildSrcOut and outDir extras on root project
+        it.ext.buildSrcOut = buildSrcOut
+        it.ext.outDir = outDir
     } else {
         // Performance optimization because it is more efficient to reuse
         // repositories from the root project than recreate identical ones
@@ -46,6 +53,8 @@
         it.repositories.addAll(rootProjectRepositories)
     }
     it.ext.prebuiltsRoot = prebuiltsRoot
+    // Expected out directory structure for :foo:bar is out/androidx/foo/bar
+    it.buildDir = new File(outDir, "androidx/${it.path.replace(":", "/")}/build")
 }
 
 apply(plugin: "com.gradle.enterprise")