Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09f6b139 authored by Spandan Das's avatar Spandan Das Committed by Gerrit Code Review
Browse files

Merge changes I8ca452aa,I437fc890,If9446700 into main

* changes:
  Handle .proto files in different package for filegroups
  Handle .proto files that end up in a different package
  Allow creation of BazelTargets in a different directory
parents 541c1cab df3ec82b
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import (
	"android/soong/ui/metrics/bp2build_metrics_proto"

	"github.com/google/blueprint"
	"github.com/google/blueprint/proptools"
)

func init() {
@@ -141,8 +142,14 @@ func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) {
			attrs)
	} else {
		if fg.ShouldConvertToProtoLibrary(ctx) {
			pkgToSrcs := partitionSrcsByPackage(ctx.ModuleDir(), bazel.MakeLabelList(srcs.Value.Includes))
			if len(pkgToSrcs) > 1 {
				ctx.ModuleErrorf("TODO: Add bp2build support for multiple package .protosrcs in filegroup")
				return
			}
			pkg := SortedKeys(pkgToSrcs)[0]
			attrs := &ProtoAttrs{
				Srcs:                srcs,
				Srcs:                bazel.MakeLabelListAttribute(pkgToSrcs[pkg]),
				Strip_import_prefix: fg.properties.Path,
			}

@@ -151,13 +158,39 @@ func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) {
				// TODO(b/246997908): we can remove this tag if we could figure out a solution for this bug.
				"manual",
			}
			if pkg != ctx.ModuleDir() {
				// Since we are creating the proto_library in a subpackage, create an import_prefix relative to the current package
				if rel, err := filepath.Rel(ctx.ModuleDir(), pkg); err != nil {
					ctx.ModuleErrorf("Could not get relative path for %v %v", pkg, err)
				} else if rel != "." {
					attrs.Import_prefix = &rel
					// Strip the package prefix
					attrs.Strip_import_prefix = proptools.StringPtr("")
				}
			}

			ctx.CreateBazelTargetModule(
				bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
				CommonAttributes{
					Name: fg.Name() + convertedProtoLibrarySuffix,
					Name: fg.Name() + "_proto",
					Dir:  proptools.StringPtr(pkg),
					Tags: bazel.MakeStringListAttribute(tags),
				},
				attrs)

			// Create an alias in the current dir. The actual target might exist in a different package, but rdeps
			// can reliabily use this alias
			ctx.CreateBazelTargetModule(
				bazel.BazelTargetModuleProperties{Rule_class: "alias"},
				CommonAttributes{
					Name: fg.Name() + convertedProtoLibrarySuffix,
					// TODO(b/246997908): we can remove this tag if we could figure out a solution for this bug.
					Tags: bazel.MakeStringListAttribute(tags),
				},
				&bazelAliasAttributes{
					Actual: bazel.MakeLabelAttribute("//" + pkg + ":" + fg.Name() + "_proto"),
				},
			)
		}

		// TODO(b/242847534): Still convert to a filegroup because other unconverted
+5 −0
Original line number Diff line number Diff line
@@ -1021,6 +1021,11 @@ type CommonAttributes struct {
	Applicable_licenses bazel.LabelListAttribute

	Testonly *bool

	// Dir is neither a Soong nor Bazel target attribute
	// If set, the bazel target will be created in this directory
	// If unset, the bazel target will default to be created in the directory of the visited soong module
	Dir *string
}

// constraintAttributes represents Bazel attributes pertaining to build constraints,
+23 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package android
import (
	"android/soong/bazel"
	"android/soong/ui/metrics/bp2build_metrics_proto"
	"path/filepath"

	"github.com/google/blueprint"
)
@@ -757,6 +758,27 @@ func (t *topDownMutatorContext) CreateBazelTargetAliasInDir(
	mod.base().addBp2buildInfo(info)
}

// Returns the directory in which the bazel target will be generated
// If ca.Dir is not nil, use that
// Otherwise default to the directory of the soong module
func dirForBazelTargetGeneration(t *topDownMutatorContext, ca *CommonAttributes) string {
	dir := t.OtherModuleDir(t.Module())
	if ca.Dir != nil {
		dir = *ca.Dir
		// Restrict its use to dirs that contain an Android.bp file.
		// There are several places in bp2build where we use the existence of Android.bp/BUILD on the filesystem
		// to curate a compatible label for src files (e.g. headers for cc).
		// If we arbritrarily create BUILD files, then it might render those curated labels incompatible.
		if exists, _, _ := t.Config().fs.Exists(filepath.Join(dir, "Android.bp")); !exists {
			t.ModuleErrorf("Cannot use ca.Dir to create a BazelTarget in dir: %v since it does not contain an Android.bp file", dir)
		}

		// Set ca.Dir to nil so that it does not get emitted to the BUILD files
		ca.Dir = nil
	}
	return dir
}

func (t *topDownMutatorContext) CreateBazelConfigSetting(
	csa bazel.ConfigSettingAttributes,
	ca CommonAttributes,
@@ -851,7 +873,7 @@ func (t *topDownMutatorContext) createBazelTargetModule(
	constraintAttributes := commonAttrs.fillCommonBp2BuildModuleAttrs(t, enabledProperty)
	mod := t.Module()
	info := bp2buildInfo{
		Dir:             t.OtherModuleDir(mod),
		Dir:             dirForBazelTargetGeneration(t, &commonAttrs),
		BazelProps:      bazelProps,
		CommonAttrs:     commonAttrs,
		ConstraintAttrs: constraintAttributes,
+87 −38
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
package android

import (
	"path/filepath"
	"strings"

	"android/soong/bazel"
@@ -156,12 +157,12 @@ func ProtoRule(rule *RuleBuilder, protoFile Path, flags ProtoFlags, deps Paths,
// Bp2buildProtoInfo contains information necessary to pass on to language specific conversion.
type Bp2buildProtoInfo struct {
	Type       *string
	Name       string
	Proto_libs bazel.LabelList
}

type ProtoAttrs struct {
	Srcs                bazel.LabelListAttribute
	Import_prefix       *string
	Strip_import_prefix *string
	Deps                bazel.LabelListAttribute
}
@@ -172,6 +173,35 @@ var includeDirsToProtoDeps = map[string]string{
	"external/protobuf/src": "//external/protobuf:libprotobuf-proto",
}

// Partitions srcs by the pkg it is in
// srcs has been created using `TransformSubpackagePaths`
// This function uses existence of Android.bp/BUILD files to create a label that is compatible with the package structure of bp2build workspace
func partitionSrcsByPackage(currentDir string, srcs bazel.LabelList) map[string]bazel.LabelList {
	getPackageFromLabel := func(label string) string {
		// Remove any preceding //
		label = strings.TrimPrefix(label, "//")
		split := strings.Split(label, ":")
		if len(split) == 1 {
			// e.g. foo.proto
			return currentDir
		} else if split[0] == "" {
			// e.g. :foo.proto
			return currentDir
		} else {
			return split[0]
		}
	}

	pkgToSrcs := map[string]bazel.LabelList{}
	for _, src := range srcs.Includes {
		pkg := getPackageFromLabel(src.Label)
		list := pkgToSrcs[pkg]
		list.Add(&src)
		pkgToSrcs[pkg] = list
	}
	return pkgToSrcs
}

// Bp2buildProtoProperties converts proto properties, creating a proto_library and returning the
// information necessary for language-specific handling.
func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, m *ModuleBase, srcs bazel.LabelListAttribute) (Bp2buildProtoInfo, bool) {
@@ -197,13 +227,18 @@ func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, m *ModuleBase, srcs baz
		}
	}

	info.Name = m.Name() + "_proto"
	name := m.Name() + "_proto"

	depsFromFilegroup := protoLibraries

	if len(directProtoSrcs.Includes) > 0 {
		pkgToSrcs := partitionSrcsByPackage(ctx.ModuleDir(), directProtoSrcs)
		for _, pkg := range SortedStringKeys(pkgToSrcs) {
			srcs := pkgToSrcs[pkg]
			attrs := ProtoAttrs{
			Srcs: bazel.MakeLabelListAttribute(directProtoSrcs),
				Srcs: bazel.MakeLabelListAttribute(srcs),
			}
		attrs.Deps.Append(bazel.MakeLabelListAttribute(protoLibraries))
			attrs.Deps.Append(bazel.MakeLabelListAttribute(depsFromFilegroup))

			for axis, configToProps := range m.GetArchVariantProperties(ctx, &ProtoProperties{}) {
				for _, rawProps := range configToProps {
@@ -236,16 +271,30 @@ func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, m *ModuleBase, srcs baz

			tags := ApexAvailableTagsWithoutTestApexes(ctx.(TopDownMutatorContext), ctx.Module())

			// Since we are creating the proto_library in a subpackage, create an import_prefix relative to the current package
			if rel, err := filepath.Rel(ctx.ModuleDir(), pkg); err != nil {
				ctx.ModuleErrorf("Could not get relative path for %v %v", pkg, err)
			} else if rel != "." {
				attrs.Import_prefix = &rel
			}

			ctx.CreateBazelTargetModule(
				bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
			CommonAttributes{Name: info.Name, Tags: tags},
				CommonAttributes{Name: name, Dir: proptools.StringPtr(pkg), Tags: tags},
				&attrs,
			)

			l := ""
			if pkg == ctx.ModuleDir() { // same package that the original module lives in
				l = ":" + name
			} else {
				l = "//" + pkg + ":" + name
			}
			protoLibraries.Add(&bazel.Label{
			Label: ":" + info.Name,
				Label: l,
			})
		}
	}

	info.Proto_libs = protoLibraries

+43 −0
Original line number Diff line number Diff line
@@ -1949,3 +1949,46 @@ func TestPrettyPrintSelectMapEqualValues(t *testing.T) {
	actual, _ := prettyPrintAttribute(lla, 0)
	android.AssertStringEquals(t, "Print the common value if all keys in an axis have the same value", `[":libfoo.impl"]`, actual)
}

// If CommonAttributes.Dir is set, the bazel target should be created in that dir
func TestCreateBazelTargetInDifferentDir(t *testing.T) {
	t.Parallel()
	bp := `
	custom {
		name: "foo",
		dir: "subdir",
	}
	`
	registerCustomModule := func(ctx android.RegistrationContext) {
		ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
	}
	// Check that foo is not created in root dir
	RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
		Description: "foo is not created in root dir because it sets dir explicitly",
		Blueprint:   bp,
		Filesystem: map[string]string{
			"subdir/Android.bp": "",
		},
		ExpectedBazelTargets: []string{},
	})
	// Check that foo is created in `subdir`
	RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
		Description: "foo is created in `subdir` because it sets dir explicitly",
		Blueprint:   bp,
		Filesystem: map[string]string{
			"subdir/Android.bp": "",
		},
		Dir: "subdir",
		ExpectedBazelTargets: []string{
			MakeBazelTarget("custom", "foo", AttrNameToString{}),
		},
	})
	// Check that we cannot create target in different dir if it is does not an Android.bp
	RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
		Description: "foo cannot be created in `subdir` because it does not contain an Android.bp file",
		Blueprint:   bp,
		Dir:         "subdir",
		ExpectedErr: fmt.Errorf("Cannot use ca.Dir to create a BazelTarget in dir: subdir since it does not contain an Android.bp file"),
	})

}
Loading