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]
}