Call mixed mode Bazel in the symlink forest.

Test: Presubmits + manual execution.
Change-Id: Idef2d821222ccbf9385d0ea3fc92178b3206df0a
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 8d561d2..4598995 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -321,9 +321,8 @@
 // the invocation returned an error code.
 func (r *builtinBazelRunner) issueBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand,
 	extraFlags ...string) (string, string, error) {
-	cmdFlags := []string{"--output_base=" + paths.outputBase, command.command}
+	cmdFlags := []string{"--output_base=" + absolutePath(paths.outputBase), command.command}
 	cmdFlags = append(cmdFlags, command.expression)
-	cmdFlags = append(cmdFlags, "--package_path=%workspace%/"+paths.intermediatesDir())
 	cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(paths, runName))
 
 	// Set default platforms to canonicalized values for mixed builds requests.
@@ -334,20 +333,20 @@
 	// The actual platform values here may be overridden by configuration
 	// transitions from the buildroot.
 	cmdFlags = append(cmdFlags,
-		fmt.Sprintf("--platforms=%s", canonicalizeLabel("//build/bazel/platforms:android_x86_64")))
+		fmt.Sprintf("--platforms=%s", "//build/bazel/platforms:android_x86_64"))
 	cmdFlags = append(cmdFlags,
-		fmt.Sprintf("--extra_toolchains=%s", canonicalizeLabel("//prebuilts/clang/host/linux-x86:all")))
+		fmt.Sprintf("--extra_toolchains=%s", "//prebuilts/clang/host/linux-x86:all"))
 	// This should be parameterized on the host OS, but let's restrict to linux
 	// to keep things simple for now.
 	cmdFlags = append(cmdFlags,
-		fmt.Sprintf("--host_platform=%s", canonicalizeLabel("//build/bazel/platforms:linux_x86_64")))
+		fmt.Sprintf("--host_platform=%s", "//build/bazel/platforms:linux_x86_64"))
 
 	// Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network.
 	cmdFlags = append(cmdFlags, "--experimental_repository_disable_download")
 	cmdFlags = append(cmdFlags, extraFlags...)
 
 	bazelCmd := exec.Command(paths.bazelPath, cmdFlags...)
-	bazelCmd.Dir = paths.workspaceDir
+	bazelCmd.Dir = absolutePath(paths.syntheticWorkspaceDir())
 	bazelCmd.Env = append(os.Environ(), "HOME="+paths.homeDir, pwdPrefix(),
 		// Disables local host detection of gcc; toolchain information is defined
 		// explicitly in BUILD files.
@@ -363,31 +362,6 @@
 	}
 }
 
-// Returns the string contents of a workspace file that should be output
-// adjacent to the main bzl file and build file.
-// This workspace file allows, via local_repository rule, sourcetree-level
-// BUILD targets to be referenced via @sourceroot.
-func (context *bazelContext) workspaceFileContents() []byte {
-	formatString := `
-# This file is generated by soong_build. Do not edit.
-local_repository(
-    name = "sourceroot",
-    path = "%[1]s",
-)
-
-local_repository(
-    name = "rules_cc",
-    path = "%[1]s/build/bazel/rules_cc",
-)
-
-local_repository(
-    name = "bazel_skylib",
-    path = "%[1]s/build/bazel/bazel_skylib",
-)
-`
-	return []byte(fmt.Sprintf(formatString, context.paths.workspaceDir))
-}
-
 func (context *bazelContext) mainBzlFileContents() []byte {
 	// TODO(cparsons): Define configuration transitions programmatically based
 	// on available archs.
@@ -398,7 +372,7 @@
 
 def _config_node_transition_impl(settings, attr):
     return {
-        "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:android_%s" % attr.arch,
+        "//command_line_option:platforms": "@//build/bazel/platforms:android_%s" % attr.arch,
     }
 
 _config_node_transition = transition(
@@ -447,18 +421,6 @@
 	return []byte(contents)
 }
 
-// Returns a "canonicalized" corresponding to the given sourcetree-level label.
-// This abstraction is required because a sourcetree label such as //foo/bar:baz
-// must be referenced via the local repository prefix, such as
-// @sourceroot//foo/bar:baz.
-func canonicalizeLabel(label string) string {
-	if strings.HasPrefix(label, "//") {
-		return "@sourceroot" + label
-	} else {
-		return "@sourceroot//" + label
-	}
-}
-
 func (context *bazelContext) mainBuildFileContents() []byte {
 	// TODO(cparsons): Map label to attribute programmatically; don't use hard-coded
 	// architecture mapping.
@@ -487,7 +449,7 @@
 
 	labelsByArch := map[string][]string{}
 	for val, _ := range context.requests {
-		labelString := fmt.Sprintf("\"%s\"", canonicalizeLabel(val.label))
+		labelString := fmt.Sprintf("\"@%s\"", val.label)
 		archString := getArchString(val)
 		labelsByArch[archString] = append(labelsByArch[archString], labelString)
 	}
@@ -593,12 +555,24 @@
 		mainSwitchSection))
 }
 
-// Returns a workspace-relative path containing build-related metadata required
-// for interfacing with Bazel. Example: out/soong/bazel.
+// Returns a path containing build-related metadata required for interfacing
+// with Bazel. Example: out/soong/bazel.
 func (p *bazelPaths) intermediatesDir() string {
 	return filepath.Join(p.buildDir, "bazel")
 }
 
+// Returns the path where the contents of the @soong_injection repository live.
+// It is used by Soong to tell Bazel things it cannot over the command line.
+func (p *bazelPaths) injectedFilesDir() string {
+	return filepath.Join(p.buildDir, "soong_injection")
+}
+
+// Returns the path of the synthetic Bazel workspace that contains a symlink
+// forest composed the whole source tree and BUILD files generated by bp2build.
+func (p *bazelPaths) syntheticWorkspaceDir() string {
+	return filepath.Join(p.buildDir, "workspace")
+}
+
 // Issues commands to Bazel to receive results for all cquery requests
 // queued in the BazelContext.
 func (context *bazelContext) InvokeBazel() error {
@@ -608,47 +582,47 @@
 	var cqueryErr string
 	var err error
 
-	intermediatesDirPath := absolutePath(context.paths.intermediatesDir())
-	if _, err := os.Stat(intermediatesDirPath); os.IsNotExist(err) {
-		err = os.Mkdir(intermediatesDirPath, 0777)
+	soongInjectionPath := absolutePath(context.paths.injectedFilesDir())
+	if _, err := os.Stat(soongInjectionPath); os.IsNotExist(err) {
+		err = os.Mkdir(soongInjectionPath, 0777)
 	}
-
 	if err != nil {
 		return err
 	}
+
+	err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666)
+	if err != nil {
+		return err
+	}
+
 	err = ioutil.WriteFile(
-		filepath.Join(intermediatesDirPath, "main.bzl"),
+		filepath.Join(soongInjectionPath, "main.bzl"),
 		context.mainBzlFileContents(), 0666)
 	if err != nil {
 		return err
 	}
+
 	err = ioutil.WriteFile(
-		filepath.Join(intermediatesDirPath, "BUILD.bazel"),
+		filepath.Join(soongInjectionPath, "BUILD.bazel"),
 		context.mainBuildFileContents(), 0666)
 	if err != nil {
 		return err
 	}
-	cqueryFileRelpath := filepath.Join(context.paths.intermediatesDir(), "buildroot.cquery")
+	cqueryFileRelpath := filepath.Join(context.paths.injectedFilesDir(), "buildroot.cquery")
 	err = ioutil.WriteFile(
 		absolutePath(cqueryFileRelpath),
 		context.cqueryStarlarkFileContents(), 0666)
 	if err != nil {
 		return err
 	}
-	err = ioutil.WriteFile(
-		filepath.Join(intermediatesDirPath, "WORKSPACE.bazel"),
-		context.workspaceFileContents(), 0666)
-	if err != nil {
-		return err
-	}
-	buildrootLabel := "//:buildroot"
+	buildrootLabel := "@soong_injection//:buildroot"
 	cqueryOutput, cqueryErr, err = context.issueBazelCommand(
 		context.paths,
 		bazel.CqueryBuildRootRunName,
 		bazelCommand{"cquery", fmt.Sprintf("kind(rule, deps(%s))", buildrootLabel)},
 		"--output=starlark",
-		"--starlark:file="+cqueryFileRelpath)
-	err = ioutil.WriteFile(filepath.Join(intermediatesDirPath, "cquery.out"),
+		"--starlark:file="+absolutePath(cqueryFileRelpath))
+	err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"),
 		[]byte(cqueryOutput), 0666)
 	if err != nil {
 		return err
@@ -702,7 +676,7 @@
 	_, _, err = context.issueBazelCommand(
 		context.paths,
 		bazel.BazelBuildPhonyRootRunName,
-		bazelCommand{"build", "//:phonyroot"})
+		bazelCommand{"build", "@soong_injection//:phonyroot"})
 
 	if err != nil {
 		return err
@@ -781,7 +755,7 @@
 }
 
 func getCqueryId(key cqueryKey) string {
-	return canonicalizeLabel(key.label) + "|" + getArchString(key)
+	return key.label + "|" + getArchString(key)
 }
 
 func getArchString(key cqueryKey) string {