convert java proto libraries with bp2build
Allow java_libraries that depend on protobufs to be converted with bp2build. Bug: 215230097 Test: build/bazel/ci/bp2build.sh Change-Id: I3ce52389e7e4e82755605ee277c1e527a6aebc6b
This commit is contained in:
parent
5ee913f527
commit
c768102bce
7 changed files with 229 additions and 31 deletions
|
@ -18,6 +18,8 @@ import (
|
|||
"strings"
|
||||
|
||||
"android/soong/bazel"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -28,6 +30,11 @@ var PrepareForTestWithFilegroup = FixtureRegisterWithContext(func(ctx Registrati
|
|||
ctx.RegisterModuleType("filegroup", FileGroupFactory)
|
||||
})
|
||||
|
||||
// IsFilegroup checks that a module is a filegroup type
|
||||
func IsFilegroup(ctx bazel.OtherModuleContext, m blueprint.Module) bool {
|
||||
return ctx.OtherModuleType(m) == "filegroup"
|
||||
}
|
||||
|
||||
// https://docs.bazel.build/versions/master/be/general.html#filegroup
|
||||
type bazelFilegroupAttributes struct {
|
||||
Srcs bazel.LabelListAttribute
|
||||
|
|
|
@ -16,6 +16,7 @@ package android
|
|||
|
||||
import (
|
||||
"android/soong/bazel"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
|
@ -26,6 +27,14 @@ const (
|
|||
canonicalPathFromRootDefault = true
|
||||
)
|
||||
|
||||
var (
|
||||
// ignoring case, checks for proto or protos as an independent word in the name, whether at the
|
||||
// beginning, end, or middle. e.g. "proto.foo", "bar-protos", "baz_proto_srcs" would all match
|
||||
filegroupLikelyProtoPattern = regexp.MustCompile("(?i)(^|[^a-z])proto(s)?([^a-z]|$)")
|
||||
|
||||
ProtoSrcLabelPartition = bazel.LabelPartition{Extensions: []string{".proto"}, LabelMapper: isProtoFilegroup}
|
||||
)
|
||||
|
||||
// TODO(ccross): protos are often used to communicate between multiple modules. If the only
|
||||
// way to convert a proto to source is to reference it as a source file, and external modules cannot
|
||||
// reference source files in other modules, then every module that owns a proto file will need to
|
||||
|
@ -165,12 +174,11 @@ type protoAttrs struct {
|
|||
|
||||
// Bp2buildProtoProperties converts proto properties, creating a proto_library and returning the
|
||||
// information necessary for language-specific handling.
|
||||
func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, module Module, srcs bazel.LabelListAttribute) (Bp2buildProtoInfo, bool) {
|
||||
func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, m *ModuleBase, srcs bazel.LabelListAttribute) (Bp2buildProtoInfo, bool) {
|
||||
var info Bp2buildProtoInfo
|
||||
if srcs.IsEmpty() {
|
||||
return info, false
|
||||
}
|
||||
m := module.base()
|
||||
|
||||
info.Name = m.Name() + "_proto"
|
||||
attrs := protoAttrs{
|
||||
|
@ -205,3 +213,13 @@ func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, module Module, srcs baz
|
|||
|
||||
return info, true
|
||||
}
|
||||
|
||||
func isProtoFilegroup(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
|
||||
m, exists := ctx.ModuleFromName(label.OriginalModuleName)
|
||||
labelStr := label.Label
|
||||
if !exists || !IsFilegroup(ctx, m) {
|
||||
return labelStr, false
|
||||
}
|
||||
likelyProtos := filegroupLikelyProtoPattern.MatchString(label.OriginalModuleName)
|
||||
return labelStr, likelyProtos
|
||||
}
|
||||
|
|
124
bp2build/java_proto_conversion_test.go
Normal file
124
bp2build/java_proto_conversion_test.go
Normal file
|
@ -0,0 +1,124 @@
|
|||
// Copyright 2021 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package bp2build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/java"
|
||||
)
|
||||
|
||||
func runJavaProtoTestCase(t *testing.T, tc bp2buildTestCase) {
|
||||
t.Helper()
|
||||
(&tc).moduleTypeUnderTest = "java_library_static"
|
||||
(&tc).moduleTypeUnderTestFactory = java.LibraryFactory
|
||||
runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
|
||||
}
|
||||
|
||||
func TestJavaProto(t *testing.T) {
|
||||
testCases := []struct {
|
||||
protoType string
|
||||
javaLibraryType string
|
||||
javaLibraryNameExtension string
|
||||
}{
|
||||
{
|
||||
protoType: "nano",
|
||||
javaLibraryType: "java_nano_proto_library",
|
||||
javaLibraryNameExtension: "java_proto_nano",
|
||||
},
|
||||
{
|
||||
protoType: "micro",
|
||||
javaLibraryType: "java_micro_proto_library",
|
||||
javaLibraryNameExtension: "java_proto_micro",
|
||||
},
|
||||
{
|
||||
protoType: "lite",
|
||||
javaLibraryType: "java_lite_proto_library",
|
||||
javaLibraryNameExtension: "java_proto_lite",
|
||||
},
|
||||
{
|
||||
protoType: "stream",
|
||||
javaLibraryType: "java_stream_proto_library",
|
||||
javaLibraryNameExtension: "java_proto_stream",
|
||||
},
|
||||
{
|
||||
protoType: "full",
|
||||
javaLibraryType: "java_proto_library",
|
||||
javaLibraryNameExtension: "java_proto",
|
||||
},
|
||||
}
|
||||
|
||||
bp := `java_library_static {
|
||||
name: "java-protos",
|
||||
proto: {
|
||||
type: "%s",
|
||||
},
|
||||
srcs: ["a.proto"],
|
||||
}`
|
||||
|
||||
protoLibrary := makeBazelTarget("proto_library", "java-protos_proto", attrNameToString{
|
||||
"srcs": `["a.proto"]`,
|
||||
"strip_import_prefix": `""`,
|
||||
})
|
||||
|
||||
for _, tc := range testCases {
|
||||
javaLibraryName := fmt.Sprintf("java-protos_%s", tc.javaLibraryNameExtension)
|
||||
|
||||
runJavaProtoTestCase(t, bp2buildTestCase{
|
||||
description: fmt.Sprintf("java_proto %s", tc.protoType),
|
||||
blueprint: fmt.Sprintf(bp, tc.protoType),
|
||||
expectedBazelTargets: []string{
|
||||
protoLibrary,
|
||||
makeBazelTarget(
|
||||
tc.javaLibraryType,
|
||||
javaLibraryName,
|
||||
attrNameToString{
|
||||
"deps": `[":java-protos_proto"]`,
|
||||
}),
|
||||
makeBazelTarget("java_library", "java-protos", attrNameToString{
|
||||
"deps": fmt.Sprintf(`[":%s"]`, javaLibraryName),
|
||||
}),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestJavaProtoDefault(t *testing.T) {
|
||||
runJavaProtoTestCase(t, bp2buildTestCase{
|
||||
description: "java_proto",
|
||||
blueprint: `java_library_static {
|
||||
name: "java-protos",
|
||||
srcs: ["a.proto"],
|
||||
}
|
||||
`,
|
||||
expectedBazelTargets: []string{
|
||||
makeBazelTarget("proto_library", "java-protos_proto", attrNameToString{
|
||||
"srcs": `["a.proto"]`,
|
||||
"strip_import_prefix": `""`,
|
||||
}),
|
||||
makeBazelTarget(
|
||||
"java_lite_proto_library",
|
||||
"java-protos_java_proto_lite",
|
||||
attrNameToString{
|
||||
"deps": `[":java-protos_proto"]`,
|
||||
}),
|
||||
makeBazelTarget("java_library", "java-protos", attrNameToString{
|
||||
"deps": `[":java-protos_java_proto_lite"]`,
|
||||
}),
|
||||
},
|
||||
})
|
||||
}
|
|
@ -16,7 +16,6 @@ package cc
|
|||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"android/soong/android"
|
||||
|
@ -34,12 +33,6 @@ const (
|
|||
protoSrcPartition = "proto"
|
||||
)
|
||||
|
||||
var (
|
||||
// ignoring case, checks for proto or protos as an independent word in the name, whether at the
|
||||
// beginning, end, or middle. e.g. "proto.foo", "bar-protos", "baz_proto_srcs" would all match
|
||||
filegroupLikelyProtoPattern = regexp.MustCompile("(?i)(^|[^a-z])proto(s)?([^a-z]|$)")
|
||||
)
|
||||
|
||||
// staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties --
|
||||
// properties which apply to either the shared or static version of a cc_library module.
|
||||
type staticOrSharedAttributes struct {
|
||||
|
@ -61,46 +54,32 @@ type staticOrSharedAttributes struct {
|
|||
Enabled bazel.BoolAttribute
|
||||
}
|
||||
|
||||
// groupSrcsByExtension partitions `srcs` into groups based on file extension.
|
||||
func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
|
||||
// Check that a module is a filegroup type
|
||||
isFilegroup := func(m blueprint.Module) bool {
|
||||
return ctx.OtherModuleType(m) == "filegroup"
|
||||
}
|
||||
|
||||
// Convert filegroup dependencies into extension-specific filegroups filtered in the filegroup.bzl
|
||||
// macro.
|
||||
addSuffixForFilegroup := func(suffix string) bazel.LabelMapper {
|
||||
return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
|
||||
m, exists := ctx.ModuleFromName(label.OriginalModuleName)
|
||||
labelStr := label.Label
|
||||
if !exists || !isFilegroup(m) {
|
||||
if !exists || !android.IsFilegroup(ctx, m) {
|
||||
return labelStr, false
|
||||
}
|
||||
return labelStr + suffix, true
|
||||
}
|
||||
}
|
||||
|
||||
isProtoFilegroup := func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
|
||||
m, exists := ctx.ModuleFromName(label.OriginalModuleName)
|
||||
labelStr := label.Label
|
||||
if !exists || !isFilegroup(m) {
|
||||
return labelStr, false
|
||||
}
|
||||
likelyProtos := filegroupLikelyProtoPattern.MatchString(label.OriginalModuleName)
|
||||
return labelStr, likelyProtos
|
||||
}
|
||||
|
||||
// TODO(b/190006308): Handle language detection of sources in a Bazel rule.
|
||||
partitioned := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
|
||||
protoSrcPartition: bazel.LabelPartition{Extensions: []string{".proto"}, LabelMapper: isProtoFilegroup},
|
||||
labels := bazel.LabelPartitions{
|
||||
protoSrcPartition: android.ProtoSrcLabelPartition,
|
||||
cSrcPartition: bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")},
|
||||
asSrcPartition: bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")},
|
||||
// C++ is the "catch-all" group, and comprises generated sources because we don't
|
||||
// know the language of these sources until the genrule is executed.
|
||||
cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
|
||||
})
|
||||
}
|
||||
|
||||
return partitioned
|
||||
return bazel.PartitionLabelListAttribute(ctx, &srcs, labels)
|
||||
}
|
||||
|
||||
// bp2BuildParseLibProps returns the attributes for a variant of a cc_library.
|
||||
|
|
|
@ -177,7 +177,7 @@ type bp2buildProtoDeps struct {
|
|||
func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) bp2buildProtoDeps {
|
||||
var ret bp2buildProtoDeps
|
||||
|
||||
protoInfo, ok := android.Bp2buildProtoProperties(ctx, m, protoSrcs)
|
||||
protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs)
|
||||
if !ok {
|
||||
return ret
|
||||
}
|
||||
|
|
16
java/java.go
16
java/java.go
|
@ -2013,8 +2013,16 @@ type javaLibraryAttributes struct {
|
|||
func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) *javaLibraryAttributes {
|
||||
//TODO(b/209577426): Support multiple arch variants
|
||||
srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs))
|
||||
|
||||
javaSrcPartition := "java"
|
||||
protoSrcPartition := "proto"
|
||||
srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
|
||||
javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true},
|
||||
protoSrcPartition: android.ProtoSrcLabelPartition,
|
||||
})
|
||||
|
||||
attrs := &javaLibraryAttributes{
|
||||
Srcs: srcs,
|
||||
Srcs: srcPartitions[javaSrcPartition],
|
||||
}
|
||||
|
||||
if m.properties.Javacflags != nil {
|
||||
|
@ -2029,6 +2037,12 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
|
|||
//TODO(b/217236083) handle static libs similarly to Soong
|
||||
deps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Static_libs))
|
||||
}
|
||||
|
||||
protoDeps := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition])
|
||||
if protoDeps != nil {
|
||||
deps.Add(protoDeps)
|
||||
}
|
||||
|
||||
attrs.Deps = bazel.MakeLabelListAttribute(deps)
|
||||
|
||||
return attrs
|
||||
|
|
|
@ -19,6 +19,13 @@ import (
|
|||
"strconv"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/bazel"
|
||||
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
||||
const (
|
||||
protoTypeDefault = "lite"
|
||||
)
|
||||
|
||||
func genProto(ctx android.ModuleContext, protoFiles android.Paths, flags android.ProtoFlags) android.Paths {
|
||||
|
@ -134,3 +141,52 @@ func protoFlags(ctx android.ModuleContext, j *CommonProperties, p *android.Proto
|
|||
|
||||
return flags
|
||||
}
|
||||
|
||||
type protoAttributes struct {
|
||||
Deps bazel.LabelListAttribute
|
||||
}
|
||||
|
||||
func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) *bazel.Label {
|
||||
protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
typ := proptools.StringDefault(protoInfo.Type, protoTypeDefault)
|
||||
var rule_class string
|
||||
suffix := "_java_proto"
|
||||
switch typ {
|
||||
case "nano":
|
||||
suffix += "_nano"
|
||||
rule_class = "java_nano_proto_library"
|
||||
case "micro":
|
||||
suffix += "_micro"
|
||||
rule_class = "java_micro_proto_library"
|
||||
case "lite":
|
||||
suffix += "_lite"
|
||||
rule_class = "java_lite_proto_library"
|
||||
case "stream":
|
||||
suffix += "_stream"
|
||||
rule_class = "java_stream_proto_library"
|
||||
case "full":
|
||||
rule_class = "java_proto_library"
|
||||
default:
|
||||
ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ)
|
||||
}
|
||||
|
||||
protoLabel := bazel.Label{Label: ":" + m.Name() + "_proto"}
|
||||
var protoAttrs protoAttributes
|
||||
protoAttrs.Deps.SetValue(bazel.LabelList{Includes: []bazel.Label{protoLabel}})
|
||||
|
||||
name := m.Name() + suffix
|
||||
|
||||
ctx.CreateBazelTargetModule(
|
||||
bazel.BazelTargetModuleProperties{
|
||||
Rule_class: rule_class,
|
||||
Bzl_load_location: "//build/bazel/rules/java:proto.bzl",
|
||||
},
|
||||
android.CommonAttributes{Name: name},
|
||||
&protoAttrs)
|
||||
|
||||
return &bazel.Label{Label: ":" + name}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue