A performance improvement for bp2build as Blueprint/Soong no longer have the overhead of additional modules. The creation of these modules results in: * traversal of additional modules for each subsequent mutator * synchronization over a go channel to collect newly created modules: https://cs.android.com/android/platform/superproject/+/master:build/blueprint/context.go;l=2594,2600;drc=1602226f23181b8c3fbfcaf3358f0297e839d7d3 We avoid both of these by storing the information directly in the underlying module. Also as a fringe benefit, removes some necessary boilerplate for conversion. For benchmarks, reduces runtime ~1% for 1% converted, ~24% for 100% converted. See more: go/benchmarks-for-https:-r.android.com-1792714 Test: ran benchmarks/tests in bp2build Test: build/bazel/ci/bp2build.sh Change-Id: Ie9273b8cbab5bc6edac1728067ce184382feb211
218 lines
5.6 KiB
Go
218 lines
5.6 KiB
Go
package bp2build
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"android/soong/android"
|
|
"android/soong/bazel"
|
|
)
|
|
|
|
var (
|
|
// A default configuration for tests to not have to specify bp2build_available on top level targets.
|
|
bp2buildConfig = android.Bp2BuildConfig{
|
|
android.BP2BUILD_TOPLEVEL: android.Bp2BuildDefaultTrueRecursively,
|
|
}
|
|
|
|
buildDir string
|
|
)
|
|
|
|
type nestedProps struct {
|
|
Nested_prop string
|
|
}
|
|
|
|
type customProps struct {
|
|
Bool_prop bool
|
|
Bool_ptr_prop *bool
|
|
// Ensure that properties tagged `blueprint:mutated` are omitted
|
|
Int_prop int `blueprint:"mutated"`
|
|
Int64_ptr_prop *int64
|
|
String_prop string
|
|
String_ptr_prop *string
|
|
String_list_prop []string
|
|
|
|
Nested_props nestedProps
|
|
Nested_props_ptr *nestedProps
|
|
|
|
Arch_paths []string `android:"path,arch_variant"`
|
|
Arch_paths_exclude []string `android:"path,arch_variant"`
|
|
}
|
|
|
|
type customModule struct {
|
|
android.ModuleBase
|
|
android.BazelModuleBase
|
|
|
|
props customProps
|
|
}
|
|
|
|
func errored(t *testing.T, desc string, errs []error) bool {
|
|
t.Helper()
|
|
if len(errs) > 0 {
|
|
for _, err := range errs {
|
|
t.Errorf("%s: %s", desc, err)
|
|
}
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// OutputFiles is needed because some instances of this module use dist with a
|
|
// tag property which requires the module implements OutputFileProducer.
|
|
func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
|
|
return android.PathsForTesting("path" + tag), nil
|
|
}
|
|
|
|
func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
// nothing for now.
|
|
}
|
|
|
|
func customModuleFactoryBase() android.Module {
|
|
module := &customModule{}
|
|
module.AddProperties(&module.props)
|
|
android.InitBazelModule(module)
|
|
return module
|
|
}
|
|
|
|
func customModuleFactory() android.Module {
|
|
m := customModuleFactoryBase()
|
|
android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
|
|
return m
|
|
}
|
|
|
|
type testProps struct {
|
|
Test_prop struct {
|
|
Test_string_prop string
|
|
}
|
|
}
|
|
|
|
type customTestModule struct {
|
|
android.ModuleBase
|
|
|
|
props customProps
|
|
test_props testProps
|
|
}
|
|
|
|
func (m *customTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
// nothing for now.
|
|
}
|
|
|
|
func customTestModuleFactoryBase() android.Module {
|
|
m := &customTestModule{}
|
|
m.AddProperties(&m.props)
|
|
m.AddProperties(&m.test_props)
|
|
return m
|
|
}
|
|
|
|
func customTestModuleFactory() android.Module {
|
|
m := customTestModuleFactoryBase()
|
|
android.InitAndroidModule(m)
|
|
return m
|
|
}
|
|
|
|
type customDefaultsModule struct {
|
|
android.ModuleBase
|
|
android.DefaultsModuleBase
|
|
}
|
|
|
|
func customDefaultsModuleFactoryBase() android.DefaultsModule {
|
|
module := &customDefaultsModule{}
|
|
module.AddProperties(&customProps{})
|
|
return module
|
|
}
|
|
|
|
func customDefaultsModuleFactoryBasic() android.Module {
|
|
return customDefaultsModuleFactoryBase()
|
|
}
|
|
|
|
func customDefaultsModuleFactory() android.Module {
|
|
m := customDefaultsModuleFactoryBase()
|
|
android.InitDefaultsModule(m)
|
|
return m
|
|
}
|
|
|
|
type customBazelModuleAttributes struct {
|
|
String_prop string
|
|
String_list_prop []string
|
|
Arch_paths bazel.LabelListAttribute
|
|
}
|
|
|
|
type customBazelModule struct {
|
|
android.BazelTargetModuleBase
|
|
customBazelModuleAttributes
|
|
}
|
|
|
|
func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
|
|
if m, ok := ctx.Module().(*customModule); ok {
|
|
if !m.ConvertWithBp2build(ctx) {
|
|
return
|
|
}
|
|
|
|
paths := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.props.Arch_paths, m.props.Arch_paths_exclude))
|
|
|
|
for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
|
|
for config, props := range configToProps {
|
|
if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
|
|
paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrcExcludes(ctx, archProps.Arch_paths, archProps.Arch_paths_exclude))
|
|
}
|
|
}
|
|
}
|
|
|
|
paths.ResolveExcludes()
|
|
|
|
attrs := &customBazelModuleAttributes{
|
|
String_prop: m.props.String_prop,
|
|
String_list_prop: m.props.String_list_prop,
|
|
Arch_paths: paths,
|
|
}
|
|
|
|
props := bazel.BazelTargetModuleProperties{
|
|
Rule_class: "custom",
|
|
}
|
|
|
|
ctx.CreateBazelTargetModule(m.Name(), props, attrs)
|
|
}
|
|
}
|
|
|
|
// A bp2build mutator that uses load statements and creates a 1:M mapping from
|
|
// module to target.
|
|
func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
|
|
if m, ok := ctx.Module().(*customModule); ok {
|
|
if !m.ConvertWithBp2build(ctx) {
|
|
return
|
|
}
|
|
|
|
baseName := m.Name()
|
|
attrs := &customBazelModuleAttributes{}
|
|
|
|
myLibraryProps := bazel.BazelTargetModuleProperties{
|
|
Rule_class: "my_library",
|
|
Bzl_load_location: "//build/bazel/rules:rules.bzl",
|
|
}
|
|
ctx.CreateBazelTargetModule(baseName, myLibraryProps, attrs)
|
|
|
|
protoLibraryProps := bazel.BazelTargetModuleProperties{
|
|
Rule_class: "proto_library",
|
|
Bzl_load_location: "//build/bazel/rules:proto.bzl",
|
|
}
|
|
ctx.CreateBazelTargetModule(baseName+"_proto_library_deps", protoLibraryProps, attrs)
|
|
|
|
myProtoLibraryProps := bazel.BazelTargetModuleProperties{
|
|
Rule_class: "my_proto_library",
|
|
Bzl_load_location: "//build/bazel/rules:proto.bzl",
|
|
}
|
|
ctx.CreateBazelTargetModule(baseName+"_my_proto_library_deps", myProtoLibraryProps, attrs)
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
return buildFileToTargets[dir]
|
|
}
|
|
|
|
func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) {
|
|
ctx.RegisterModuleType("custom", customModuleFactory)
|
|
ctx.RegisterBp2BuildMutator("custom", customBp2BuildMutator)
|
|
ctx.RegisterForBazelConversion()
|
|
}
|