Direct Bazel builds from m.

This CL adds support to bp2build/Soong to dump a BUILD file under
out/soong/soong_injection/targets containing alias targets to their real
targets for every converted Soong module, regardless of whether they are
handcrafted or generated.

Test: TH
Change-Id: Ic1816fda5d019c395301618134fac68b3057d752
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 3abbc4c..0e6030e 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -11,6 +11,7 @@
         "build_conversion.go",
         "bzl_conversion.go",
         "configurability.go",
+        "compatibility.go",
         "constants.go",
         "conversion.go",
         "metrics.go",
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index ee36982..06a7306 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -29,12 +29,12 @@
 	bp2buildDir := android.PathForOutput(ctx, "bp2build")
 	android.RemoveAllOutputDir(bp2buildDir)
 
-	buildToTargets, metrics := GenerateBazelTargets(ctx, true)
+	buildToTargets, metrics, compatLayer := GenerateBazelTargets(ctx, true)
 	bp2buildFiles := CreateBazelFiles(nil, buildToTargets, ctx.mode)
 	writeFiles(ctx, bp2buildDir, bp2buildFiles)
 
 	soongInjectionDir := android.PathForOutput(ctx, bazel.SoongInjectionDirName)
-	writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles())
+	writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles(compatLayer))
 
 	return metrics
 }
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index a1e0424..96a8b09 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -32,6 +32,7 @@
 
 type BazelTarget struct {
 	name            string
+	packageName     string
 	content         string
 	ruleClass       string
 	bzlLoadLocation string
@@ -44,6 +45,16 @@
 	return t.bzlLoadLocation != ""
 }
 
+// Label is the fully qualified Bazel label constructed from the BazelTarget's
+// package name and target name.
+func (t BazelTarget) Label() string {
+	if t.packageName == "." {
+		return "//:" + t.name
+	} else {
+		return "//" + t.packageName + ":" + t.name
+	}
+}
+
 // BazelTargets is a typedef for a slice of BazelTarget objects.
 type BazelTargets []BazelTarget
 
@@ -213,7 +224,7 @@
 	return attributes
 }
 
-func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (map[string]BazelTargets, CodegenMetrics) {
+func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (map[string]BazelTargets, CodegenMetrics, CodegenCompatLayer) {
 	buildFileToTargets := make(map[string]BazelTargets)
 	buildFileToAppend := make(map[string]bool)
 
@@ -222,6 +233,10 @@
 		RuleClassCount: make(map[string]int),
 	}
 
+	compatLayer := CodegenCompatLayer{
+		NameToLabelMap: make(map[string]string),
+	}
+
 	dirs := make(map[string]bool)
 
 	bpCtx := ctx.Context()
@@ -236,6 +251,7 @@
 			if b, ok := m.(android.Bazelable); ok && b.HasHandcraftedLabel() {
 				metrics.handCraftedTargetCount += 1
 				metrics.TotalModuleCount += 1
+				compatLayer.AddNameToLabelEntry(m.Name(), b.HandcraftedLabel())
 				pathToBuildFile := getBazelPackagePath(b)
 				// We are using the entire contents of handcrafted build file, so if multiple targets within
 				// a package have handcrafted targets, we only want to include the contents one time.
@@ -253,6 +269,7 @@
 			} else if btm, ok := m.(android.BazelTargetModule); ok {
 				t = generateBazelTarget(bpCtx, m, btm)
 				metrics.RuleClassCount[t.ruleClass] += 1
+				compatLayer.AddNameToLabelEntry(m.Name(), t.Label())
 			} else {
 				metrics.TotalModuleCount += 1
 				return
@@ -283,7 +300,7 @@
 		}
 	}
 
-	return buildFileToTargets, metrics
+	return buildFileToTargets, metrics, compatLayer
 }
 
 func getBazelPackagePath(b android.Bazelable) string {
@@ -324,6 +341,7 @@
 	targetName := targetNameForBp2Build(ctx, m)
 	return BazelTarget{
 		name:            targetName,
+		packageName:     ctx.ModuleDir(m),
 		ruleClass:       ruleClass,
 		bzlLoadLocation: bzlLoadLocation,
 		content: fmt.Sprintf(
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 33609af..0e52f2a 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -1398,14 +1398,14 @@
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
 			bp: `filegroup {
-    name: "fg_foo",
-    bazel_module: { label: "//other:fg_foo" },
-}
+		    name: "fg_foo",
+		    bazel_module: { label: "//other:fg_foo" },
+		}
 
-filegroup {
-    name: "foo",
-    bazel_module: { label: "//other:foo" },
-}`,
+		filegroup {
+		    name: "foo",
+		    bazel_module: { label: "//other:foo" },
+		}`,
 			expectedBazelTargets: []string{
 				`// BUILD file`,
 			},
@@ -1414,25 +1414,31 @@
 			},
 		},
 		{
-			description:                        "filegroup bazel_module.label and bp2build",
+			description:                        "filegroup bazel_module.label and bp2build in subdir",
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp: `filegroup {
-    name: "fg_foo",
-    bazel_module: {
-      label: "//other:fg_foo",
-      bp2build_available: true,
-    },
-}`,
+			dir:                                "other",
+			bp:                                 ``,
+			fs: map[string]string{
+				"other/Android.bp": `filegroup {
+				name: "fg_foo",
+				bazel_module: {
+					bp2build_available: true,
+				},
+			}
+			filegroup {
+				name: "fg_bar",
+				bazel_module: {
+					label: "//other:fg_bar"
+				},
+			}`,
+				"other/BUILD.bazel": `// definition for fg_bar`,
+			},
 			expectedBazelTargets: []string{
 				`filegroup(
     name = "fg_foo",
-)`,
-				`// BUILD file`,
-			},
-			fs: map[string]string{
-				"other/BUILD.bazel": `// BUILD file`,
+)`, `// definition for fg_bar`,
 			},
 		},
 		{
@@ -1441,18 +1447,18 @@
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
 			bp: `filegroup {
-    name: "fg_foo",
-    bazel_module: {
-      label: "//other:fg_foo",
-    },
-}
+		    name: "fg_foo",
+		    bazel_module: {
+		      label: "//other:fg_foo",
+		    },
+		}
 
-filegroup {
-    name: "fg_bar",
-    bazel_module: {
-      bp2build_available: true,
-    },
-}`,
+		filegroup {
+		    name: "fg_bar",
+		    bazel_module: {
+		      bp2build_available: true,
+		    },
+		}`,
 			expectedBazelTargets: []string{
 				`filegroup(
     name = "fg_bar",
diff --git a/bp2build/compatibility.go b/bp2build/compatibility.go
new file mode 100644
index 0000000..5baa524
--- /dev/null
+++ b/bp2build/compatibility.go
@@ -0,0 +1,31 @@
+package bp2build
+
+import (
+	"android/soong/bazel"
+	"fmt"
+)
+
+// Data from the code generation process that is used to improve compatibility
+// between build systems.
+type CodegenCompatLayer struct {
+	// A map from the original module name to the generated/handcrafted Bazel
+	// label for legacy build systems to be able to build a fully-qualified
+	// Bazel target from an unique module name.
+	NameToLabelMap map[string]string
+}
+
+// Log an entry of module name -> Bazel target label.
+func (compatLayer CodegenCompatLayer) AddNameToLabelEntry(name, label string) {
+	// The module name may be prefixed with bazel.BazelTargetModuleNamePrefix if
+	// generated from bp2build.
+	name = bazel.StripNamePrefix(name)
+	if existingLabel, ok := compatLayer.NameToLabelMap[name]; ok {
+		panic(fmt.Errorf(
+			"Module '%s' maps to more than one Bazel target label: %s, %s. "+
+				"This shouldn't happen. It probably indicates a bug with the bp2build internals.",
+			name,
+			existingLabel,
+			label))
+	}
+	compatLayer.NameToLabelMap[name] = label
+}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index bced4c1..75bc2b4 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -16,15 +16,31 @@
 	Contents string
 }
 
-func CreateSoongInjectionFiles() []BazelFile {
+func CreateSoongInjectionFiles(compatLayer CodegenCompatLayer) []BazelFile {
 	var files []BazelFile
 
-	files = append(files, newFile("cc_toolchain", "BUILD", "")) // Creates a //cc_toolchain package.
+	files = append(files, newFile("cc_toolchain", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package.
 	files = append(files, newFile("cc_toolchain", "constants.bzl", config.BazelCcToolchainVars()))
 
+	files = append(files, newFile("module_name_to_label", GeneratedBuildFileName, nameToLabelAliases(compatLayer.NameToLabelMap)))
+
 	return files
 }
 
+func nameToLabelAliases(nameToLabelMap map[string]string) string {
+	ret := make([]string, len(nameToLabelMap))
+
+	for k, v := range nameToLabelMap {
+		// v is the fully qualified label rooted at '//'
+		ret = append(ret, fmt.Sprintf(
+			`alias(
+    name = "%s",
+    actual = "@%s",
+)`, k, v))
+	}
+	return strings.Join(ret, "\n\n")
+}
+
 func CreateBazelFiles(
 	ruleShims map[string]RuleShim,
 	buildToTargets map[string]BazelTargets,
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index 0931ff7..56ea589 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -80,17 +80,21 @@
 }
 
 func TestCreateBazelFiles_Bp2Build_CreatesDefaultFiles(t *testing.T) {
-	files := CreateSoongInjectionFiles()
+	files := CreateSoongInjectionFiles(CodegenCompatLayer{})
 
 	expectedFilePaths := []bazelFilepath{
 		{
 			dir:      "cc_toolchain",
-			basename: "BUILD",
+			basename: GeneratedBuildFileName,
 		},
 		{
 			dir:      "cc_toolchain",
 			basename: "constants.bzl",
 		},
+		{
+			dir:      "module_name_to_label",
+			basename: GeneratedBuildFileName,
+		},
 	}
 
 	if len(files) != len(expectedFilePaths) {
@@ -104,7 +108,7 @@
 			t.Errorf("Did not find expected file %s/%s", actualFile.Dir, actualFile.Basename)
 		}
 
-		if expectedFile.basename != "BUILD" && actualFile.Contents == "" {
+		if expectedFile.basename != GeneratedBuildFileName && actualFile.Contents == "" {
 			t.Errorf("Contents of %s unexpected empty.", actualFile)
 		}
 	}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 861f7d2..f3cd7f0 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -213,6 +213,6 @@
 // Helper method for tests to easily access the targets in a dir.
 func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) BazelTargets {
 	// TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
-	buildFileToTargets, _ := GenerateBazelTargets(codegenCtx, false)
+	buildFileToTargets, _, _ := GenerateBazelTargets(codegenCtx, false)
 	return buildFileToTargets[dir]
 }