Merge "Add AIDL enforce_permissions attribute"
diff --git a/android/arch.go b/android/arch.go
index a719cf3..67158e0 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -829,7 +829,7 @@
const maxArchTypeNameSize = 500
// Convert the type to a new set of types that contains only the arch-specific properties
- // (those that are tagged with `android:"arch_specific"`), and sharded into multiple types
+ // (those that are tagged with `android:"arch_variant"`), and sharded into multiple types
// to keep the runtime-generated names under the limit.
propShards, _ := proptools.FilterPropertyStructSharded(props, maxArchTypeNameSize, filterArchStruct)
@@ -864,6 +864,10 @@
archVariant := variantReplacer.Replace(archVariant)
variants = append(variants, proptools.FieldNameForProperty(archVariant))
}
+ for _, cpuVariant := range cpuVariants[arch] {
+ cpuVariant := variantReplacer.Replace(cpuVariant)
+ variants = append(variants, proptools.FieldNameForProperty(cpuVariant))
+ }
for _, feature := range archFeatures[arch] {
feature := variantReplacer.Replace(feature)
variants = append(variants, proptools.FieldNameForProperty(feature))
@@ -1741,6 +1745,18 @@
a.CpuVariant = ""
}
+ if a.ArchVariant != "" {
+ if validArchVariants := archVariants[archType]; !InList(a.ArchVariant, validArchVariants) {
+ return Arch{}, fmt.Errorf("[%q] unknown arch variant %q, support variants: %q", archType, a.ArchVariant, validArchVariants)
+ }
+ }
+
+ if a.CpuVariant != "" {
+ if validCpuVariants := cpuVariants[archType]; !InList(a.CpuVariant, validCpuVariants) {
+ return Arch{}, fmt.Errorf("[%q] unknown cpu variant %q, support variants: %q", archType, a.CpuVariant, validCpuVariants)
+ }
+ }
+
// Filter empty ABIs out of the list.
for i := 0; i < len(a.Abi); i++ {
if a.Abi[i] == "" {
diff --git a/android/arch_list.go b/android/arch_list.go
index d68a0d1..79ad4af 100644
--- a/android/arch_list.go
+++ b/android/arch_list.go
@@ -22,38 +22,12 @@
"armv7-a-neon",
"armv8-a",
"armv8-2a",
- "cortex-a7",
- "cortex-a8",
- "cortex-a9",
- "cortex-a15",
- "cortex-a53",
- "cortex-a53-a57",
- "cortex-a55",
- "cortex-a72",
- "cortex-a73",
- "cortex-a75",
- "cortex-a76",
- "krait",
- "kryo",
- "kryo385",
- "exynos-m1",
- "exynos-m2",
},
Arm64: {
- "armv8_a",
- "armv8_a_branchprot",
- "armv8_2a",
+ "armv8-a",
+ "armv8-a-branchprot",
+ "armv8-2a",
"armv8-2a-dotprod",
- "cortex-a53",
- "cortex-a55",
- "cortex-a72",
- "cortex-a73",
- "cortex-a75",
- "cortex-a76",
- "kryo",
- "kryo385",
- "exynos-m1",
- "exynos-m2",
},
X86: {
"amberlake",
@@ -87,6 +61,41 @@
},
}
+var cpuVariants = map[ArchType][]string{
+ Arm: {
+ "cortex-a7",
+ "cortex-a8",
+ "cortex-a9",
+ "cortex-a15",
+ "cortex-a53",
+ "cortex-a53.a57",
+ "cortex-a55",
+ "cortex-a72",
+ "cortex-a73",
+ "cortex-a75",
+ "cortex-a76",
+ "krait",
+ "kryo",
+ "kryo385",
+ "exynos-m1",
+ "exynos-m2",
+ },
+ Arm64: {
+ "cortex-a53",
+ "cortex-a55",
+ "cortex-a72",
+ "cortex-a73",
+ "cortex-a75",
+ "cortex-a76",
+ "kryo",
+ "kryo385",
+ "exynos-m1",
+ "exynos-m2",
+ },
+ X86: {},
+ X86_64: {},
+}
+
var archFeatures = map[ArchType][]string{
Arm: {
"neon",
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 0052551..804a5fb 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -73,7 +73,7 @@
}
type BazelContext interface {
- // The below methods involve queuing cquery requests to be later invoked
+ // The methods below involve queuing cquery requests to be later invoked
// by bazel. If any of these methods return (_, false), then the request
// has been queued to be run later.
@@ -561,7 +561,7 @@
return id_string + ">>" + %s(target)
`
- for requestType, _ := range requestTypeToCqueryIdEntries {
+ for requestType := range requestTypeToCqueryIdEntries {
labelMapName := requestType.Name() + "_Labels"
functionName := requestType.Name() + "_Fn"
labelRegistrationMapSection += fmt.Sprintf(mapDeclarationFormatString,
diff --git a/android/config.go b/android/config.go
index 57eff92..4a7e0d9 100644
--- a/android/config.go
+++ b/android/config.go
@@ -350,18 +350,19 @@
config := &config{
productVariables: productVariables{
- DeviceName: stringPtr("test_device"),
- Platform_sdk_version: intPtr(30),
- Platform_sdk_codename: stringPtr("S"),
- Platform_version_active_codenames: []string{"S", "Tiramisu"},
- DeviceSystemSdkVersions: []string{"14", "15"},
- Platform_systemsdk_versions: []string{"29", "30"},
- AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
- AAPTPreferredConfig: stringPtr("xhdpi"),
- AAPTCharacteristics: stringPtr("nosdcard"),
- AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"},
- UncompressPrivAppDex: boolPtr(true),
- ShippingApiLevel: stringPtr("30"),
+ DeviceName: stringPtr("test_device"),
+ Platform_sdk_version: intPtr(30),
+ Platform_sdk_codename: stringPtr("S"),
+ Platform_base_sdk_extension_version: intPtr(1),
+ Platform_version_active_codenames: []string{"S", "Tiramisu"},
+ DeviceSystemSdkVersions: []string{"14", "15"},
+ Platform_systemsdk_versions: []string{"29", "30"},
+ AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
+ AAPTPreferredConfig: stringPtr("xhdpi"),
+ AAPTCharacteristics: stringPtr("nosdcard"),
+ AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"},
+ UncompressPrivAppDex: boolPtr(true),
+ ShippingApiLevel: stringPtr("30"),
},
outDir: buildDir,
@@ -742,6 +743,14 @@
return String(c.productVariables.Platform_sdk_codename)
}
+func (c *config) PlatformSdkExtensionVersion() int {
+ return *c.productVariables.Platform_sdk_extension_version
+}
+
+func (c *config) PlatformBaseSdkExtensionVersion() int {
+ return *c.productVariables.Platform_base_sdk_extension_version
+}
+
func (c *config) PlatformSecurityPatch() string {
return String(c.productVariables.Platform_security_patch)
}
diff --git a/android/filegroup.go b/android/filegroup.go
index c932ffa..d2ff97d 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -18,6 +18,8 @@
"strings"
"android/soong/bazel"
+
+ "github.com/google/blueprint"
)
func init() {
@@ -28,6 +30,11 @@
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
diff --git a/android/module_test.go b/android/module_test.go
index a1bab6d..1dcddf7 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -15,12 +15,9 @@
package android
import (
- "bytes"
"path/filepath"
"runtime"
"testing"
-
- mkparser "android/soong/androidmk/parser"
)
func TestSrcIsModule(t *testing.T) {
@@ -475,21 +472,10 @@
prepareForModuleTests,
PrepareForTestWithArchMutator,
FixtureModifyConfig(SetKatiEnabledForTests),
- FixtureRegisterWithContext(func(ctx RegistrationContext) {
- ctx.RegisterSingletonType("makevars", makeVarsSingletonFunc)
- }),
+ PrepareForTestWithMakevars,
).RunTestWithBp(t, bp)
- installs := result.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).installsForTesting
- buf := bytes.NewBuffer(append([]byte(nil), installs...))
- parser := mkparser.NewParser("makevars", buf)
-
- nodes, errs := parser.Parse()
- if len(errs) > 0 {
- t.Fatalf("error parsing install rules: %s", errs[0])
- }
-
- rules := parseMkRules(t, result.Config, nodes)
+ rules := result.InstallMakeRulesForTesting(t)
module := func(name string, host bool) TestingModule {
variant := "android_common"
@@ -501,121 +487,78 @@
outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
- ruleForOutput := func(output string) installMakeRule {
+ ruleForOutput := func(output string) InstallMakeRule {
for _, rule := range rules {
- if rule.target == output {
+ if rule.Target == output {
return rule
}
}
t.Fatalf("no make install rule for %s", output)
- return installMakeRule{}
+ return InstallMakeRule{}
}
- installRule := func(name string) installMakeRule {
+ installRule := func(name string) InstallMakeRule {
return ruleForOutput(filepath.Join("out/target/product/test_device/system", name))
}
- symlinkRule := func(name string) installMakeRule {
+ symlinkRule := func(name string) InstallMakeRule {
return ruleForOutput(filepath.Join("out/target/product/test_device/system/symlinks", name))
}
hostOutputRule := func(name string) TestingBuildParams { return module(name, true).Output(name) }
- hostInstallRule := func(name string) installMakeRule {
+ hostInstallRule := func(name string) InstallMakeRule {
return ruleForOutput(filepath.Join("out/host/linux-x86", name))
}
- hostSymlinkRule := func(name string) installMakeRule {
+ hostSymlinkRule := func(name string) InstallMakeRule {
return ruleForOutput(filepath.Join("out/host/linux-x86/symlinks", name))
}
- assertDeps := func(rule installMakeRule, deps ...string) {
+ assertDeps := func(rule InstallMakeRule, deps ...string) {
t.Helper()
- AssertArrayString(t, "expected inputs", deps, rule.deps)
+ AssertArrayString(t, "expected inputs", deps, rule.Deps)
}
- assertOrderOnlys := func(rule installMakeRule, orderonlys ...string) {
+ assertOrderOnlys := func(rule InstallMakeRule, orderonlys ...string) {
t.Helper()
- AssertArrayString(t, "expected orderonly dependencies", orderonlys, rule.orderOnlyDeps)
+ AssertArrayString(t, "expected orderonly dependencies", orderonlys, rule.OrderOnlyDeps)
}
// Check host install rule dependencies
assertDeps(hostInstallRule("foo"),
hostOutputRule("foo").Output.String(),
- hostInstallRule("bar").target,
- hostSymlinkRule("bar").target,
- hostInstallRule("baz").target,
- hostSymlinkRule("baz").target,
- hostInstallRule("qux").target,
- hostSymlinkRule("qux").target,
+ hostInstallRule("bar").Target,
+ hostSymlinkRule("bar").Target,
+ hostInstallRule("baz").Target,
+ hostSymlinkRule("baz").Target,
+ hostInstallRule("qux").Target,
+ hostSymlinkRule("qux").Target,
)
assertOrderOnlys(hostInstallRule("foo"))
// Check host symlink rule dependencies. Host symlinks must use a normal dependency, not an
// order-only dependency, so that the tool gets updated when the symlink is depended on.
- assertDeps(hostSymlinkRule("foo"), hostInstallRule("foo").target)
+ assertDeps(hostSymlinkRule("foo"), hostInstallRule("foo").Target)
assertOrderOnlys(hostSymlinkRule("foo"))
// Check device install rule dependencies
assertDeps(installRule("foo"), outputRule("foo").Output.String())
assertOrderOnlys(installRule("foo"),
- installRule("bar").target,
- symlinkRule("bar").target,
- installRule("baz").target,
- symlinkRule("baz").target,
- installRule("qux").target,
- symlinkRule("qux").target,
+ installRule("bar").Target,
+ symlinkRule("bar").Target,
+ installRule("baz").Target,
+ symlinkRule("baz").Target,
+ installRule("qux").Target,
+ symlinkRule("qux").Target,
)
// Check device symlink rule dependencies. Device symlinks could use an order-only dependency,
// but the current implementation uses a normal dependency.
- assertDeps(symlinkRule("foo"), installRule("foo").target)
+ assertDeps(symlinkRule("foo"), installRule("foo").Target)
assertOrderOnlys(symlinkRule("foo"))
}
-type installMakeRule struct {
- target string
- deps []string
- orderOnlyDeps []string
-}
-
-func parseMkRules(t *testing.T, config Config, nodes []mkparser.Node) []installMakeRule {
- var rules []installMakeRule
- for _, node := range nodes {
- if mkParserRule, ok := node.(*mkparser.Rule); ok {
- var rule installMakeRule
-
- if targets := mkParserRule.Target.Words(); len(targets) == 0 {
- t.Fatalf("no targets for rule %s", mkParserRule.Dump())
- } else if len(targets) > 1 {
- t.Fatalf("unsupported multiple targets for rule %s", mkParserRule.Dump())
- } else if !targets[0].Const() {
- t.Fatalf("unsupported non-const target for rule %s", mkParserRule.Dump())
- } else {
- rule.target = normalizeStringRelativeToTop(config, targets[0].Value(nil))
- }
-
- prereqList := &rule.deps
- for _, prereq := range mkParserRule.Prerequisites.Words() {
- if !prereq.Const() {
- t.Fatalf("unsupported non-const prerequisite for rule %s", mkParserRule.Dump())
- }
-
- if prereq.Value(nil) == "|" {
- prereqList = &rule.orderOnlyDeps
- continue
- }
-
- *prereqList = append(*prereqList, normalizeStringRelativeToTop(config, prereq.Value(nil)))
- }
-
- rules = append(rules, rule)
- }
- }
-
- return rules
-}
-
type PropsTestModuleEmbedded struct {
Embedded_prop *string
}
diff --git a/android/proto.go b/android/proto.go
index f466261..c3759f8 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -16,6 +16,7 @@
import (
"android/soong/bazel"
+ "regexp"
"strings"
"github.com/google/blueprint"
@@ -26,6 +27,14 @@
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 @@
// 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 @@
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
+}
diff --git a/android/singleton_module_test.go b/android/singleton_module_test.go
index eb5554c..9d98478 100644
--- a/android/singleton_module_test.go
+++ b/android/singleton_module_test.go
@@ -46,8 +46,8 @@
PrepareForTestWithAndroidMk,
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterSingletonModuleType("test_singleton_module", testSingletonModuleFactory)
- ctx.RegisterSingletonType("makevars", makeVarsSingletonFunc)
}),
+ PrepareForTestWithMakevars,
)
func TestSingletonModule(t *testing.T) {
diff --git a/android/testing.go b/android/testing.go
index 39864e1..a9632e9 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -15,6 +15,7 @@
package android
import (
+ "bytes"
"fmt"
"path/filepath"
"regexp"
@@ -23,6 +24,8 @@
"sync"
"testing"
+ mkparser "android/soong/androidmk/parser"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -115,6 +118,10 @@
ctx.PreArchMutators(RegisterNamespaceMutator)
})
+var PrepareForTestWithMakevars = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterSingletonType("makevars", makeVarsSingletonFunc)
+})
+
// Test fixture preparer that will register most java build components.
//
// Singletons and mutators should only be added here if they are needed for a majority of java
@@ -602,6 +609,62 @@
"\nall singletons: %v", name, allSingletonNames))
}
+type InstallMakeRule struct {
+ Target string
+ Deps []string
+ OrderOnlyDeps []string
+}
+
+func parseMkRules(t *testing.T, config Config, nodes []mkparser.Node) []InstallMakeRule {
+ var rules []InstallMakeRule
+ for _, node := range nodes {
+ if mkParserRule, ok := node.(*mkparser.Rule); ok {
+ var rule InstallMakeRule
+
+ if targets := mkParserRule.Target.Words(); len(targets) == 0 {
+ t.Fatalf("no targets for rule %s", mkParserRule.Dump())
+ } else if len(targets) > 1 {
+ t.Fatalf("unsupported multiple targets for rule %s", mkParserRule.Dump())
+ } else if !targets[0].Const() {
+ t.Fatalf("unsupported non-const target for rule %s", mkParserRule.Dump())
+ } else {
+ rule.Target = normalizeStringRelativeToTop(config, targets[0].Value(nil))
+ }
+
+ prereqList := &rule.Deps
+ for _, prereq := range mkParserRule.Prerequisites.Words() {
+ if !prereq.Const() {
+ t.Fatalf("unsupported non-const prerequisite for rule %s", mkParserRule.Dump())
+ }
+
+ if prereq.Value(nil) == "|" {
+ prereqList = &rule.OrderOnlyDeps
+ continue
+ }
+
+ *prereqList = append(*prereqList, normalizeStringRelativeToTop(config, prereq.Value(nil)))
+ }
+
+ rules = append(rules, rule)
+ }
+ }
+
+ return rules
+}
+
+func (ctx *TestContext) InstallMakeRulesForTesting(t *testing.T) []InstallMakeRule {
+ installs := ctx.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).installsForTesting
+ buf := bytes.NewBuffer(append([]byte(nil), installs...))
+ parser := mkparser.NewParser("makevars", buf)
+
+ nodes, errs := parser.Parse()
+ if len(errs) > 0 {
+ t.Fatalf("error parsing install rules: %s", errs[0])
+ }
+
+ return parseMkRules(t, ctx.config, nodes)
+}
+
func (ctx *TestContext) Config() Config {
return ctx.config
}
diff --git a/android/variable.go b/android/variable.go
index 59ae919..627d9bd 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -191,6 +191,7 @@
Platform_sdk_version_or_codename *string `json:",omitempty"`
Platform_sdk_final *bool `json:",omitempty"`
Platform_sdk_extension_version *int `json:",omitempty"`
+ Platform_base_sdk_extension_version *int `json:",omitempty"`
Platform_version_active_codenames []string `json:",omitempty"`
Platform_vndk_version *string `json:",omitempty"`
Platform_systemsdk_versions []string `json:",omitempty"`
diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go
new file mode 100644
index 0000000..93b0677
--- /dev/null
+++ b/bp2build/java_proto_conversion_test.go
@@ -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"]`,
+ }),
+ },
+ })
+}
diff --git a/build_test.bash b/build_test.bash
index b6d00e2..1dc6660 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -25,7 +25,9 @@
# Products that are broken or otherwise don't work with multiproduct_kati
SKIPPED_PRODUCTS=(
+ # Both of these products are for soong-only builds, and will fail the kati stage.
mainline_sdk
+ ndk
)
# To track how long we took to startup. %N isn't supported on Darwin, but
diff --git a/cc/afdo.go b/cc/afdo.go
index d7cce77..c888213 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -32,7 +32,7 @@
var afdoProfileProjectsConfigKey = android.NewOnceKey("AfdoProfileProjects")
-const afdoCFlagsFormat = "-fprofile-sample-accurate -fprofile-sample-use=%s"
+const afdoCFlagsFormat = "-funique-internal-linkage-names -fprofile-sample-accurate -fprofile-sample-use=%s"
func getAfdoProfileProjects(config android.DeviceConfig) []string {
return config.OnceStringSlice(afdoProfileProjectsConfigKey, func() []string {
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 42fc0e4..379d6f2 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -16,7 +16,6 @@
import (
"fmt"
"path/filepath"
- "regexp"
"strings"
"android/soong/android"
@@ -34,12 +33,6 @@
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 @@
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.
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index d789cde..0da51cb 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -37,10 +37,10 @@
"": []string{
"-march=x86-64",
},
+
"broadwell": []string{
"-march=broadwell",
},
-
"haswell": []string{
"-march=core-avx2",
},
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 339a16d..5980319 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -16,6 +16,7 @@
import (
"path/filepath"
+ "strings"
"android/soong/android"
"android/soong/bazel"
@@ -188,6 +189,16 @@
TableOfContents: p.tocFile,
})
+ // TODO(b/220898484): Mainline module sdk prebuilts of stub libraries use a stub
+ // library as their source and must not be installed, but libclang_rt.* libraries
+ // have stubs because they are LLNDK libraries, but use an implementation library
+ // as their source and need to be installed. This discrepancy should be resolved
+ // without the prefix hack below.
+ if p.hasStubsVariants() && !p.buildStubs() && !ctx.Host() &&
+ !strings.HasPrefix(ctx.baseModuleName(), "libclang_rt.") {
+ ctx.Module().MakeUninstallable()
+ }
+
return outputFile
}
}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 94f75fe..901f458 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -20,6 +20,7 @@
"android/soong/android"
"android/soong/bazel/cquery"
+
"github.com/google/blueprint"
)
@@ -29,6 +30,7 @@
)
func testPrebuilt(t *testing.T, bp string, fs android.MockFS, handlers ...android.FixturePreparer) *android.TestContext {
+ t.Helper()
result := android.GroupFixturePreparers(
prepareForPrebuiltTest,
fs.AddToFixture(),
@@ -449,3 +451,72 @@
expectedOutputFiles := []string{pathPrefix + "foo.so"}
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
}
+
+func TestPrebuiltStubNoinstall(t *testing.T) {
+ testFunc := func(t *testing.T, bp string) {
+ result := android.GroupFixturePreparers(
+ prepareForPrebuiltTest,
+ android.PrepareForTestWithMakevars,
+ ).RunTestWithBp(t, bp)
+
+ installRules := result.InstallMakeRulesForTesting(t)
+ var installedlibRule *android.InstallMakeRule
+ for i, rule := range installRules {
+ if rule.Target == "out/target/product/test_device/system/lib/installedlib.so" {
+ if installedlibRule != nil {
+ t.Errorf("Duplicate install rules for %s", rule.Target)
+ }
+ installedlibRule = &installRules[i]
+ }
+ }
+ if installedlibRule == nil {
+ t.Errorf("No install rule found for installedlib")
+ return
+ }
+
+ android.AssertStringListDoesNotContain(t,
+ "installedlib has install dependency on stub",
+ installedlibRule.Deps,
+ "out/target/product/test_device/system/lib/stublib.so")
+ android.AssertStringListDoesNotContain(t,
+ "installedlib has order-only install dependency on stub",
+ installedlibRule.OrderOnlyDeps,
+ "out/target/product/test_device/system/lib/stublib.so")
+ }
+
+ const prebuiltStublibBp = `
+ cc_prebuilt_library {
+ name: "stublib",
+ prefer: true,
+ srcs: ["foo.so"],
+ stubs: {
+ versions: ["1"],
+ },
+ }
+ `
+
+ const installedlibBp = `
+ cc_library {
+ name: "installedlib",
+ shared_libs: ["stublib"],
+ }
+ `
+
+ t.Run("prebuilt without source", func(t *testing.T) {
+ testFunc(t, prebuiltStublibBp+installedlibBp)
+ })
+
+ const disabledSourceStublibBp = `
+ cc_library {
+ name: "stublib",
+ enabled: false,
+ stubs: {
+ versions: ["1"],
+ },
+ }
+ `
+
+ t.Run("prebuilt with disabled source", func(t *testing.T) {
+ testFunc(t, disabledSourceStublibBp+prebuiltStublibBp+installedlibBp)
+ })
+}
diff --git a/cc/proto.go b/cc/proto.go
index 3cf1453..8e6d5ed 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -177,7 +177,7 @@
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
}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 8282426..2ddd70e 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -496,7 +496,7 @@
}
return paths[0], nil
} else {
- return reportError("unknown location label %q", label)
+ return reportError("unknown location label %q is not in srcs, out, tools or tool_files.", label)
}
} else if strings.HasPrefix(name, "locations ") {
label := strings.TrimSpace(strings.TrimPrefix(name, "locations "))
@@ -507,7 +507,7 @@
}
return strings.Join(paths, " "), nil
} else {
- return reportError("unknown locations label %q", label)
+ return reportError("unknown locations label %q is not in srcs, out, tools or tool_files.", label)
}
} else {
return reportError("unknown variable '$(%s)'", name)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 04c97fd..1b5cef2 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -341,7 +341,7 @@
out: ["out"],
cmd: "echo foo > $(location missing)",
`,
- err: `unknown location label "missing"`,
+ err: `unknown location label "missing" is not in srcs, out, tools or tool_files.`,
},
{
name: "error locations",
@@ -349,7 +349,7 @@
out: ["out"],
cmd: "echo foo > $(locations missing)",
`,
- err: `unknown locations label "missing"`,
+ err: `unknown locations label "missing" is not in srcs, out, tools or tool_files`,
},
{
name: "error location no files",
diff --git a/java/droidstubs.go b/java/droidstubs.go
index f9dcfd6..5dc7bc9 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -334,11 +334,7 @@
// TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
cmd.FlagWithArg("--hide ", "HiddenTypedefConstant").
FlagWithArg("--hide ", "SuperfluousPrefix").
- FlagWithArg("--hide ", "AnnotationExtraction").
- // (b/217545629)
- FlagWithArg("--hide ", "ChangedThrows").
- // (b/217552813)
- FlagWithArg("--hide ", "ChangedAbstract")
+ FlagWithArg("--hide ", "AnnotationExtraction")
}
}
@@ -476,7 +472,8 @@
Flag("--quiet").
Flag("--format=v2").
FlagWithArg("--repeat-errors-max ", "10").
- FlagWithArg("--hide ", "UnresolvedImport")
+ FlagWithArg("--hide ", "UnresolvedImport").
+ FlagWithArg("--hide ", "InvalidNullability")
return cmd
}
diff --git a/java/java.go b/java/java.go
index e55f045..d0f0abc 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2013,8 +2013,16 @@
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 @@
//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
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index c67e2bd..44650a6 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "path"
"strconv"
"strings"
@@ -37,6 +38,11 @@
// list of api version directories
Api_dirs []string
+ // Directory containing finalized api txt files for extension versions.
+ // Extension versions higher than the base sdk extension version will
+ // be assumed to be finalized later than all Api_dirs.
+ Extensions_dir *string
+
// The next API directory can optionally point to a directory where
// files incompatibility-tracking files are stored for the current
// "in progress" API. Each module present in one of the api_dirs will have
@@ -60,36 +66,45 @@
// no need to implement
}
-func parseJarPath(path string) (module string, apiver string, scope string) {
- elements := strings.Split(path, "/")
+// parsePrebuiltPath parses the relevant variables out of a variety of paths, e.g.
+// <version>/<scope>/<module>.jar
+// <version>/<scope>/api/<module>.txt
+// extensions/<version>/<scope>/<module>.jar
+// extensions/<version>/<scope>/api/<module>.txt
+func parsePrebuiltPath(ctx android.LoadHookContext, p string) (module string, version string, scope string) {
+ elements := strings.Split(p, "/")
- apiver = elements[0]
- scope = elements[1]
-
- module = strings.TrimSuffix(elements[2], ".jar")
- return
-}
-
-func parseApiFilePath(ctx android.LoadHookContext, path string) (module string, apiver string, scope string) {
- elements := strings.Split(path, "/")
- apiver = elements[0]
-
- scope = elements[1]
- if scope != "public" && scope != "system" && scope != "test" && scope != "module-lib" && scope != "system-server" {
- ctx.ModuleErrorf("invalid scope %q found in path: %q", scope, path)
+ scopeIdx := len(elements) - 2
+ if elements[scopeIdx] == "api" {
+ scopeIdx--
+ }
+ scope = elements[scopeIdx]
+ if scope != "core" && scope != "public" && scope != "system" && scope != "test" && scope != "module-lib" && scope != "system-server" {
+ ctx.ModuleErrorf("invalid scope %q found in path: %q", scope, p)
return
}
+ version = elements[scopeIdx-1]
- // elements[2] is string literal "api". skipping.
- module = strings.TrimSuffix(elements[3], ".txt")
+ module = strings.TrimSuffix(path.Base(p), path.Ext(p))
return
}
-func prebuiltApiModuleName(mctx android.LoadHookContext, module string, scope string, apiver string) string {
- return mctx.ModuleName() + "_" + scope + "_" + apiver + "_" + module
+// parseFinalizedPrebuiltPath is like parsePrebuiltPath, but verifies the version is numeric (a finalized version).
+func parseFinalizedPrebuiltPath(ctx android.LoadHookContext, p string) (module string, version int, scope string) {
+ module, v, scope := parsePrebuiltPath(ctx, p)
+ version, err := strconv.Atoi(v)
+ if err != nil {
+ ctx.ModuleErrorf("Found finalized API files in non-numeric dir '%v'", v)
+ return
+ }
+ return
}
-func createImport(mctx android.LoadHookContext, module, scope, apiver, path, sdkVersion string, compileDex bool) {
+func prebuiltApiModuleName(mctx android.LoadHookContext, module, scope, version string) string {
+ return fmt.Sprintf("%s_%s_%s_%s", mctx.ModuleName(), scope, version, module)
+}
+
+func createImport(mctx android.LoadHookContext, module, scope, version, path, sdkVersion string, compileDex bool) {
props := struct {
Name *string
Jars []string
@@ -97,7 +112,7 @@
Installable *bool
Compile_dex *bool
}{}
- props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, apiver))
+ props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, version))
props.Jars = append(props.Jars, path)
props.Sdk_version = proptools.StringPtr(sdkVersion)
props.Installable = proptools.BoolPtr(false)
@@ -132,111 +147,125 @@
mctx.CreateModule(genrule.GenRuleFactory, &props)
}
-func getPrebuiltFiles(mctx android.LoadHookContext, p *prebuiltApis, name string) []string {
+// globApiDirs collects all the files in all api_dirs and all scopes that match the given glob, e.g. '*.jar' or 'api/*.txt'.
+// <api-dir>/<scope>/<glob> for all api-dir and scope.
+func globApiDirs(mctx android.LoadHookContext, p *prebuiltApis, api_dir_glob string) []string {
var files []string
for _, apiver := range p.properties.Api_dirs {
- files = append(files, getPrebuiltFilesInSubdir(mctx, apiver, name)...)
+ files = append(files, globScopeDir(mctx, apiver, api_dir_glob)...)
}
return files
}
-func getPrebuiltFilesInSubdir(mctx android.LoadHookContext, subdir string, name string) []string {
+// globExtensionDirs collects all the files under the extension dir (for all versions and scopes) that match the given glob
+// <extension-dir>/<version>/<scope>/<glob> for all version and scope.
+func globExtensionDirs(mctx android.LoadHookContext, p *prebuiltApis, extension_dir_glob string) []string {
+ // <extensions-dir>/<num>/<extension-dir-glob>
+ return globScopeDir(mctx, *p.properties.Extensions_dir+"/*", extension_dir_glob)
+}
+
+// globScopeDir collects all the files in the given subdir across all scopes that match the given glob, e.g. '*.jar' or 'api/*.txt'.
+// <subdir>/<scope>/<glob> for all scope.
+func globScopeDir(mctx android.LoadHookContext, subdir string, subdir_glob string) []string {
var files []string
dir := mctx.ModuleDir() + "/" + subdir
for _, scope := range []string{"public", "system", "test", "core", "module-lib", "system-server"} {
- glob := fmt.Sprintf("%s/%s/%s", dir, scope, name)
+ glob := fmt.Sprintf("%s/%s/%s", dir, scope, subdir_glob)
vfiles, err := mctx.GlobWithDeps(glob, nil)
if err != nil {
- mctx.ModuleErrorf("failed to glob %s files under %q: %s", name, dir+"/"+scope, err)
+ mctx.ModuleErrorf("failed to glob %s files under %q: %s", subdir_glob, dir+"/"+scope, err)
}
files = append(files, vfiles...)
}
+ for i, f := range files {
+ files[i] = strings.TrimPrefix(f, mctx.ModuleDir()+"/")
+ }
return files
}
func prebuiltSdkStubs(mctx android.LoadHookContext, p *prebuiltApis) {
- mydir := mctx.ModuleDir() + "/"
// <apiver>/<scope>/<module>.jar
- files := getPrebuiltFiles(mctx, p, "*.jar")
+ files := globApiDirs(mctx, p, "*.jar")
sdkVersion := proptools.StringDefault(p.properties.Imports_sdk_version, "current")
compileDex := proptools.BoolDefault(p.properties.Imports_compile_dex, false)
for _, f := range files {
// create a Import module for each jar file
- localPath := strings.TrimPrefix(f, mydir)
- module, apiver, scope := parseJarPath(localPath)
- createImport(mctx, module, scope, apiver, localPath, sdkVersion, compileDex)
+ module, version, scope := parsePrebuiltPath(mctx, f)
+ createImport(mctx, module, scope, version, f, sdkVersion, compileDex)
if module == "core-for-system-modules" {
- createSystemModules(mctx, apiver, scope)
+ createSystemModules(mctx, version, scope)
}
}
}
-func createSystemModules(mctx android.LoadHookContext, apiver string, scope string) {
+func createSystemModules(mctx android.LoadHookContext, version, scope string) {
props := struct {
Name *string
Libs []string
}{}
- props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", scope, apiver))
- props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", scope, apiver))
+ props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", scope, version))
+ props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", scope, version))
mctx.CreateModule(systemModulesImportFactory, &props)
}
func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) {
- mydir := mctx.ModuleDir() + "/"
// <apiver>/<scope>/api/<module>.txt
- files := getPrebuiltFiles(mctx, p, "api/*.txt")
-
- if len(files) == 0 {
- mctx.ModuleErrorf("no api file found under %q", mydir)
- }
-
- // construct a map to find out the latest api file path
- // for each (<module>, <scope>) pair.
- type latestApiInfo struct {
- module string
- scope string
- version int
- path string
+ apiLevelFiles := globApiDirs(mctx, p, "api/*.txt")
+ if len(apiLevelFiles) == 0 {
+ mctx.ModuleErrorf("no api file found under %q", mctx.ModuleDir())
}
// Create modules for all (<module>, <scope, <version>) triplets,
- // and a "latest" module variant for each (<module>, <scope>) pair
apiModuleName := func(module, scope, version string) string {
return module + ".api." + scope + "." + version
}
- m := make(map[string]latestApiInfo)
- for _, f := range files {
- localPath := strings.TrimPrefix(f, mydir)
- module, apiver, scope := parseApiFilePath(mctx, localPath)
- createApiModule(mctx, apiModuleName(module, scope, apiver), localPath)
+ for _, f := range apiLevelFiles {
+ module, version, scope := parseFinalizedPrebuiltPath(mctx, f)
+ createApiModule(mctx, apiModuleName(module, scope, strconv.Itoa(version)), f)
+ }
- version, err := strconv.Atoi(apiver)
- if err != nil {
- mctx.ModuleErrorf("Found finalized API files in non-numeric dir %v", apiver)
- return
- }
+ // Figure out the latest version of each module/scope
+ type latestApiInfo struct {
+ module, scope, path string
+ version int
+ }
- // Track latest version of each module/scope, except for incompatibilities
- if !strings.HasSuffix(module, "incompatibilities") {
+ getLatest := func(files []string) map[string]latestApiInfo {
+ m := make(map[string]latestApiInfo)
+ for _, f := range files {
+ module, version, scope := parseFinalizedPrebuiltPath(mctx, f)
+ if strings.HasSuffix(module, "incompatibilities") {
+ continue
+ }
key := module + "." + scope
- info, ok := m[key]
- if !ok {
- m[key] = latestApiInfo{module, scope, version, localPath}
- } else if version > info.version {
- info.version = version
- info.path = localPath
- m[key] = info
+ info, exists := m[key]
+ if !exists || version > info.version {
+ m[key] = latestApiInfo{module, scope, f, version}
+ }
+ }
+ return m
+ }
+
+ latest := getLatest(apiLevelFiles)
+ if p.properties.Extensions_dir != nil {
+ extensionApiFiles := globExtensionDirs(mctx, p, "api/*.txt")
+ for k, v := range getLatest(extensionApiFiles) {
+ if v.version > mctx.Config().PlatformBaseSdkExtensionVersion() {
+ if _, exists := latest[k]; !exists {
+ mctx.ModuleErrorf("Module %v finalized for extension %d but never during an API level; likely error", v.module, v.version)
+ }
+ latest[k] = v
}
}
}
// Sort the keys in order to make build.ninja stable
- for _, k := range android.SortedStringKeys(m) {
- info := m[k]
+ for _, k := range android.SortedStringKeys(latest) {
+ info := latest[k]
name := apiModuleName(info.module, info.scope, "latest")
createApiModule(mctx, name, info.path)
}
@@ -244,21 +273,20 @@
// Create incompatibilities tracking files for all modules, if we have a "next" api.
incompatibilities := make(map[string]bool)
if nextApiDir := String(p.properties.Next_api_dir); nextApiDir != "" {
- files := getPrebuiltFilesInSubdir(mctx, nextApiDir, "api/*incompatibilities.txt")
+ files := globScopeDir(mctx, nextApiDir, "api/*incompatibilities.txt")
for _, f := range files {
- localPath := strings.TrimPrefix(f, mydir)
- filename, _, scope := parseApiFilePath(mctx, localPath)
+ filename, _, scope := parsePrebuiltPath(mctx, f)
referencedModule := strings.TrimSuffix(filename, "-incompatibilities")
- createApiModule(mctx, apiModuleName(referencedModule+"-incompatibilities", scope, "latest"), localPath)
+ createApiModule(mctx, apiModuleName(referencedModule+"-incompatibilities", scope, "latest"), f)
incompatibilities[referencedModule+"."+scope] = true
}
}
// Create empty incompatibilities files for remaining modules
- for _, k := range android.SortedStringKeys(m) {
+ for _, k := range android.SortedStringKeys(latest) {
if _, ok := incompatibilities[k]; !ok {
- createEmptyFile(mctx, apiModuleName(m[k].module+"-incompatibilities", m[k].scope, "latest"))
+ createEmptyFile(mctx, apiModuleName(latest[k].module+"-incompatibilities", latest[k].scope, "latest"))
}
}
}
diff --git a/java/prebuilt_apis_test.go b/java/prebuilt_apis_test.go
index 79f4225..75422ad 100644
--- a/java/prebuilt_apis_test.go
+++ b/java/prebuilt_apis_test.go
@@ -20,9 +20,14 @@
"testing"
"android/soong/android"
+
"github.com/google/blueprint"
)
+func intPtr(v int) *int {
+ return &v
+}
+
func TestPrebuiltApis_SystemModulesCreation(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForJavaTest,
@@ -54,3 +59,34 @@
sort.Strings(expected)
android.AssertArrayString(t, "sdk system modules", expected, sdkSystemModules)
}
+
+func TestPrebuiltApis_WithExtensions(t *testing.T) {
+ runTestWithBaseExtensionLevel := func(v int) (foo_input string, bar_input string) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_base_sdk_extension_version = intPtr(v)
+ }),
+ FixtureWithPrebuiltApisAndExtensions(map[string][]string{
+ "31": {"foo"},
+ "32": {"foo", "bar"},
+ "current": {"foo", "bar"},
+ }, map[string][]string{
+ "1": {"foo"},
+ "2": {"foo", "bar"},
+ }),
+ ).RunTest(t)
+ foo_input = result.ModuleForTests("foo.api.public.latest", "").Rule("generator").Implicits[0].String()
+ bar_input = result.ModuleForTests("bar.api.public.latest", "").Rule("generator").Implicits[0].String()
+ return
+ }
+ // Here, the base extension level is 1, so extension level 2 is the latest
+ foo_input, bar_input := runTestWithBaseExtensionLevel(1)
+ android.AssertStringEquals(t, "Expected latest = extension level 2", "prebuilts/sdk/extensions/2/public/api/foo.txt", foo_input)
+ android.AssertStringEquals(t, "Expected latest = extension level 2", "prebuilts/sdk/extensions/2/public/api/bar.txt", bar_input)
+
+ // Here, the base extension level is 2, so 2 is not later than 32.
+ foo_input, bar_input = runTestWithBaseExtensionLevel(2)
+ android.AssertStringEquals(t, "Expected latest = api level 32", "prebuilts/sdk/32/public/api/foo.txt", foo_input)
+ android.AssertStringEquals(t, "Expected latest = api level 32", "prebuilts/sdk/32/public/api/bar.txt", bar_input)
+}
diff --git a/java/proto.go b/java/proto.go
index 8d23803..5ba486f 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -19,6 +19,13 @@
"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 @@
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}
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index e794a48..bfdfffc 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1511,15 +1511,15 @@
}
droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...)
disabledWarnings := []string{
- "MissingPermission",
"BroadcastBehavior",
- "HiddenSuperclass",
"DeprecationMismatch",
- "UnavailableSymbol",
- "SdkConstant",
+ "HiddenSuperclass",
"HiddenTypeParameter",
+ "MissingPermission",
+ "SdkConstant",
"Todo",
"Typo",
+ "UnavailableSymbol",
}
droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
diff --git a/java/testing.go b/java/testing.go
index 6c49bc8..82aa29b 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -146,6 +146,10 @@
// This defines a file in the mock file system in a predefined location (prebuilts/sdk/Android.bp)
// and so only one instance of this can be used in each fixture.
func FixtureWithPrebuiltApis(release2Modules map[string][]string) android.FixturePreparer {
+ return FixtureWithPrebuiltApisAndExtensions(release2Modules, nil)
+}
+
+func FixtureWithPrebuiltApisAndExtensions(apiLevel2Modules map[string][]string, extensionLevel2Modules map[string][]string) android.FixturePreparer {
mockFS := android.MockFS{}
path := "prebuilts/sdk/Android.bp"
@@ -153,14 +157,20 @@
prebuilt_apis {
name: "sdk",
api_dirs: ["%s"],
+ extensions_dir: "extensions",
imports_sdk_version: "none",
imports_compile_dex: true,
}
- `, strings.Join(android.SortedStringKeys(release2Modules), `", "`))
+ `, strings.Join(android.SortedStringKeys(apiLevel2Modules), `", "`))
- for release, modules := range release2Modules {
+ for release, modules := range apiLevel2Modules {
mockFS.Merge(prebuiltApisFilesForModules([]string{release}, modules))
}
+ if extensionLevel2Modules != nil {
+ for release, modules := range extensionLevel2Modules {
+ mockFS.Merge(prebuiltExtensionApiFiles([]string{release}, modules))
+ }
+ }
return android.GroupFixturePreparers(
android.FixtureAddTextFile(path, bp),
android.FixtureMergeMockFs(mockFS),
@@ -198,6 +208,19 @@
return fs
}
+func prebuiltExtensionApiFiles(extensionLevels []string, modules []string) map[string][]byte {
+ fs := make(map[string][]byte)
+ for _, level := range extensionLevels {
+ for _, sdkKind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkModule, android.SdkSystemServer} {
+ for _, lib := range modules {
+ fs[fmt.Sprintf("prebuilts/sdk/extensions/%s/%s/api/%s.txt", level, sdkKind, lib)] = nil
+ fs[fmt.Sprintf("prebuilts/sdk/extensions/%s/%s/api/%s-removed.txt", level, sdkKind, lib)] = nil
+ }
+ }
+ }
+ return fs
+}
+
// FixtureConfigureBootJars configures the boot jars in both the dexpreopt.GlobalConfig and
// Config.productVariables structs. As a side effect that enables dexpreopt.
func FixtureConfigureBootJars(bootJars ...string) android.FixturePreparer {
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index 4783037..b57963b 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -19,54 +19,9 @@
exit 1
fi
-TOP=$(pwd)
-
-source build/envsetup.sh
-PLATFORM_SDK_VERSION=$(get_build_var PLATFORM_SDK_VERSION)
-PLATFORM_VERSION_ALL_CODENAMES=$(get_build_var PLATFORM_VERSION_ALL_CODENAMES)
-
-# PLATFORM_VERSION_ALL_CODENAMES is a comma separated list like O,P. We need to
-# turn this into ["O","P"].
-PLATFORM_VERSION_ALL_CODENAMES=${PLATFORM_VERSION_ALL_CODENAMES/,/'","'}
-PLATFORM_VERSION_ALL_CODENAMES="[\"${PLATFORM_VERSION_ALL_CODENAMES}\"]"
-
-# Get the list of missing <uses-library> modules and convert it to a JSON array
-# (quote module names, add comma separator and wrap in brackets).
-MISSING_USES_LIBRARIES="$(get_build_var INTERNAL_PLATFORM_MISSING_USES_LIBRARIES)"
-MISSING_USES_LIBRARIES="[$(echo $MISSING_USES_LIBRARIES | sed -e 's/\([^ ]\+\)/\"\1\"/g' -e 's/[ ]\+/, /g')]"
-
-SOONG_OUT=${OUT_DIR}/soong
-SOONG_NDK_OUT=${OUT_DIR}/soong/ndk
-rm -rf ${SOONG_OUT}
-mkdir -p ${SOONG_OUT}
-
-# We only really need to set some of these variables, but soong won't merge this
-# with the defaults, so we need to write out all the defaults with our values
-# added.
-cat > ${SOONG_OUT}/soong.variables << EOF
-{
- "Platform_sdk_version": ${PLATFORM_SDK_VERSION},
- "Platform_version_active_codenames": ${PLATFORM_VERSION_ALL_CODENAMES},
-
- "DeviceName": "generic_arm64",
- "HostArch": "x86_64",
- "Malloc_not_svelte": false,
- "Safestack": false,
-
- "Ndk_abis": true,
-
- "VendorVars": {
- "art_module": {
- "source_build": "true"
- }
- },
-
- "MissingUsesLibraries": ${MISSING_USES_LIBRARIES}
-}
-EOF
-m --soong-only --skip-config ${SOONG_OUT}/ndk.timestamp
+TARGET_PRODUCT=ndk build/soong/soong_ui.bash --make-mode --soong-only ${OUT_DIR}/soong/ndk.timestamp
if [ -n "${DIST_DIR}" ]; then
mkdir -p ${DIST_DIR} || true
- tar cjf ${DIST_DIR}/ndk_platform.tar.bz2 -C ${SOONG_OUT} ndk
+ tar cjf ${DIST_DIR}/ndk_platform.tar.bz2 -C ${OUT_DIR}/soong ndk
fi
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 4190e84..d1beaba 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -149,6 +149,9 @@
// Only available for host sh_test modules.
Data_device_libs []string `android:"path,arch_variant"`
+ // Install the test into a folder named for the module in all test suites.
+ Per_testcase_directory *bool
+
// Test options.
Test_options TestOptions
}
@@ -464,6 +467,7 @@
if Bool(s.testProperties.Test_options.Unit_test) {
entries.SetBool("LOCAL_IS_UNIT_TEST", true)
}
+ entries.SetBoolIfTrue("LOCAL_COMPATIBILITY_PER_TESTCASE_DIRECTORY", Bool(s.testProperties.Per_testcase_directory))
},
},
}}