bp2build: introduce CodegenMode.

The CodegenMode enum helps to differentiate between bp2build and queryview modes of generating BUILD files from the Soong module graph.

bp2build is used for generating BUILD files from an unconfigured Soong module graph for Soong->Bazel conversion, whereas QueryView is a front-end for querying the existing Soong configured module graph with Bazel query.

Test: go test

Test: TH
Change-Id: I5709f591f1ae08b2770adf272d8ce60c9ee1f46a
This commit is contained in:
Jingwen Chen 2021-01-24 22:55:54 -05:00
parent f1b0e82547
commit 33832f96e0
8 changed files with 43 additions and 20 deletions

View file

@ -28,9 +28,9 @@ func Codegen(ctx CodegenContext) {
ruleShims := CreateRuleShims(android.ModuleTypeFactories())
buildToTargets := GenerateSoongModuleTargets(ctx.Context(), true)
buildToTargets := GenerateSoongModuleTargets(ctx.Context(), ctx.mode)
filesToWrite := CreateBazelFiles(ruleShims, buildToTargets, true)
filesToWrite := CreateBazelFiles(ruleShims, buildToTargets, ctx.mode)
for _, f := range filesToWrite {
if err := writeFile(outputDir, ctx, f); err != nil {
fmt.Errorf("Failed to write %q (dir %q) due to %q", f.Basename, f.Dir, err)

View file

@ -46,18 +46,38 @@ type bpToBuildContext interface {
type CodegenContext struct {
config android.Config
context android.Context
mode CodegenMode
}
// CodegenMode is an enum to differentiate code-generation modes.
type CodegenMode int
const (
// Bp2Build: generate BUILD files with targets buildable by Bazel directly.
//
// This mode is used for the Soong->Bazel build definition conversion.
Bp2Build CodegenMode = iota
// QueryView: generate BUILD files with targets representing fully mutated
// Soong modules, representing the fully configured Soong module graph with
// variants and dependency endges.
//
// This mode is used for discovering and introspecting the existing Soong
// module graph.
QueryView
)
func (ctx CodegenContext) AddNinjaFileDeps(...string) {}
func (ctx CodegenContext) Config() android.Config { return ctx.config }
func (ctx CodegenContext) Context() android.Context { return ctx.context }
// NewCodegenContext creates a wrapper context that conforms to PathContext for
// writing BUILD files in the output directory.
func NewCodegenContext(config android.Config, context android.Context) CodegenContext {
func NewCodegenContext(config android.Config, context android.Context, mode CodegenMode) CodegenContext {
return CodegenContext{
context: context,
config: config,
mode: mode,
}
}
@ -73,19 +93,22 @@ func propsToAttributes(props map[string]string) string {
return attributes
}
func GenerateSoongModuleTargets(ctx bpToBuildContext, bp2buildEnabled bool) map[string][]BazelTarget {
func GenerateSoongModuleTargets(ctx bpToBuildContext, codegenMode CodegenMode) map[string][]BazelTarget {
buildFileToTargets := make(map[string][]BazelTarget)
ctx.VisitAllModules(func(m blueprint.Module) {
dir := ctx.ModuleDir(m)
var t BazelTarget
if bp2buildEnabled {
switch codegenMode {
case Bp2Build:
if _, ok := m.(android.BazelTargetModule); !ok {
return
}
t = generateBazelTarget(ctx, m)
} else {
case QueryView:
t = generateSoongModuleTarget(ctx, m)
default:
panic(fmt.Errorf("Unknown code-generation mode: %s", codegenMode))
}
buildFileToTargets[ctx.ModuleDir(m)] = append(buildFileToTargets[dir], t)

View file

@ -201,7 +201,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) {
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, false)[dir]
bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, QueryView)[dir]
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
}
@ -252,7 +252,7 @@ func TestGenerateBazelTargetModules(t *testing.T) {
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, true)[dir]
bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, Bp2Build)[dir]
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
}
@ -365,7 +365,7 @@ func TestModuleTypeBp2Build(t *testing.T) {
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, true)[dir]
bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, Bp2Build)[dir]
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
}

View file

@ -172,7 +172,7 @@ func TestGenerateSoongModuleBzl(t *testing.T) {
content: "irrelevant",
},
}
files := CreateBazelFiles(ruleShims, make(map[string][]BazelTarget), false)
files := CreateBazelFiles(ruleShims, make(map[string][]BazelTarget), QueryView)
var actualSoongModuleBzl BazelFile
for _, f := range files {

View file

@ -18,7 +18,7 @@ type BazelFile struct {
func CreateBazelFiles(
ruleShims map[string]RuleShim,
buildToTargets map[string][]BazelTarget,
bp2buildEnabled bool) []BazelFile {
mode CodegenMode) []BazelFile {
files := make([]BazelFile, 0, len(ruleShims)+len(buildToTargets)+numAdditionalFiles)
// Write top level files: WORKSPACE and BUILD. These files are empty.
@ -28,7 +28,7 @@ func CreateBazelFiles(
files = append(files, newFile(bazelRulesSubDir, "BUILD", ""))
if !bp2buildEnabled {
if mode == QueryView {
// These files are only used for queryview.
files = append(files, newFile(bazelRulesSubDir, "providers.bzl", providersBzl))
@ -38,16 +38,16 @@ func CreateBazelFiles(
files = append(files, newFile(bazelRulesSubDir, "soong_module.bzl", generateSoongModuleBzl(ruleShims)))
}
files = append(files, createBuildFiles(buildToTargets, bp2buildEnabled)...)
files = append(files, createBuildFiles(buildToTargets, mode)...)
return files
}
func createBuildFiles(buildToTargets map[string][]BazelTarget, bp2buildEnabled bool) []BazelFile {
func createBuildFiles(buildToTargets map[string][]BazelTarget, mode CodegenMode) []BazelFile {
files := make([]BazelFile, 0, len(buildToTargets))
for _, dir := range android.SortedStringKeys(buildToTargets) {
content := soongModuleLoad
if bp2buildEnabled {
if mode == Bp2Build {
// No need to load soong_module for bp2build BUILD files.
content = ""
}

View file

@ -55,7 +55,7 @@ func sortFiles(files []BazelFile) {
}
func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) {
files := CreateBazelFiles(map[string]RuleShim{}, map[string][]BazelTarget{}, false)
files := CreateBazelFiles(map[string]RuleShim{}, map[string][]BazelTarget{}, QueryView)
expectedFilePaths := []filepath{
{
dir: "",
@ -85,7 +85,7 @@ func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) {
}
func TestCreateBazelFiles_Bp2Build_AddsTopLevelFiles(t *testing.T) {
files := CreateBazelFiles(map[string]RuleShim{}, map[string][]BazelTarget{}, true)
files := CreateBazelFiles(map[string]RuleShim{}, map[string][]BazelTarget{}, Bp2Build)
expectedFilePaths := []filepath{
{
dir: "",

View file

@ -170,7 +170,7 @@ func runBp2Build(configuration android.Config, extraNinjaDeps []string) {
bp2buildCtx.SetNameInterface(newNameResolver(configuration))
bootstrap.Main(bp2buildCtx.Context, configuration, extraNinjaDeps...)
codegenContext := bp2build.NewCodegenContext(configuration, *bp2buildCtx)
codegenContext := bp2build.NewCodegenContext(configuration, *bp2buildCtx, bp2build.Bp2Build)
bp2build.Codegen(codegenContext)
}

View file

@ -24,9 +24,9 @@ import (
func createBazelQueryView(ctx *android.Context, bazelQueryViewDir string) error {
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
buildToTargets := bp2build.GenerateSoongModuleTargets(*ctx, false)
buildToTargets := bp2build.GenerateSoongModuleTargets(*ctx, bp2build.QueryView)
filesToWrite := bp2build.CreateBazelFiles(ruleShims, buildToTargets, false)
filesToWrite := bp2build.CreateBazelFiles(ruleShims, buildToTargets, bp2build.QueryView)
for _, f := range filesToWrite {
if err := writeReadOnlyFile(bazelQueryViewDir, f); err != nil {
return err