Merge "Direct Bazel builds from m."

This commit is contained in:
Treehugger Robot
2021-06-21 08:16:21 +00:00
committed by Gerrit Code Review
10 changed files with 126 additions and 44 deletions

View File

@@ -19,6 +19,7 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"sort" "sort"
"strings"
) )
// BazelTargetModuleProperties contain properties and metadata used for // BazelTargetModuleProperties contain properties and metadata used for
@@ -33,6 +34,10 @@ type BazelTargetModuleProperties struct {
const BazelTargetModuleNamePrefix = "__bp2build__" const BazelTargetModuleNamePrefix = "__bp2build__"
func StripNamePrefix(moduleName string) string {
return strings.TrimPrefix(moduleName, BazelTargetModuleNamePrefix)
}
var productVariableSubstitutionPattern = regexp.MustCompile("%(d|s)") var productVariableSubstitutionPattern = regexp.MustCompile("%(d|s)")
// Label is used to represent a Bazel compatible Label. Also stores the original // Label is used to represent a Bazel compatible Label. Also stores the original

View File

@@ -11,6 +11,7 @@ bootstrap_go_package {
"build_conversion.go", "build_conversion.go",
"bzl_conversion.go", "bzl_conversion.go",
"configurability.go", "configurability.go",
"compatibility.go",
"constants.go", "constants.go",
"conversion.go", "conversion.go",
"metrics.go", "metrics.go",

View File

@@ -29,12 +29,12 @@ func Codegen(ctx *CodegenContext) CodegenMetrics {
bp2buildDir := android.PathForOutput(ctx, "bp2build") bp2buildDir := android.PathForOutput(ctx, "bp2build")
android.RemoveAllOutputDir(bp2buildDir) android.RemoveAllOutputDir(bp2buildDir)
buildToTargets, metrics := GenerateBazelTargets(ctx, true) buildToTargets, metrics, compatLayer := GenerateBazelTargets(ctx, true)
bp2buildFiles := CreateBazelFiles(nil, buildToTargets, ctx.mode) bp2buildFiles := CreateBazelFiles(nil, buildToTargets, ctx.mode)
writeFiles(ctx, bp2buildDir, bp2buildFiles) writeFiles(ctx, bp2buildDir, bp2buildFiles)
soongInjectionDir := android.PathForOutput(ctx, bazel.SoongInjectionDirName) soongInjectionDir := android.PathForOutput(ctx, bazel.SoongInjectionDirName)
writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles()) writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles(compatLayer))
return metrics return metrics
} }

View File

@@ -32,6 +32,7 @@ type BazelAttributes struct {
type BazelTarget struct { type BazelTarget struct {
name string name string
packageName string
content string content string
ruleClass string ruleClass string
bzlLoadLocation string bzlLoadLocation string
@@ -44,6 +45,16 @@ func (t BazelTarget) IsLoadedFromStarlark() bool {
return t.bzlLoadLocation != "" 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. // BazelTargets is a typedef for a slice of BazelTarget objects.
type BazelTargets []BazelTarget type BazelTargets []BazelTarget
@@ -213,7 +224,7 @@ func propsToAttributes(props map[string]string) string {
return attributes 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) buildFileToTargets := make(map[string]BazelTargets)
buildFileToAppend := make(map[string]bool) buildFileToAppend := make(map[string]bool)
@@ -222,6 +233,10 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (map[str
RuleClassCount: make(map[string]int), RuleClassCount: make(map[string]int),
} }
compatLayer := CodegenCompatLayer{
NameToLabelMap: make(map[string]string),
}
dirs := make(map[string]bool) dirs := make(map[string]bool)
bpCtx := ctx.Context() bpCtx := ctx.Context()
@@ -236,6 +251,7 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (map[str
if b, ok := m.(android.Bazelable); ok && b.HasHandcraftedLabel() { if b, ok := m.(android.Bazelable); ok && b.HasHandcraftedLabel() {
metrics.handCraftedTargetCount += 1 metrics.handCraftedTargetCount += 1
metrics.TotalModuleCount += 1 metrics.TotalModuleCount += 1
compatLayer.AddNameToLabelEntry(m.Name(), b.HandcraftedLabel())
pathToBuildFile := getBazelPackagePath(b) pathToBuildFile := getBazelPackagePath(b)
// We are using the entire contents of handcrafted build file, so if multiple targets within // 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. // a package have handcrafted targets, we only want to include the contents one time.
@@ -253,6 +269,7 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (map[str
} else if btm, ok := m.(android.BazelTargetModule); ok { } else if btm, ok := m.(android.BazelTargetModule); ok {
t = generateBazelTarget(bpCtx, m, btm) t = generateBazelTarget(bpCtx, m, btm)
metrics.RuleClassCount[t.ruleClass] += 1 metrics.RuleClassCount[t.ruleClass] += 1
compatLayer.AddNameToLabelEntry(m.Name(), t.Label())
} else { } else {
metrics.TotalModuleCount += 1 metrics.TotalModuleCount += 1
return return
@@ -283,7 +300,7 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (map[str
} }
} }
return buildFileToTargets, metrics return buildFileToTargets, metrics, compatLayer
} }
func getBazelPackagePath(b android.Bazelable) string { func getBazelPackagePath(b android.Bazelable) string {
@@ -324,6 +341,7 @@ func generateBazelTarget(ctx bpToBuildContext, m blueprint.Module, btm android.B
targetName := targetNameForBp2Build(ctx, m) targetName := targetNameForBp2Build(ctx, m)
return BazelTarget{ return BazelTarget{
name: targetName, name: targetName,
packageName: ctx.ModuleDir(m),
ruleClass: ruleClass, ruleClass: ruleClass,
bzlLoadLocation: bzlLoadLocation, bzlLoadLocation: bzlLoadLocation,
content: fmt.Sprintf( content: fmt.Sprintf(

View File

@@ -1414,25 +1414,31 @@ filegroup {
}, },
}, },
{ {
description: "filegroup bazel_module.label and bp2build", description: "filegroup bazel_module.label and bp2build in subdir",
moduleTypeUnderTest: "filegroup", moduleTypeUnderTest: "filegroup",
moduleTypeUnderTestFactory: android.FileGroupFactory, moduleTypeUnderTestFactory: android.FileGroupFactory,
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build, moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
bp: `filegroup { dir: "other",
bp: ``,
fs: map[string]string{
"other/Android.bp": `filegroup {
name: "fg_foo", name: "fg_foo",
bazel_module: { bazel_module: {
label: "//other:fg_foo",
bp2build_available: true, bp2build_available: true,
}, },
}
filegroup {
name: "fg_bar",
bazel_module: {
label: "//other:fg_bar"
},
}`, }`,
"other/BUILD.bazel": `// definition for fg_bar`,
},
expectedBazelTargets: []string{ expectedBazelTargets: []string{
`filegroup( `filegroup(
name = "fg_foo", name = "fg_foo",
)`, )`, `// definition for fg_bar`,
`// BUILD file`,
},
fs: map[string]string{
"other/BUILD.bazel": `// BUILD file`,
}, },
}, },
{ {

31
bp2build/compatibility.go Normal file
View File

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

View File

@@ -16,15 +16,31 @@ type BazelFile struct {
Contents string Contents string
} }
func CreateSoongInjectionFiles() []BazelFile { func CreateSoongInjectionFiles(compatLayer CodegenCompatLayer) []BazelFile {
var files []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("cc_toolchain", "constants.bzl", config.BazelCcToolchainVars()))
files = append(files, newFile("module_name_to_label", GeneratedBuildFileName, nameToLabelAliases(compatLayer.NameToLabelMap)))
return files 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( func CreateBazelFiles(
ruleShims map[string]RuleShim, ruleShims map[string]RuleShim,
buildToTargets map[string]BazelTargets, buildToTargets map[string]BazelTargets,

View File

@@ -80,17 +80,21 @@ func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) {
} }
func TestCreateBazelFiles_Bp2Build_CreatesDefaultFiles(t *testing.T) { func TestCreateBazelFiles_Bp2Build_CreatesDefaultFiles(t *testing.T) {
files := CreateSoongInjectionFiles() files := CreateSoongInjectionFiles(CodegenCompatLayer{})
expectedFilePaths := []bazelFilepath{ expectedFilePaths := []bazelFilepath{
{ {
dir: "cc_toolchain", dir: "cc_toolchain",
basename: "BUILD", basename: GeneratedBuildFileName,
}, },
{ {
dir: "cc_toolchain", dir: "cc_toolchain",
basename: "constants.bzl", basename: "constants.bzl",
}, },
{
dir: "module_name_to_label",
basename: GeneratedBuildFileName,
},
} }
if len(files) != len(expectedFilePaths) { if len(files) != len(expectedFilePaths) {
@@ -104,7 +108,7 @@ func TestCreateBazelFiles_Bp2Build_CreatesDefaultFiles(t *testing.T) {
t.Errorf("Did not find expected file %s/%s", actualFile.Dir, actualFile.Basename) 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) t.Errorf("Contents of %s unexpected empty.", actualFile)
} }
} }

View File

@@ -213,6 +213,6 @@ func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
// Helper method for tests to easily access the targets in a dir. // Helper method for tests to easily access the targets in a dir.
func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) BazelTargets { func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) BazelTargets {
// TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely // TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
buildFileToTargets, _ := GenerateBazelTargets(codegenCtx, false) buildFileToTargets, _, _ := GenerateBazelTargets(codegenCtx, false)
return buildFileToTargets[dir] return buildFileToTargets[dir]
} }

View File

@@ -25,9 +25,10 @@ import (
func createBazelQueryView(ctx *bp2build.CodegenContext, bazelQueryViewDir string) error { func createBazelQueryView(ctx *bp2build.CodegenContext, bazelQueryViewDir string) error {
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories()) ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
// Ignore metrics reporting for queryview, since queryview is already a full-repo // Ignore metrics reporting and compat layers for queryview, since queryview
// conversion and can use data from bazel query directly. // is already a full-repo conversion and can use data from bazel query
buildToTargets, _ := bp2build.GenerateBazelTargets(ctx, true) // directly.
buildToTargets, _, _ := bp2build.GenerateBazelTargets(ctx, true)
filesToWrite := bp2build.CreateBazelFiles(ruleShims, buildToTargets, bp2build.QueryView) filesToWrite := bp2build.CreateBazelFiles(ruleShims, buildToTargets, bp2build.QueryView)
for _, f := range filesToWrite { for _, f := range filesToWrite {