Merge changes from topic "aidl_interface_bp2build"

* changes:
  add bp2build unit tests for aidl_interface
  AIDL source generation accounts for Bazel paths
  convert .aidl srcs for java_library
  add Partition method to LabelListAttribute
This commit is contained in:
Sam Delmerico
2022-08-26 20:07:58 +00:00
committed by Gerrit Code Review
17 changed files with 770 additions and 50 deletions

View File

@@ -157,6 +157,7 @@ var (
"frameworks/av/media/liberror": Bp2BuildDefaultTrueRecursively, "frameworks/av/media/liberror": Bp2BuildDefaultTrueRecursively,
"frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively, "frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively,
"frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue, "frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue,
"frameworks/base/services/tests/servicestests/aidl": Bp2BuildDefaultTrue,
"frameworks/base/startop/apps/test": Bp2BuildDefaultTrue, "frameworks/base/startop/apps/test": Bp2BuildDefaultTrue,
"frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively, "frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
"frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively, "frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively,
@@ -408,6 +409,7 @@ var (
"linker_config", "linker_config",
"java_import", "java_import",
"java_import_host", "java_import_host",
"aidl_interface_headers",
} }
Bp2buildModuleDoNotConvertList = []string{ Bp2buildModuleDoNotConvertList = []string{

View File

@@ -16,6 +16,7 @@ package android
import ( import (
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"android/soong/bazel" "android/soong/bazel"
@@ -37,6 +38,34 @@ func IsFilegroup(ctx bazel.OtherModuleContext, m blueprint.Module) bool {
return ctx.OtherModuleType(m) == "filegroup" return ctx.OtherModuleType(m) == "filegroup"
} }
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]|$)")
filegroupLikelyAidlPattern = regexp.MustCompile("(?i)(^|[^a-z])aidl([^a-z]|$)")
ProtoSrcLabelPartition = bazel.LabelPartition{
Extensions: []string{".proto"},
LabelMapper: isFilegroupWithPattern(filegroupLikelyProtoPattern),
}
AidlSrcLabelPartition = bazel.LabelPartition{
Extensions: []string{".aidl"},
LabelMapper: isFilegroupWithPattern(filegroupLikelyAidlPattern),
}
)
func isFilegroupWithPattern(pattern *regexp.Regexp) bazel.LabelMapper {
return func(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
}
likelyMatched := pattern.MatchString(label.OriginalModuleName)
return labelStr, likelyMatched
}
}
// https://docs.bazel.build/versions/master/be/general.html#filegroup // https://docs.bazel.build/versions/master/be/general.html#filegroup
type bazelFilegroupAttributes struct { type bazelFilegroupAttributes struct {
Srcs bazel.LabelListAttribute Srcs bazel.LabelListAttribute
@@ -232,3 +261,16 @@ func (fg *fileGroup) GetAidlLibraryLabel(ctx BazelConversionPathContext) string
return fg.GetBazelLabel(ctx, fg) return fg.GetBazelLabel(ctx, fg)
} }
} }
// Given a name in srcs prop, check to see if the name references a filegroup
// and the filegroup is converted to aidl_library
func IsConvertedToAidlLibrary(ctx BazelConversionPathContext, name string) bool {
if module, ok := ctx.ModuleFromName(name); ok {
if IsFilegroup(ctx, module) {
if fg, ok := module.(Bp2buildAidlLibrary); ok {
return fg.ShouldConvertToAidlLibrary(ctx)
}
}
}
return false
}

View File

@@ -642,6 +642,20 @@ type TestResult struct {
NinjaDeps []string NinjaDeps []string
} }
type TestPathContext struct {
*TestResult
}
var _ PathContext = &TestPathContext{}
func (t *TestPathContext) Config() Config {
return t.TestResult.Config
}
func (t *TestPathContext) AddNinjaFileDeps(deps ...string) {
panic("unimplemented")
}
func createFixture(t *testing.T, buildDir string, preparers []*simpleFixturePreparer) Fixture { func createFixture(t *testing.T, buildDir string, preparers []*simpleFixturePreparer) Fixture {
config := TestConfig(buildDir, nil, "", nil) config := TestConfig(buildDir, nil, "", nil)
ctx := NewTestContext(config) ctx := NewTestContext(config)

View File

@@ -1978,6 +1978,18 @@ func PathForTesting(paths ...string) Path {
return testPath{basePath{path: p, rel: p}} return testPath{basePath{path: p, rel: p}}
} }
func PathForTestingWithRel(path, rel string) Path {
p, err := validateSafePath(path, rel)
if err != nil {
panic(err)
}
r, err := validatePath(rel)
if err != nil {
panic(err)
}
return testPath{basePath{path: p, rel: r}}
}
// PathsForTesting returns a Path constructed from each element in strs. It should only be used from within tests. // PathsForTesting returns a Path constructed from each element in strs. It should only be used from within tests.
func PathsForTesting(strs ...string) Paths { func PathsForTesting(strs ...string) Paths {
p := make(Paths, len(strs)) p := make(Paths, len(strs))

View File

@@ -16,7 +16,6 @@ package android
import ( import (
"android/soong/bazel" "android/soong/bazel"
"regexp"
"strings" "strings"
"github.com/google/blueprint" "github.com/google/blueprint"
@@ -27,14 +26,6 @@ const (
canonicalPathFromRootDefault = true 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 // 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 // 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 // reference source files in other modules, then every module that owns a proto file will need to
@@ -213,13 +204,3 @@ func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, m *ModuleBase, srcs baz
return info, true 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
}

View File

@@ -119,7 +119,7 @@ func (ll *LabelList) uniqueParentDirectories() []string {
return dirs return dirs
} }
// Add inserts the label Label at the end of the LabelList. // Add inserts the label Label at the end of the LabelList.Includes.
func (ll *LabelList) Add(label *Label) { func (ll *LabelList) Add(label *Label) {
if label == nil { if label == nil {
return return
@@ -127,6 +127,14 @@ func (ll *LabelList) Add(label *Label) {
ll.Includes = append(ll.Includes, *label) ll.Includes = append(ll.Includes, *label)
} }
// AddExclude inserts the label Label at the end of the LabelList.Excludes.
func (ll *LabelList) AddExclude(label *Label) {
if label == nil {
return
}
ll.Excludes = append(ll.Excludes, *label)
}
// Append appends the fields of other labelList to the corresponding fields of ll. // Append appends the fields of other labelList to the corresponding fields of ll.
func (ll *LabelList) Append(other LabelList) { func (ll *LabelList) Append(other LabelList) {
if len(ll.Includes) > 0 || len(other.Includes) > 0 { if len(ll.Includes) > 0 || len(other.Includes) > 0 {
@@ -137,6 +145,30 @@ func (ll *LabelList) Append(other LabelList) {
} }
} }
// Partition splits a LabelList into two LabelLists depending on the return value
// of the predicate.
// This function preserves the Includes and Excludes, but it does not provide
// that information to the partition function.
func (ll *LabelList) Partition(predicate func(label Label) bool) (LabelList, LabelList) {
predicated := LabelList{}
unpredicated := LabelList{}
for _, include := range ll.Includes {
if predicate(include) {
predicated.Add(&include)
} else {
unpredicated.Add(&include)
}
}
for _, exclude := range ll.Excludes {
if predicate(exclude) {
predicated.AddExclude(&exclude)
} else {
unpredicated.AddExclude(&exclude)
}
}
return predicated, unpredicated
}
// UniqueSortedBazelLabels takes a []Label and deduplicates the labels, and returns // UniqueSortedBazelLabels takes a []Label and deduplicates the labels, and returns
// the slice in a sorted order. // the slice in a sorted order.
func UniqueSortedBazelLabels(originalLabels []Label) []Label { func UniqueSortedBazelLabels(originalLabels []Label) []Label {
@@ -822,6 +854,29 @@ func (lla *LabelListAttribute) ResolveExcludes() {
} }
} }
// Partition splits a LabelListAttribute into two LabelListAttributes depending
// on the return value of the predicate.
// This function preserves the Includes and Excludes, but it does not provide
// that information to the partition function.
func (lla LabelListAttribute) Partition(predicate func(label Label) bool) (LabelListAttribute, LabelListAttribute) {
predicated := LabelListAttribute{}
unpredicated := LabelListAttribute{}
valuePartitionTrue, valuePartitionFalse := lla.Value.Partition(predicate)
predicated.SetValue(valuePartitionTrue)
unpredicated.SetValue(valuePartitionFalse)
for axis, selectValueLabelLists := range lla.ConfigurableValues {
for config, labelList := range selectValueLabelLists {
configPredicated, configUnpredicated := labelList.Partition(predicate)
predicated.SetSelectValue(axis, config, configPredicated)
unpredicated.SetSelectValue(axis, config, configUnpredicated)
}
}
return predicated, unpredicated
}
// OtherModuleContext is a limited context that has methods with information about other modules. // OtherModuleContext is a limited context that has methods with information about other modules.
type OtherModuleContext interface { type OtherModuleContext interface {
ModuleFromName(name string) (blueprint.Module, bool) ModuleFromName(name string) (blueprint.Module, bool)

View File

@@ -310,6 +310,134 @@ func TestResolveExcludes(t *testing.T) {
} }
} }
func TestLabelListAttributePartition(t *testing.T) {
testCases := []struct {
name string
input LabelListAttribute
predicated LabelListAttribute
unpredicated LabelListAttribute
predicate func(label Label) bool
}{
{
name: "move all to predicated partition",
input: MakeLabelListAttribute(makeLabelList(
[]string{"keep1", "throw1", "keep2", "throw2"},
[]string{"keep1", "throw1", "keep2", "throw2"},
)),
predicated: MakeLabelListAttribute(makeLabelList(
[]string{"keep1", "throw1", "keep2", "throw2"},
[]string{"keep1", "throw1", "keep2", "throw2"},
)),
unpredicated: LabelListAttribute{},
predicate: func(label Label) bool {
return true
},
},
{
name: "move all to unpredicated partition",
input: MakeLabelListAttribute(makeLabelList(
[]string{"keep1", "throw1", "keep2", "throw2"},
[]string{"keep1", "throw1", "keep2", "throw2"},
)),
predicated: LabelListAttribute{},
unpredicated: MakeLabelListAttribute(makeLabelList(
[]string{"keep1", "throw1", "keep2", "throw2"},
[]string{"keep1", "throw1", "keep2", "throw2"},
)),
predicate: func(label Label) bool {
return false
},
},
{
name: "partition includes and excludes",
input: MakeLabelListAttribute(makeLabelList(
[]string{"keep1", "throw1", "keep2", "throw2"},
[]string{"keep1", "throw1", "keep2", "throw2"},
)),
predicated: MakeLabelListAttribute(makeLabelList(
[]string{"keep1", "keep2"},
[]string{"keep1", "keep2"},
)),
unpredicated: MakeLabelListAttribute(makeLabelList(
[]string{"throw1", "throw2"},
[]string{"throw1", "throw2"},
)),
predicate: func(label Label) bool {
return strings.HasPrefix(label.Label, "keep")
},
},
{
name: "partition excludes only",
input: MakeLabelListAttribute(makeLabelList(
[]string{},
[]string{"keep1", "throw1", "keep2", "throw2"},
)),
predicated: MakeLabelListAttribute(makeLabelList(
[]string{},
[]string{"keep1", "keep2"},
)),
unpredicated: MakeLabelListAttribute(makeLabelList(
[]string{},
[]string{"throw1", "throw2"},
)),
predicate: func(label Label) bool {
return strings.HasPrefix(label.Label, "keep")
},
},
{
name: "partition includes only",
input: MakeLabelListAttribute(makeLabelList(
[]string{"keep1", "throw1", "keep2", "throw2"},
[]string{},
)),
predicated: MakeLabelListAttribute(makeLabelList(
[]string{"keep1", "keep2"},
[]string{},
)),
unpredicated: MakeLabelListAttribute(makeLabelList(
[]string{"throw1", "throw2"},
[]string{},
)),
predicate: func(label Label) bool {
return strings.HasPrefix(label.Label, "keep")
},
},
{
name: "empty partition",
input: MakeLabelListAttribute(makeLabelList([]string{}, []string{})),
predicated: LabelListAttribute{},
unpredicated: LabelListAttribute{},
predicate: func(label Label) bool {
return true
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
predicated, unpredicated := tc.input.Partition(tc.predicate)
if !predicated.Value.Equals(tc.predicated.Value) {
t.Errorf("expected predicated labels to be %v; got %v", tc.predicated, predicated)
}
for axis, configs := range predicated.ConfigurableValues {
tcConfigs, ok := tc.predicated.ConfigurableValues[axis]
if !ok || !reflect.DeepEqual(configs, tcConfigs) {
t.Errorf("expected predicated labels to be %v; got %v", tc.predicated, predicated)
}
}
if !unpredicated.Value.Equals(tc.unpredicated.Value) {
t.Errorf("expected unpredicated labels to be %v; got %v", tc.unpredicated, unpredicated)
}
for axis, configs := range unpredicated.ConfigurableValues {
tcConfigs, ok := tc.unpredicated.ConfigurableValues[axis]
if !ok || !reflect.DeepEqual(configs, tcConfigs) {
t.Errorf("expected unpredicated labels to be %v; got %v", tc.unpredicated, unpredicated)
}
}
})
}
}
// labelAddSuffixForTypeMapper returns a LabelMapper that adds suffix to label name for modules of // labelAddSuffixForTypeMapper returns a LabelMapper that adds suffix to label name for modules of
// typ // typ
func labelAddSuffixForTypeMapper(suffix, typ string) LabelMapper { func labelAddSuffixForTypeMapper(suffix, typ string) LabelMapper {

View File

@@ -18,6 +18,7 @@ bootstrap_go_package {
"testing.go", "testing.go",
], ],
deps: [ deps: [
"aidl-soong-rules",
"soong-android", "soong-android",
"soong-android-allowlists", "soong-android-allowlists",
"soong-android-soongconfig", "soong-android-soongconfig",
@@ -36,6 +37,7 @@ bootstrap_go_package {
], ],
testSrcs: [ testSrcs: [
"aar_conversion_test.go", "aar_conversion_test.go",
"aidl_interface_conversion_test.go",
"android_app_certificate_conversion_test.go", "android_app_certificate_conversion_test.go",
"android_app_conversion_test.go", "android_app_conversion_test.go",
"apex_conversion_test.go", "apex_conversion_test.go",

View File

@@ -0,0 +1,249 @@
package bp2build
import (
"android/soong/aidl"
"android/soong/android"
"testing"
)
func runAidlInterfaceTestCase(t *testing.T, tc Bp2buildTestCase) {
t.Helper()
RunBp2BuildTestCase(
t,
func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("aidl_interface", aidl.AidlInterfaceFactory)
ctx.RegisterModuleType("aidl_interface_headers", aidl.AidlInterfaceHeadersFactory)
},
tc,
)
}
func TestAidlInterfaceHeaders(t *testing.T) {
runAidlInterfaceTestCase(t, Bp2buildTestCase{
Description: `aidl_interface_headers`,
Blueprint: `
aidl_interface_headers {
name: "aidl-interface-headers",
include_dir: "src",
srcs: [
"src/A.aidl",
],
}
`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("aidl_library", "aidl-interface-headers", AttrNameToString{
"strip_import_prefix": `"src"`,
"hdrs": `["src/A.aidl"]`,
}),
},
})
}
func TestAidlInterface(t *testing.T) {
runAidlInterfaceTestCase(t, Bp2buildTestCase{
Description: `aidl_interface with single "latest" aidl_interface import`,
Blueprint: `
aidl_interface_headers {
name: "aidl-interface-headers",
}
aidl_interface {
name: "aidl-interface-import",
versions: [
"1",
"2",
],
}
aidl_interface {
name: "aidl-interface1",
flags: ["--flag1"],
imports: [
"aidl-interface-import-V1",
],
headers: [
"aidl-interface-headers",
],
versions: [
"1",
"2",
"3",
],
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("aidl_library", "aidl-interface-headers", AttrNameToString{}),
MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface-import", AttrNameToString{
"backends": `[
"cpp",
"java",
"ndk",
]`,
"versions": `[
"1",
"2",
]`,
}),
MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{
"backends": `[
"cpp",
"java",
"ndk",
]`,
"deps": `[
":aidl-interface-import-V1",
":aidl-interface-headers",
]`,
"flags": `["--flag1"]`,
"versions": `[
"1",
"2",
"3",
]`,
}),
},
})
}
func TestAidlInterfaceWithNoProperties(t *testing.T) {
runAidlInterfaceTestCase(t, Bp2buildTestCase{
Description: `aidl_interface no properties set`,
Blueprint: `
aidl_interface {
name: "aidl-interface1",
}
`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{
"backends": `[
"cpp",
"java",
"ndk",
]`,
}),
},
})
}
func TestAidlInterfaceWithDisabledBackends(t *testing.T) {
runAidlInterfaceTestCase(t, Bp2buildTestCase{
Description: `aidl_interface with some backends disabled`,
Blueprint: `
aidl_interface {
name: "aidl-interface1",
backend: {
ndk: {
enabled: false,
},
cpp: {
enabled: false,
},
},
}
`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{
"backends": `["java"]`,
}),
},
})
}
func TestAidlInterfaceWithLatestImport(t *testing.T) {
runAidlInterfaceTestCase(t, Bp2buildTestCase{
Description: `aidl_interface with single "latest" aidl_interface import`,
Blueprint: `
aidl_interface {
name: "aidl-interface-import",
versions: [
"1",
"2",
],
}
aidl_interface {
name: "aidl-interface1",
imports: [
"aidl-interface-import",
],
versions: [
"1",
"2",
"3",
],
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface-import", AttrNameToString{
"backends": `[
"cpp",
"java",
"ndk",
]`,
"versions": `[
"1",
"2",
]`,
}),
MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{
"backends": `[
"cpp",
"java",
"ndk",
]`,
"deps": `[":aidl-interface-import-latest"]`,
"versions": `[
"1",
"2",
"3",
]`,
}),
},
})
}
func TestAidlInterfaceWithVersionedImport(t *testing.T) {
runAidlInterfaceTestCase(t, Bp2buildTestCase{
Description: `aidl_interface with single versioned aidl_interface import`,
Blueprint: `
aidl_interface {
name: "aidl-interface-import",
versions: [
"1",
"2",
],
}
aidl_interface {
name: "aidl-interface1",
imports: [
"aidl-interface-import-V2",
],
versions: [
"1",
"2",
"3",
],
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface-import", AttrNameToString{
"backends": `[
"cpp",
"java",
"ndk",
]`,
"versions": `[
"1",
"2",
]`,
}),
MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{
"backends": `[
"cpp",
"java",
"ndk",
]`,
"deps": `[":aidl-interface-import-V2"]`,
"versions": `[
"1",
"2",
"3",
]`,
}),
},
})
}

View File

@@ -372,3 +372,132 @@ func TestJavaLibraryResourcesFailsWithMultipleDirs(t *testing.T) {
ExpectedBazelTargets: []string{}, ExpectedBazelTargets: []string{},
}) })
} }
func TestJavaLibraryAidl(t *testing.T) {
runJavaLibraryTestCase(t, Bp2buildTestCase{
Description: "Java library - aidl creates separate dependency",
ModuleTypeUnderTest: "java_library",
ModuleTypeUnderTestFactory: java.LibraryFactory,
Blueprint: `java_library {
name: "example_lib",
srcs: [
"a.java",
"b.java",
"a.aidl",
"b.aidl",
],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
makeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{
"srcs": `[
"a.aidl",
"b.aidl",
]`,
}),
makeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{
"deps": `[":example_lib_aidl_library"]`,
}),
makeBazelTarget("java_library", "example_lib", AttrNameToString{
"deps": `[":example_lib_java_aidl_library"]`,
"exports": `[":example_lib_java_aidl_library"]`,
"srcs": `[
"a.java",
"b.java",
]`,
}),
}})
}
func TestJavaLibraryAidlSrcsNoFileGroup(t *testing.T) {
runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
Description: "Java library - aidl filegroup is parsed",
ModuleTypeUnderTest: "java_library",
ModuleTypeUnderTestFactory: java.LibraryFactory,
Blueprint: `
java_library {
name: "example_lib",
srcs: [
"a.java",
"b.aidl",
],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
makeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{
"srcs": `["b.aidl"]`,
}),
makeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{
"deps": `[":example_lib_aidl_library"]`,
}),
makeBazelTarget("java_library", "example_lib", AttrNameToString{
"deps": `[":example_lib_java_aidl_library"]`,
"exports": `[":example_lib_java_aidl_library"]`,
"srcs": `["a.java"]`,
}),
},
}, func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
})
}
func TestJavaLibraryAidlFilegroup(t *testing.T) {
runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
Description: "Java library - aidl filegroup is parsed",
ModuleTypeUnderTest: "java_library",
ModuleTypeUnderTestFactory: java.LibraryFactory,
Blueprint: `
filegroup {
name: "random_other_files",
srcs: [
"a.java",
"b.java",
],
}
filegroup {
name: "aidl_files",
srcs: [
"a.aidl",
"b.aidl",
],
}
java_library {
name: "example_lib",
srcs: [
"a.java",
"b.java",
":aidl_files",
":random_other_files",
],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("aidl_library", "aidl_files", AttrNameToString{
"srcs": `[
"a.aidl",
"b.aidl",
]`,
}),
makeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{
"deps": `[":aidl_files"]`,
}),
makeBazelTarget("java_library", "example_lib", AttrNameToString{
"deps": `[":example_lib_java_aidl_library"]`,
"exports": `[":example_lib_java_aidl_library"]`,
"srcs": `[
"a.java",
"b.java",
":random_other_files",
]`,
}),
MakeBazelTargetNoRestrictions("filegroup", "random_other_files", AttrNameToString{
"srcs": `[
"a.java",
"b.java",
]`,
}),
},
}, func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
})
}

10
go.mod
View File

@@ -1,13 +1,17 @@
module android/soong module android/soong
require google.golang.org/protobuf v0.0.0 require (
google.golang.org/protobuf v0.0.0
require github.com/google/blueprint v0.0.0 github.com/google/blueprint v0.0.0
android/soong/aidl v0.0.0
)
replace google.golang.org/protobuf v0.0.0 => ../../external/golang-protobuf replace google.golang.org/protobuf v0.0.0 => ../../external/golang-protobuf
replace github.com/google/blueprint v0.0.0 => ../blueprint replace github.com/google/blueprint v0.0.0 => ../blueprint
replace android/soong/aidl v0.0.0 => ../../system/tools/aidl/build
// Indirect deps from golang-protobuf // Indirect deps from golang-protobuf
exclude github.com/golang/protobuf v1.5.0 exclude github.com/golang/protobuf v1.5.0

View File

@@ -820,7 +820,7 @@ func (j *Module) individualAidlFlags(ctx android.ModuleContext, aidlFile android
} }
func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath, func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
aidlIncludeDirs android.Paths) (string, android.Paths) { aidlIncludeDirs android.Paths, aidlSrcs android.Paths) (string, android.Paths) {
aidlIncludes := android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Local_include_dirs) aidlIncludes := android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Local_include_dirs)
aidlIncludes = append(aidlIncludes, aidlIncludes = append(aidlIncludes,
@@ -830,6 +830,7 @@ func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Opt
var flags []string var flags []string
var deps android.Paths var deps android.Paths
var includeDirs android.Paths
flags = append(flags, j.deviceProperties.Aidl.Flags...) flags = append(flags, j.deviceProperties.Aidl.Flags...)
@@ -837,21 +838,24 @@ func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Opt
flags = append(flags, "-p"+aidlPreprocess.String()) flags = append(flags, "-p"+aidlPreprocess.String())
deps = append(deps, aidlPreprocess.Path()) deps = append(deps, aidlPreprocess.Path())
} else if len(aidlIncludeDirs) > 0 { } else if len(aidlIncludeDirs) > 0 {
flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I")) includeDirs = append(includeDirs, aidlIncludeDirs...)
} }
if len(j.exportAidlIncludeDirs) > 0 { if len(j.exportAidlIncludeDirs) > 0 {
flags = append(flags, android.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I")) includeDirs = append(includeDirs, j.exportAidlIncludeDirs...)
} }
if len(aidlIncludes) > 0 { if len(aidlIncludes) > 0 {
flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I")) includeDirs = append(includeDirs, aidlIncludes...)
} }
flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String()) includeDirs = append(includeDirs, android.PathForModuleSrc(ctx))
if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() { if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
flags = append(flags, "-I"+src.String()) includeDirs = append(includeDirs, src.Path())
} }
flags = append(flags, android.JoinWithPrefix(includeDirs.Strings(), "-I"))
// add flags for dirs containing AIDL srcs that haven't been specified yet
flags = append(flags, genAidlIncludeFlags(ctx, aidlSrcs, includeDirs))
if Bool(j.deviceProperties.Aidl.Generate_traces) { if Bool(j.deviceProperties.Aidl.Generate_traces) {
flags = append(flags, "-t") flags = append(flags, "-t")
@@ -935,9 +939,6 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB
// systemModules // systemModules
flags.systemModules = deps.systemModules flags.systemModules = deps.systemModules
// aidl flags.
flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
return flags return flags
} }
@@ -1046,6 +1047,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files") ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files")
} }
aidlSrcs := srcFiles.FilterByExt(".aidl")
flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs, aidlSrcs)
nonGeneratedSrcJars := srcFiles.FilterByExt(".srcjar") nonGeneratedSrcJars := srcFiles.FilterByExt(".srcjar")
srcFiles = j.genSources(ctx, srcFiles, flags) srcFiles = j.genSources(ctx, srcFiles, flags)

View File

@@ -314,7 +314,7 @@ func (j *Javadoc) genSources(ctx android.ModuleContext, srcFiles android.Paths,
outSrcFiles := make(android.Paths, 0, len(srcFiles)) outSrcFiles := make(android.Paths, 0, len(srcFiles))
var aidlSrcs android.Paths var aidlSrcs android.Paths
aidlIncludeFlags := genAidlIncludeFlags(srcFiles) aidlIncludeFlags := genAidlIncludeFlags(ctx, srcFiles, android.Paths{})
for _, srcFile := range srcFiles { for _, srcFile := range srcFiles {
switch srcFile.Ext() { switch srcFile.Ext() {

View File

@@ -15,6 +15,7 @@
package java package java
import ( import (
"path/filepath"
"strconv" "strconv"
"strings" "strings"
@@ -116,12 +117,31 @@ func genLogtags(ctx android.ModuleContext, logtagsFile android.Path) android.Pat
return javaFile return javaFile
} }
func genAidlIncludeFlags(srcFiles android.Paths) string { // genAidlIncludeFlags returns additional include flags based on the relative path
// of each .aidl file passed in srcFiles. excludeDirs is a list of paths relative to
// the Android checkout root that should not be included in the returned flags.
func genAidlIncludeFlags(ctx android.PathContext, srcFiles android.Paths, excludeDirs android.Paths) string {
var baseDirs []string var baseDirs []string
excludeDirsStrings := excludeDirs.Strings()
for _, srcFile := range srcFiles { for _, srcFile := range srcFiles {
if srcFile.Ext() == ".aidl" { if srcFile.Ext() == ".aidl" {
baseDir := strings.TrimSuffix(srcFile.String(), srcFile.Rel()) baseDir := strings.TrimSuffix(srcFile.String(), srcFile.Rel())
if baseDir != "" && !android.InList(baseDir, baseDirs) { baseDir = filepath.Clean(baseDir)
baseDirSeen := android.InList(baseDir, baseDirs) || android.InList(baseDir, excludeDirsStrings)
// For go/bp2build mixed builds, a file may be listed under a
// directory in the Bazel output tree that is symlinked to a
// directory under the android source tree. We should only
// include one copy of this directory so that the AIDL tool
// doesn't find multiple definitions of the same AIDL class.
// This code comes into effect when filegroups are used in mixed builds.
bazelPathPrefix := android.PathForBazelOut(ctx, "").String()
bazelBaseDir, err := filepath.Rel(bazelPathPrefix, baseDir)
bazelBaseDirSeen := err == nil &&
android.InList(bazelBaseDir, baseDirs) ||
android.InList(bazelBaseDir, excludeDirsStrings)
if baseDir != "" && !baseDirSeen && !bazelBaseDirSeen {
baseDirs = append(baseDirs, baseDir) baseDirs = append(baseDirs, baseDir)
} }
} }
@@ -136,8 +156,6 @@ func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths,
var protoSrcs android.Paths var protoSrcs android.Paths
var aidlSrcs android.Paths var aidlSrcs android.Paths
aidlIncludeFlags := genAidlIncludeFlags(srcFiles)
for _, srcFile := range srcFiles { for _, srcFile := range srcFiles {
switch srcFile.Ext() { switch srcFile.Ext() {
case ".aidl": case ".aidl":
@@ -168,7 +186,7 @@ func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths,
individualFlags[aidlSrc.String()] = flags individualFlags[aidlSrc.String()] = flags
} }
} }
srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags+aidlIncludeFlags, individualFlags, flags.aidlDeps) srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags, individualFlags, flags.aidlDeps)
outSrcFiles = append(outSrcFiles, srcJarFiles...) outSrcFiles = append(outSrcFiles, srcJarFiles...)
} }

View File

@@ -2259,16 +2259,27 @@ type javaDependencyLabels struct {
StaticDeps bazel.LabelListAttribute StaticDeps bazel.LabelListAttribute
} }
// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules
// and also separates dependencies into dynamic dependencies and static dependencies.
// Each corresponding Bazel target type, can have a different method for handling
// dynamic vs. static dependencies, and so these are returned to the calling function.
type eventLogTagsAttributes struct { type eventLogTagsAttributes struct {
Srcs bazel.LabelListAttribute Srcs bazel.LabelListAttribute
} }
type aidlLibraryAttributes struct {
Srcs bazel.LabelListAttribute
}
type javaAidlLibraryAttributes struct {
Deps bazel.LabelListAttribute
}
// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules
// and also separates dependencies into dynamic dependencies and static dependencies.
// Each corresponding Bazel target type, can have a different method for handling
// dynamic vs. static dependencies, and so these are returned to the calling function.
func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) { func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) {
var srcs bazel.LabelListAttribute var srcs bazel.LabelListAttribute
var deps bazel.LabelList
var staticDeps bazel.LabelList
archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{}) archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{})
for axis, configToProps := range archVariantProps { for axis, configToProps := range archVariantProps {
for config, _props := range configToProps { for config, _props := range configToProps {
@@ -2282,18 +2293,18 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
javaSrcPartition := "java" javaSrcPartition := "java"
protoSrcPartition := "proto" protoSrcPartition := "proto"
logtagSrcPartition := "logtag" logtagSrcPartition := "logtag"
aidlSrcPartition := "aidl"
srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{ srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true}, javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true},
logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}}, logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}},
protoSrcPartition: android.ProtoSrcLabelPartition, protoSrcPartition: android.ProtoSrcLabelPartition,
aidlSrcPartition: android.AidlSrcLabelPartition,
}) })
javaSrcs := srcPartitions[javaSrcPartition] javaSrcs := srcPartitions[javaSrcPartition]
var logtagsSrcs bazel.LabelList
if !srcPartitions[logtagSrcPartition].IsEmpty() { if !srcPartitions[logtagSrcPartition].IsEmpty() {
logtagsLibName := m.Name() + "_logtags" logtagsLibName := m.Name() + "_logtags"
logtagsSrcs = bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}})
ctx.CreateBazelTargetModule( ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{ bazel.BazelTargetModuleProperties{
Rule_class: "event_log_tags", Rule_class: "event_log_tags",
@@ -2304,8 +2315,45 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
Srcs: srcPartitions[logtagSrcPartition], Srcs: srcPartitions[logtagSrcPartition],
}, },
) )
logtagsSrcs := bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}})
javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs))
}
if !srcPartitions[aidlSrcPartition].IsEmpty() {
aidlLibs, aidlSrcs := srcPartitions[aidlSrcPartition].Partition(func(src bazel.Label) bool {
return android.IsConvertedToAidlLibrary(ctx, src.OriginalModuleName)
})
if !aidlSrcs.IsEmpty() {
aidlLibName := m.Name() + "_aidl_library"
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "aidl_library",
Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
},
android.CommonAttributes{Name: aidlLibName},
&aidlLibraryAttributes{
Srcs: aidlSrcs,
},
)
aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
}
javaAidlLibName := m.Name() + "_java_aidl_library"
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "java_aidl_library",
Bzl_load_location: "//build/bazel/rules/java:aidl_library.bzl",
},
android.CommonAttributes{Name: javaAidlLibName},
&javaAidlLibraryAttributes{
Deps: aidlLibs,
},
)
staticDeps.Add(&bazel.Label{Label: ":" + javaAidlLibName})
} }
javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs))
var javacopts []string var javacopts []string
if m.properties.Javacflags != nil { if m.properties.Javacflags != nil {
@@ -2331,14 +2379,10 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
Javacopts: bazel.MakeStringListAttribute(javacopts), Javacopts: bazel.MakeStringListAttribute(javacopts),
} }
depLabels := &javaDependencyLabels{}
var deps bazel.LabelList
if m.properties.Libs != nil { if m.properties.Libs != nil {
deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs)))) deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs))))
} }
var staticDeps bazel.LabelList
if m.properties.Static_libs != nil { if m.properties.Static_libs != nil {
staticDeps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Static_libs)))) staticDeps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Static_libs))))
} }
@@ -2352,6 +2396,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
// and so this should be a static dependency. // and so this should be a static dependency.
staticDeps.Add(protoDepLabel) staticDeps.Add(protoDepLabel)
depLabels := &javaDependencyLabels{}
depLabels.Deps = bazel.MakeLabelListAttribute(deps) depLabels.Deps = bazel.MakeLabelListAttribute(deps)
depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps) depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps)
@@ -2376,7 +2421,7 @@ func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
// TODO(b/220869005) remove forced dependency on current public android.jar // TODO(b/220869005) remove forced dependency on current public android.jar
deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:public_current_android_sdk_java_import")) deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:public_current_android_sdk_java_import"))
} }
} else if !depLabels.Deps.IsEmpty() { } else if !deps.IsEmpty() {
ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.") ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
} }

View File

@@ -1747,3 +1747,37 @@ func TestImportMixedBuild(t *testing.T) {
android.AssertDeepEquals(t, "Implementation/Resources JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationAndResourcesJars)) android.AssertDeepEquals(t, "Implementation/Resources JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationAndResourcesJars))
android.AssertDeepEquals(t, "Implementation JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationJars)) android.AssertDeepEquals(t, "Implementation JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationJars))
} }
func TestGenAidlIncludeFlagsForMixedBuilds(t *testing.T) {
bazelOutputBaseDir := filepath.Join("out", "bazel")
result := android.GroupFixturePreparers(
PrepareForIntegrationTestWithJava,
android.FixtureModifyConfig(func(config android.Config) {
config.BazelContext = android.MockBazelContext{
OutputBaseDir: bazelOutputBaseDir,
}
}),
).RunTest(t)
ctx := &android.TestPathContext{TestResult: result}
srcDirectory := filepath.Join("frameworks", "base")
srcDirectoryAlreadyIncluded := filepath.Join("frameworks", "base", "core", "java")
bazelSrcDirectory := android.PathForBazelOut(ctx, srcDirectory)
bazelSrcDirectoryAlreadyIncluded := android.PathForBazelOut(ctx, srcDirectoryAlreadyIncluded)
srcs := android.Paths{
android.PathForTestingWithRel(bazelSrcDirectory.String(), "bazelAidl.aidl"),
android.PathForTestingWithRel(bazelSrcDirectory.String(), "bazelAidl2.aidl"),
android.PathForTestingWithRel(bazelSrcDirectoryAlreadyIncluded.String(), "bazelAidlExclude.aidl"),
android.PathForTestingWithRel(bazelSrcDirectoryAlreadyIncluded.String(), "bazelAidl2Exclude.aidl"),
}
dirsAlreadyIncluded := android.Paths{
android.PathForTesting(srcDirectoryAlreadyIncluded),
}
expectedFlags := " -Iout/bazel/execroot/__main__/frameworks/base"
flags := genAidlIncludeFlags(ctx, srcs, dirsAlreadyIncluded)
if flags != expectedFlags {
t.Errorf("expected flags to be %q; was %q", expectedFlags, flags)
}
}

View File

@@ -93,6 +93,7 @@ function create_mock_soong {
symlink_directory external/go-cmp symlink_directory external/go-cmp
symlink_directory external/golang-protobuf symlink_directory external/golang-protobuf
symlink_directory external/starlark-go symlink_directory external/starlark-go
symlink_directory system/tools/aidl
touch "$MOCK_TOP/Android.bp" touch "$MOCK_TOP/Android.bp"
} }