Expand handling of unconverted deps in bp2build
Support three options for converting modules with unconverted dependencies 1. (default) Warn when converting a module if it has unconverted deps. 2. Error when encountering a module with unconverted deps. (not hooked up yet) Test: build/bazel/ci/bp2build.sh Test: build/bazel/ci/mixed_libc.sh Test: BP2BUILD_ERROR_UNCONVERTED=1 build/bazel/ci/bp2build.sh with unconverted deps -- get appropriate error Bug: 181155349 Change-Id: Ifaabf0cd2e43e963366dc137159c705294165c3d
This commit is contained in:
@@ -61,8 +61,8 @@ type Bazelable interface {
|
|||||||
HandcraftedLabel() string
|
HandcraftedLabel() string
|
||||||
GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string
|
GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string
|
||||||
ConvertWithBp2build(ctx BazelConversionPathContext) bool
|
ConvertWithBp2build(ctx BazelConversionPathContext) bool
|
||||||
|
convertWithBp2build(ctx BazelConversionPathContext, module blueprint.Module) bool
|
||||||
GetBazelBuildFileContents(c Config, path, name string) (string, error)
|
GetBazelBuildFileContents(c Config, path, name string) (string, error)
|
||||||
ConvertedToBazel(ctx BazelConversionPathContext) bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BazelModule is a lightweight wrapper interface around Module for Bazel-convertible modules.
|
// BazelModule is a lightweight wrapper interface around Module for Bazel-convertible modules.
|
||||||
@@ -311,9 +311,10 @@ func (b *BazelModuleBase) MixedBuildsEnabled(ctx BazelConversionPathContext) boo
|
|||||||
if !ctx.Config().BazelContext.BazelEnabled() {
|
if !ctx.Config().BazelContext.BazelEnabled() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if len(b.GetBazelLabel(ctx, ctx.Module())) == 0 {
|
if !convertedToBazel(ctx, ctx.Module()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if GenerateCcLibraryStaticOnly(ctx) {
|
if GenerateCcLibraryStaticOnly(ctx) {
|
||||||
// Don't use partially-converted cc_library targets in mixed builds,
|
// Don't use partially-converted cc_library targets in mixed builds,
|
||||||
// since mixed builds would generally rely on both static and shared
|
// since mixed builds would generally rely on both static and shared
|
||||||
@@ -323,20 +324,33 @@ func (b *BazelModuleBase) MixedBuildsEnabled(ctx BazelConversionPathContext) boo
|
|||||||
return !mixedBuildsDisabled[ctx.Module().Name()]
|
return !mixedBuildsDisabled[ctx.Module().Name()]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel.
|
||||||
|
func convertedToBazel(ctx BazelConversionPathContext, module blueprint.Module) bool {
|
||||||
|
b, ok := module.(Bazelable)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return b.convertWithBp2build(ctx, module) || b.HasHandcraftedLabel()
|
||||||
|
}
|
||||||
|
|
||||||
// ConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build.
|
// ConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build.
|
||||||
func (b *BazelModuleBase) ConvertWithBp2build(ctx BazelConversionPathContext) bool {
|
func (b *BazelModuleBase) ConvertWithBp2build(ctx BazelConversionPathContext) bool {
|
||||||
if bp2buildModuleDoNotConvert[ctx.Module().Name()] {
|
return b.convertWithBp2build(ctx, ctx.Module())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BazelModuleBase) convertWithBp2build(ctx BazelConversionPathContext, module blueprint.Module) bool {
|
||||||
|
if bp2buildModuleDoNotConvert[module.Name()] {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the module type of this module has a bp2build converter. This
|
// Ensure that the module type of this module has a bp2build converter. This
|
||||||
// prevents mixed builds from using auto-converted modules just by matching
|
// prevents mixed builds from using auto-converted modules just by matching
|
||||||
// the package dir; it also has to have a bp2build mutator as well.
|
// the package dir; it also has to have a bp2build mutator as well.
|
||||||
if ctx.Config().bp2buildModuleTypeConfig[ctx.ModuleType()] == false {
|
if ctx.Config().bp2buildModuleTypeConfig[ctx.OtherModuleType(module)] == false {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
packagePath := ctx.ModuleDir()
|
packagePath := ctx.OtherModuleDir(module)
|
||||||
config := ctx.Config().bp2buildPackageConfig
|
config := ctx.Config().bp2buildPackageConfig
|
||||||
|
|
||||||
// This is a tristate value: true, false, or unset.
|
// This is a tristate value: true, false, or unset.
|
||||||
@@ -407,9 +421,3 @@ func (b *BazelModuleBase) GetBazelBuildFileContents(c Config, path, name string)
|
|||||||
}
|
}
|
||||||
return string(data[:]), nil
|
return string(data[:]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertedToBazel returns whether this module has been converted to Bazel, whether automatically
|
|
||||||
// or manually
|
|
||||||
func (b *BazelModuleBase) ConvertedToBazel(ctx BazelConversionPathContext) bool {
|
|
||||||
return b.ConvertWithBp2build(ctx) || b.HasHandcraftedLabel()
|
|
||||||
}
|
|
||||||
|
@@ -75,9 +75,10 @@ type BazelConversionPathContext interface {
|
|||||||
GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
|
GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
|
||||||
ModuleFromName(name string) (blueprint.Module, bool)
|
ModuleFromName(name string) (blueprint.Module, bool)
|
||||||
Module() Module
|
Module() Module
|
||||||
ModuleType() string
|
OtherModuleType(m blueprint.Module) string
|
||||||
OtherModuleName(m blueprint.Module) string
|
OtherModuleName(m blueprint.Module) string
|
||||||
OtherModuleDir(m blueprint.Module) string
|
OtherModuleDir(m blueprint.Module) string
|
||||||
|
AddUnconvertedBp2buildDep(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BazelLabelForModuleDeps expects a list of reference to other modules, ("<module>"
|
// BazelLabelForModuleDeps expects a list of reference to other modules, ("<module>"
|
||||||
@@ -345,6 +346,9 @@ func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string, isWhol
|
|||||||
if m == nil {
|
if m == nil {
|
||||||
panic(fmt.Errorf("No module named %q found, but was a direct dep of %q", dep, ctx.Module().Name()))
|
panic(fmt.Errorf("No module named %q found, but was a direct dep of %q", dep, ctx.Module().Name()))
|
||||||
}
|
}
|
||||||
|
if !convertedToBazel(ctx, m) {
|
||||||
|
ctx.AddUnconvertedBp2buildDep(dep)
|
||||||
|
}
|
||||||
otherLabel := bazelModuleLabel(ctx, m, tag)
|
otherLabel := bazelModuleLabel(ctx, m, tag)
|
||||||
label := bazelModuleLabel(ctx, ctx.Module(), "")
|
label := bazelModuleLabel(ctx, ctx.Module(), "")
|
||||||
if isWholeLibs {
|
if isWholeLibs {
|
||||||
@@ -363,11 +367,10 @@ func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string, isWhol
|
|||||||
|
|
||||||
func bazelModuleLabel(ctx BazelConversionPathContext, module blueprint.Module, tag string) string {
|
func bazelModuleLabel(ctx BazelConversionPathContext, module blueprint.Module, tag string) string {
|
||||||
// TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
|
// TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
|
||||||
b, ok := module.(Bazelable)
|
if !convertedToBazel(ctx, module) {
|
||||||
// TODO(b/181155349): perhaps return an error here if the module can't be/isn't being converted
|
|
||||||
if !ok || !b.ConvertedToBazel(ctx) {
|
|
||||||
return bp2buildModuleLabel(ctx, module)
|
return bp2buildModuleLabel(ctx, module)
|
||||||
}
|
}
|
||||||
|
b, _ := module.(Bazelable)
|
||||||
return b.GetBazelLabel(ctx, module)
|
return b.GetBazelLabel(ctx, module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -316,6 +316,9 @@ type BaseModuleContext interface {
|
|||||||
|
|
||||||
AddMissingDependencies(missingDeps []string)
|
AddMissingDependencies(missingDeps []string)
|
||||||
|
|
||||||
|
// AddUnconvertedBp2buildDep stores module name of a direct dependency that was not converted via bp2build
|
||||||
|
AddUnconvertedBp2buildDep(dep string)
|
||||||
|
|
||||||
Target() Target
|
Target() Target
|
||||||
TargetPrimary() bool
|
TargetPrimary() bool
|
||||||
|
|
||||||
@@ -496,6 +499,7 @@ type Module interface {
|
|||||||
IsConvertedByBp2build() bool
|
IsConvertedByBp2build() bool
|
||||||
// Bp2buildTargets returns the target(s) generated for Bazel via bp2build for this module
|
// Bp2buildTargets returns the target(s) generated for Bazel via bp2build for this module
|
||||||
Bp2buildTargets() []bp2buildInfo
|
Bp2buildTargets() []bp2buildInfo
|
||||||
|
GetUnconvertedBp2buildDeps() []string
|
||||||
|
|
||||||
BuildParamsForTests() []BuildParams
|
BuildParamsForTests() []BuildParams
|
||||||
RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
|
RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
|
||||||
@@ -833,6 +837,10 @@ type commonProperties struct {
|
|||||||
// supported as Soong handles some things within a single target that we may choose to split into
|
// supported as Soong handles some things within a single target that we may choose to split into
|
||||||
// multiple targets, e.g. renderscript, protos, yacc within a cc module.
|
// multiple targets, e.g. renderscript, protos, yacc within a cc module.
|
||||||
Bp2buildInfo []bp2buildInfo `blueprint:"mutated"`
|
Bp2buildInfo []bp2buildInfo `blueprint:"mutated"`
|
||||||
|
|
||||||
|
// UnconvertedBp2buildDep stores the module names of direct dependency that were not converted to
|
||||||
|
// Bazel
|
||||||
|
UnconvertedBp2buildDeps []string `blueprint:"mutated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type distProperties struct {
|
type distProperties struct {
|
||||||
@@ -1212,6 +1220,18 @@ func (m *ModuleBase) Bp2buildTargets() []bp2buildInfo {
|
|||||||
return m.commonProperties.Bp2buildInfo
|
return m.commonProperties.Bp2buildInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddUnconvertedBp2buildDep stores module name of a dependency that was not converted to Bazel.
|
||||||
|
func (b *baseModuleContext) AddUnconvertedBp2buildDep(dep string) {
|
||||||
|
unconvertedDeps := &b.Module().base().commonProperties.UnconvertedBp2buildDeps
|
||||||
|
*unconvertedDeps = append(*unconvertedDeps, dep)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUnconvertedBp2buildDeps returns the list of module names of this module's direct dependencies that
|
||||||
|
// were not converted to Bazel.
|
||||||
|
func (m *ModuleBase) GetUnconvertedBp2buildDeps() []string {
|
||||||
|
return m.commonProperties.UnconvertedBp2buildDeps
|
||||||
|
}
|
||||||
|
|
||||||
func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
|
func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
|
||||||
(*d)["Android"] = map[string]interface{}{}
|
(*d)["Android"] = map[string]interface{}{}
|
||||||
}
|
}
|
||||||
|
@@ -532,7 +532,6 @@ func (t *topDownMutatorContext) CreateBazelTargetModule(
|
|||||||
BazelProps: bazelProps,
|
BazelProps: bazelProps,
|
||||||
Attrs: attrs,
|
Attrs: attrs,
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Module().base().addBp2buildInfo(info)
|
t.Module().base().addBp2buildInfo(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,6 +19,7 @@ import (
|
|||||||
"android/soong/bazel"
|
"android/soong/bazel"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Codegen is the backend of bp2build. The code generator is responsible for
|
// Codegen is the backend of bp2build. The code generator is responsible for
|
||||||
@@ -29,14 +30,22 @@ func Codegen(ctx *CodegenContext) CodegenMetrics {
|
|||||||
bp2buildDir := android.PathForOutput(ctx, "bp2build")
|
bp2buildDir := android.PathForOutput(ctx, "bp2build")
|
||||||
android.RemoveAllOutputDir(bp2buildDir)
|
android.RemoveAllOutputDir(bp2buildDir)
|
||||||
|
|
||||||
buildToTargets, metrics, compatLayer := GenerateBazelTargets(ctx, true)
|
res, errs := GenerateBazelTargets(ctx, true)
|
||||||
bp2buildFiles := CreateBazelFiles(nil, buildToTargets, ctx.mode)
|
if len(errs) > 0 {
|
||||||
|
errMsgs := make([]string, len(errs))
|
||||||
|
for i, err := range errs {
|
||||||
|
errMsgs[i] = fmt.Sprintf("%q", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("ERROR: Encountered %d error(s): \nERROR: %s", len(errs), strings.Join(errMsgs, "\n"))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
bp2buildFiles := CreateBazelFiles(nil, res.buildFileToTargets, 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(compatLayer))
|
writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles(res.compatLayer))
|
||||||
|
|
||||||
return metrics
|
return res.metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the output directory and create it if it doesn't exist.
|
// Get the output directory and create it if it doesn't exist.
|
||||||
|
@@ -153,10 +153,11 @@ type bpToBuildContext interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CodegenContext struct {
|
type CodegenContext struct {
|
||||||
config android.Config
|
config android.Config
|
||||||
context android.Context
|
context android.Context
|
||||||
mode CodegenMode
|
mode CodegenMode
|
||||||
additionalDeps []string
|
additionalDeps []string
|
||||||
|
unconvertedDepMode unconvertedDepsMode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CodegenContext) Mode() CodegenMode {
|
func (c *CodegenContext) Mode() CodegenMode {
|
||||||
@@ -181,6 +182,16 @@ const (
|
|||||||
QueryView
|
QueryView
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type unconvertedDepsMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Include a warning in conversion metrics about converted modules with unconverted direct deps
|
||||||
|
warnUnconvertedDeps unconvertedDepsMode = iota
|
||||||
|
// Error and fail conversion if encountering a module with unconverted direct deps
|
||||||
|
// Enabled by setting environment variable `BP2BUILD_ERROR_UNCONVERTED`
|
||||||
|
errorModulesUnconvertedDeps
|
||||||
|
)
|
||||||
|
|
||||||
func (mode CodegenMode) String() string {
|
func (mode CodegenMode) String() string {
|
||||||
switch mode {
|
switch mode {
|
||||||
case Bp2Build:
|
case Bp2Build:
|
||||||
@@ -211,10 +222,15 @@ func (ctx *CodegenContext) Context() android.Context { return ctx.context }
|
|||||||
// NewCodegenContext creates a wrapper context that conforms to PathContext for
|
// NewCodegenContext creates a wrapper context that conforms to PathContext for
|
||||||
// writing BUILD files in the output directory.
|
// writing BUILD files in the output directory.
|
||||||
func NewCodegenContext(config android.Config, context android.Context, mode CodegenMode) *CodegenContext {
|
func NewCodegenContext(config android.Config, context android.Context, mode CodegenMode) *CodegenContext {
|
||||||
|
var unconvertedDeps unconvertedDepsMode
|
||||||
|
if config.IsEnvTrue("BP2BUILD_ERROR_UNCONVERTED") {
|
||||||
|
unconvertedDeps = errorModulesUnconvertedDeps
|
||||||
|
}
|
||||||
return &CodegenContext{
|
return &CodegenContext{
|
||||||
context: context,
|
context: context,
|
||||||
config: config,
|
config: config,
|
||||||
mode: mode,
|
mode: mode,
|
||||||
|
unconvertedDepMode: unconvertedDeps,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +246,17 @@ func propsToAttributes(props map[string]string) string {
|
|||||||
return attributes
|
return attributes
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (map[string]BazelTargets, CodegenMetrics, CodegenCompatLayer) {
|
type conversionResults struct {
|
||||||
|
buildFileToTargets map[string]BazelTargets
|
||||||
|
metrics CodegenMetrics
|
||||||
|
compatLayer CodegenCompatLayer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r conversionResults) BuildDirToTargets() map[string]BazelTargets {
|
||||||
|
return r.buildFileToTargets
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (conversionResults, []error) {
|
||||||
buildFileToTargets := make(map[string]BazelTargets)
|
buildFileToTargets := make(map[string]BazelTargets)
|
||||||
buildFileToAppend := make(map[string]bool)
|
buildFileToAppend := make(map[string]bool)
|
||||||
|
|
||||||
@@ -245,6 +271,8 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (map[str
|
|||||||
|
|
||||||
dirs := make(map[string]bool)
|
dirs := make(map[string]bool)
|
||||||
|
|
||||||
|
var errs []error
|
||||||
|
|
||||||
bpCtx := ctx.Context()
|
bpCtx := ctx.Context()
|
||||||
bpCtx.VisitAllModules(func(m blueprint.Module) {
|
bpCtx.VisitAllModules(func(m blueprint.Module) {
|
||||||
dir := bpCtx.ModuleDir(m)
|
dir := bpCtx.ModuleDir(m)
|
||||||
@@ -266,13 +294,24 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (map[str
|
|||||||
}
|
}
|
||||||
t, err := getHandcraftedBuildContent(ctx, b, pathToBuildFile)
|
t, err := getHandcraftedBuildContent(ctx, b, pathToBuildFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("Error converting %s: %s", bpCtx.ModuleName(m), err))
|
errs = append(errs, fmt.Errorf("Error converting %s: %s", bpCtx.ModuleName(m), err))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
targets = append(targets, t)
|
targets = append(targets, t)
|
||||||
// TODO(b/181575318): currently we append the whole BUILD file, let's change that to do
|
// TODO(b/181575318): currently we append the whole BUILD file, let's change that to do
|
||||||
// something more targeted based on the rule type and target
|
// something more targeted based on the rule type and target
|
||||||
buildFileToAppend[pathToBuildFile] = true
|
buildFileToAppend[pathToBuildFile] = true
|
||||||
} else if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
|
} else if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
|
||||||
|
if unconvertedDeps := aModule.GetUnconvertedBp2buildDeps(); len(unconvertedDeps) > 0 {
|
||||||
|
msg := fmt.Sprintf("%q depends on unconverted modules: %s", m.Name(), strings.Join(unconvertedDeps, ", "))
|
||||||
|
if ctx.unconvertedDepMode == warnUnconvertedDeps {
|
||||||
|
metrics.moduleWithUnconvertedDepsMsgs = append(metrics.moduleWithUnconvertedDepsMsgs, msg)
|
||||||
|
} else if ctx.unconvertedDepMode == errorModulesUnconvertedDeps {
|
||||||
|
metrics.TotalModuleCount += 1
|
||||||
|
errs = append(errs, fmt.Errorf(msg))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
targets = generateBazelTargets(bpCtx, aModule)
|
targets = generateBazelTargets(bpCtx, aModule)
|
||||||
for _, t := range targets {
|
for _, t := range targets {
|
||||||
if t.name == m.Name() {
|
if t.name == m.Name() {
|
||||||
@@ -295,11 +334,17 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (map[str
|
|||||||
t := generateSoongModuleTarget(bpCtx, m)
|
t := generateSoongModuleTarget(bpCtx, m)
|
||||||
targets = append(targets, t)
|
targets = append(targets, t)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("Unknown code-generation mode: %s", ctx.Mode()))
|
errs = append(errs, fmt.Errorf("Unknown code-generation mode: %s", ctx.Mode()))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
buildFileToTargets[dir] = append(buildFileToTargets[dir], targets...)
|
buildFileToTargets[dir] = append(buildFileToTargets[dir], targets...)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return conversionResults{}, errs
|
||||||
|
}
|
||||||
|
|
||||||
if generateFilegroups {
|
if generateFilegroups {
|
||||||
// Add a filegroup target that exposes all sources in the subtree of this package
|
// Add a filegroup target that exposes all sources in the subtree of this package
|
||||||
// NOTE: This also means we generate a BUILD file for every Android.bp file (as long as it has at least one module)
|
// NOTE: This also means we generate a BUILD file for every Android.bp file (as long as it has at least one module)
|
||||||
@@ -312,7 +357,11 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (map[str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return buildFileToTargets, metrics, compatLayer
|
return conversionResults{
|
||||||
|
buildFileToTargets: buildFileToTargets,
|
||||||
|
metrics: metrics,
|
||||||
|
compatLayer: compatLayer,
|
||||||
|
}, errs
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBazelPackagePath(b android.Bazelable) string {
|
func getBazelPackagePath(b android.Bazelable) string {
|
||||||
|
@@ -16,6 +16,7 @@ package bp2build
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -199,7 +200,8 @@ func TestGenerateSoongModuleTargets(t *testing.T) {
|
|||||||
android.FailIfErrored(t, errs)
|
android.FailIfErrored(t, errs)
|
||||||
|
|
||||||
codegenCtx := NewCodegenContext(config, *ctx.Context, QueryView)
|
codegenCtx := NewCodegenContext(config, *ctx.Context, QueryView)
|
||||||
bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
|
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
|
||||||
|
android.FailIfErrored(t, err)
|
||||||
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
|
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
|
||||||
t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
|
t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
|
||||||
}
|
}
|
||||||
@@ -341,7 +343,8 @@ custom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
||||||
bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
|
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
|
||||||
|
android.FailIfErrored(t, err)
|
||||||
|
|
||||||
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
|
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
|
||||||
t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount)
|
t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount)
|
||||||
@@ -502,7 +505,8 @@ load("//build/bazel/rules:rules.bzl", "my_library")`,
|
|||||||
android.FailIfErrored(t, errs)
|
android.FailIfErrored(t, errs)
|
||||||
|
|
||||||
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
||||||
bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
|
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
|
||||||
|
android.FailIfErrored(t, err)
|
||||||
if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount {
|
if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount {
|
||||||
t.Fatalf("Expected %d bazel target, got %d", testCase.expectedBazelTargetCount, actualCount)
|
t.Fatalf("Expected %d bazel target, got %d", testCase.expectedBazelTargetCount, actualCount)
|
||||||
}
|
}
|
||||||
@@ -679,59 +683,38 @@ func TestModuleTypeBp2Build(t *testing.T) {
|
|||||||
"other/Android.bp": `filegroup {
|
"other/Android.bp": `filegroup {
|
||||||
name: "foo",
|
name: "foo",
|
||||||
srcs: ["a", "b"],
|
srcs: ["a", "b"],
|
||||||
|
bazel_module: { bp2build_available: true },
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "depends_on_other_unconverted_module_error",
|
||||||
|
moduleTypeUnderTest: "filegroup",
|
||||||
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
||||||
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
||||||
|
unconvertedDepsMode: errorModulesUnconvertedDeps,
|
||||||
|
blueprint: `filegroup {
|
||||||
|
name: "foobar",
|
||||||
|
srcs: [
|
||||||
|
":foo",
|
||||||
|
"c",
|
||||||
|
],
|
||||||
|
bazel_module: { bp2build_available: true },
|
||||||
|
}`,
|
||||||
|
expectedErr: fmt.Errorf(`"foobar" depends on unconverted modules: foo`),
|
||||||
|
filesystem: map[string]string{
|
||||||
|
"other/Android.bp": `filegroup {
|
||||||
|
name: "foo",
|
||||||
|
srcs: ["a", "b"],
|
||||||
}`,
|
}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
dir := "."
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
fs := make(map[string][]byte)
|
t.Run(testCase.description, func(t *testing.T) {
|
||||||
toParse := []string{
|
runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, testCase)
|
||||||
"Android.bp",
|
})
|
||||||
}
|
|
||||||
for f, content := range testCase.filesystem {
|
|
||||||
if strings.HasSuffix(f, "Android.bp") {
|
|
||||||
toParse = append(toParse, f)
|
|
||||||
}
|
|
||||||
fs[f] = []byte(content)
|
|
||||||
}
|
|
||||||
config := android.TestConfig(buildDir, nil, testCase.blueprint, fs)
|
|
||||||
ctx := android.NewTestContext(config)
|
|
||||||
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
|
|
||||||
ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
|
|
||||||
ctx.RegisterForBazelConversion()
|
|
||||||
|
|
||||||
_, errs := ctx.ParseFileList(dir, toParse)
|
|
||||||
if errored(t, testCase, errs) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
_, errs = ctx.ResolveDependencies(config)
|
|
||||||
if errored(t, testCase, errs) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
checkDir := dir
|
|
||||||
if testCase.dir != "" {
|
|
||||||
checkDir = testCase.dir
|
|
||||||
}
|
|
||||||
|
|
||||||
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
|
||||||
bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
|
|
||||||
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
|
|
||||||
t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
|
|
||||||
} else {
|
|
||||||
for i, target := range bazelTargets {
|
|
||||||
if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
|
|
||||||
t.Errorf(
|
|
||||||
"%s: Expected generated Bazel target to be '%s', got '%s'",
|
|
||||||
testCase.description,
|
|
||||||
w,
|
|
||||||
g,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,7 +792,8 @@ func TestAllowlistingBp2buildTargetsExplicitly(t *testing.T) {
|
|||||||
android.FailIfErrored(t, errs)
|
android.FailIfErrored(t, errs)
|
||||||
|
|
||||||
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
||||||
bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
|
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
|
||||||
|
android.FailIfErrored(t, err)
|
||||||
if actualCount := len(bazelTargets); actualCount != testCase.expectedCount {
|
if actualCount := len(bazelTargets); actualCount != testCase.expectedCount {
|
||||||
t.Fatalf("%s: Expected %d bazel target, got %d", testCase.description, testCase.expectedCount, actualCount)
|
t.Fatalf("%s: Expected %d bazel target, got %d", testCase.description, testCase.expectedCount, actualCount)
|
||||||
}
|
}
|
||||||
@@ -921,7 +905,8 @@ filegroup { name: "opt-out-h", bazel_module: { bp2build_available: false } }
|
|||||||
|
|
||||||
// For each directory, test that the expected number of generated targets is correct.
|
// For each directory, test that the expected number of generated targets is correct.
|
||||||
for dir, expectedCount := range testCase.expectedCount {
|
for dir, expectedCount := range testCase.expectedCount {
|
||||||
bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
|
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
|
||||||
|
android.FailIfErrored(t, err)
|
||||||
if actualCount := len(bazelTargets); actualCount != expectedCount {
|
if actualCount := len(bazelTargets); actualCount != expectedCount {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
"%s: Expected %d bazel target for %s package, got %d",
|
"%s: Expected %d bazel target for %s package, got %d",
|
||||||
@@ -1064,7 +1049,9 @@ func TestCombineBuildFilesBp2buildTargets(t *testing.T) {
|
|||||||
if testCase.dir != "" {
|
if testCase.dir != "" {
|
||||||
checkDir = testCase.dir
|
checkDir = testCase.dir
|
||||||
}
|
}
|
||||||
bazelTargets := generateBazelTargetsForDir(NewCodegenContext(config, *ctx.Context, Bp2Build), checkDir)
|
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
||||||
|
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, checkDir)
|
||||||
|
android.FailIfErrored(t, err)
|
||||||
bazelTargets.sort()
|
bazelTargets.sort()
|
||||||
actualCount := len(bazelTargets)
|
actualCount := len(bazelTargets)
|
||||||
expectedCount := len(testCase.expectedBazelTargets)
|
expectedCount := len(testCase.expectedBazelTargets)
|
||||||
@@ -1185,7 +1172,9 @@ func TestGlobExcludeSrcs(t *testing.T) {
|
|||||||
if testCase.dir != "" {
|
if testCase.dir != "" {
|
||||||
checkDir = testCase.dir
|
checkDir = testCase.dir
|
||||||
}
|
}
|
||||||
bazelTargets := generateBazelTargetsForDir(NewCodegenContext(config, *ctx.Context, Bp2Build), checkDir)
|
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
||||||
|
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, checkDir)
|
||||||
|
android.FailIfErrored(t, err)
|
||||||
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
|
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
|
||||||
t.Errorf("%s: Expected %d bazel target, got %d\n%s", testCase.description, expectedCount, actualCount, bazelTargets)
|
t.Errorf("%s: Expected %d bazel target, got %d\n%s", testCase.description, expectedCount, actualCount, bazelTargets)
|
||||||
} else {
|
} else {
|
||||||
|
@@ -267,7 +267,8 @@ genrule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
||||||
bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
|
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, checkDir)
|
||||||
|
android.FailIfErrored(t, err)
|
||||||
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
|
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
|
||||||
t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
|
t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
|
||||||
} else {
|
} else {
|
||||||
@@ -461,7 +462,8 @@ genrule {
|
|||||||
android.FailIfErrored(t, errs)
|
android.FailIfErrored(t, errs)
|
||||||
|
|
||||||
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
||||||
bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
|
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
|
||||||
|
android.FailIfErrored(t, err)
|
||||||
if actualCount := len(bazelTargets); actualCount != 1 {
|
if actualCount := len(bazelTargets); actualCount != 1 {
|
||||||
t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount)
|
t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount)
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ package bp2build
|
|||||||
import (
|
import (
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Simple metrics struct to collect information about a Blueprint to BUILD
|
// Simple metrics struct to collect information about a Blueprint to BUILD
|
||||||
@@ -16,6 +17,8 @@ type CodegenMetrics struct {
|
|||||||
|
|
||||||
// Total number of handcrafted targets
|
// Total number of handcrafted targets
|
||||||
handCraftedTargetCount int
|
handCraftedTargetCount int
|
||||||
|
|
||||||
|
moduleWithUnconvertedDepsMsgs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the codegen metrics to stdout.
|
// Print the codegen metrics to stdout.
|
||||||
@@ -27,8 +30,10 @@ func (metrics CodegenMetrics) Print() {
|
|||||||
generatedTargetCount += count
|
generatedTargetCount += count
|
||||||
}
|
}
|
||||||
fmt.Printf(
|
fmt.Printf(
|
||||||
"[bp2build] Generated %d total BUILD targets and included %d handcrafted BUILD targets from %d Android.bp modules.\n",
|
"[bp2build] Generated %d total BUILD targets and included %d handcrafted BUILD targets from %d Android.bp modules.\n With %d modules with unconverted deps \n\t%s",
|
||||||
generatedTargetCount,
|
generatedTargetCount,
|
||||||
metrics.handCraftedTargetCount,
|
metrics.handCraftedTargetCount,
|
||||||
metrics.TotalModuleCount)
|
metrics.TotalModuleCount,
|
||||||
|
len(metrics.moduleWithUnconvertedDepsMsgs),
|
||||||
|
strings.Join(metrics.moduleWithUnconvertedDepsMsgs, "\n\t"))
|
||||||
}
|
}
|
||||||
|
@@ -39,9 +39,8 @@ var (
|
|||||||
func checkError(t *testing.T, errs []error, expectedErr error) bool {
|
func checkError(t *testing.T, errs []error, expectedErr error) bool {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
// expectedErr is not nil, find it in the list of errors
|
|
||||||
if len(errs) != 1 {
|
if len(errs) != 1 {
|
||||||
t.Errorf("Expected only 1 error, got %d: %q", len(errs), errs)
|
return false
|
||||||
}
|
}
|
||||||
if errs[0].Error() == expectedErr.Error() {
|
if errs[0].Error() == expectedErr.Error() {
|
||||||
return true
|
return true
|
||||||
@@ -83,6 +82,7 @@ type bp2buildTestCase struct {
|
|||||||
filesystem map[string]string
|
filesystem map[string]string
|
||||||
dir string
|
dir string
|
||||||
expectedErr error
|
expectedErr error
|
||||||
|
unconvertedDepsMode unconvertedDepsMode
|
||||||
}
|
}
|
||||||
|
|
||||||
func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
|
func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
|
||||||
@@ -126,7 +126,13 @@ func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.Regi
|
|||||||
checkDir = tc.dir
|
checkDir = tc.dir
|
||||||
}
|
}
|
||||||
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
||||||
bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
|
codegenCtx.unconvertedDepMode = tc.unconvertedDepsMode
|
||||||
|
bazelTargets, errs := generateBazelTargetsForDir(codegenCtx, checkDir)
|
||||||
|
if tc.expectedErr != nil && checkError(t, errs, tc.expectedErr) {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
android.FailIfErrored(t, errs)
|
||||||
|
}
|
||||||
if actualCount, expectedCount := len(bazelTargets), len(tc.expectedBazelTargets); actualCount != expectedCount {
|
if actualCount, expectedCount := len(bazelTargets), len(tc.expectedBazelTargets); actualCount != expectedCount {
|
||||||
t.Errorf("%s: Expected %d bazel target, got %d; %v",
|
t.Errorf("%s: Expected %d bazel target, got %d; %v",
|
||||||
tc.description, expectedCount, actualCount, bazelTargets)
|
tc.description, expectedCount, actualCount, bazelTargets)
|
||||||
@@ -316,10 +322,10 @@ 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, []error) {
|
||||||
// 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)
|
res, err := GenerateBazelTargets(codegenCtx, false)
|
||||||
return buildFileToTargets[dir]
|
return res.buildFileToTargets[dir], err
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) {
|
func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) {
|
||||||
|
@@ -27,12 +27,12 @@ func createBazelQueryView(ctx *bp2build.CodegenContext, bazelQueryViewDir string
|
|||||||
os.RemoveAll(bazelQueryViewDir)
|
os.RemoveAll(bazelQueryViewDir)
|
||||||
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
|
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
|
||||||
|
|
||||||
// Ignore metrics reporting and compat layers for queryview, since queryview
|
res, err := bp2build.GenerateBazelTargets(ctx, true)
|
||||||
// is already a full-repo conversion and can use data from bazel query
|
if err != nil {
|
||||||
// directly.
|
panic(err)
|
||||||
buildToTargets, _, _ := bp2build.GenerateBazelTargets(ctx, true)
|
}
|
||||||
|
|
||||||
filesToWrite := bp2build.CreateBazelFiles(ruleShims, buildToTargets, bp2build.QueryView)
|
filesToWrite := bp2build.CreateBazelFiles(ruleShims, res.BuildDirToTargets(), bp2build.QueryView)
|
||||||
for _, f := range filesToWrite {
|
for _, f := range filesToWrite {
|
||||||
if err := writeReadOnlyFile(bazelQueryViewDir, f); err != nil {
|
if err := writeReadOnlyFile(bazelQueryViewDir, f); err != nil {
|
||||||
return err
|
return err
|
||||||
|
Reference in New Issue
Block a user