Merge "Generate boot zip file from prebuilt_bootclasspath_fragment"
diff --git a/android/mutator.go b/android/mutator.go
index 365bf29..819dd0f 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -19,6 +19,7 @@
"fmt"
"reflect"
"strings"
+ "sync"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -229,6 +230,9 @@
var bp2buildDepsMutators = []RegisterMutatorFunc{}
var bp2buildMutators = map[string]RegisterMutatorFunc{}
+// See http://b/192523357
+var bp2buildLock sync.Mutex
+
// RegisterBp2BuildMutator registers specially crafted mutators for
// converting Blueprint/Android modules into special modules that can
// be code-generated into Bazel BUILD targets.
@@ -238,6 +242,9 @@
f := func(ctx RegisterMutatorsContext) {
ctx.TopDown(moduleType, m)
}
+ // Use a lock to avoid a concurrent map write if RegisterBp2BuildMutator is called in parallel
+ bp2buildLock.Lock()
+ defer bp2buildLock.Unlock()
bp2buildMutators[moduleType] = f
}
diff --git a/apex/Android.bp b/apex/Android.bp
index 6269757..b9b5428 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -9,6 +9,7 @@
"blueprint",
"soong",
"soong-android",
+ "soong-bazel",
"soong-bpf",
"soong-cc",
"soong-filesystem",
diff --git a/apex/apex.go b/apex/apex.go
index baaf874..11df288 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -27,6 +27,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/bazel"
"android/soong/bpf"
"android/soong/cc"
prebuilt_etc "android/soong/etc"
@@ -53,6 +54,8 @@
ctx.PreArchMutators(registerPreArchMutators)
ctx.PreDepsMutators(RegisterPreDepsMutators)
ctx.PostDepsMutators(RegisterPostDepsMutators)
+
+ android.RegisterBp2BuildMutator("apex", ApexBundleBp2Build)
}
func registerPreArchMutators(ctx android.RegisterMutatorsContext) {
@@ -327,6 +330,7 @@
android.DefaultableModuleBase
android.OverridableModuleBase
android.SdkBase
+ android.BazelModuleBase
// Properties
properties apexBundleProperties
@@ -3178,3 +3182,63 @@
},
}
}
+
+// For Bazel / bp2build
+
+type bazelApexBundleAttributes struct {
+ Manifest bazel.LabelAttribute
+}
+
+type bazelApexBundle struct {
+ android.BazelTargetModuleBase
+ bazelApexBundleAttributes
+}
+
+func BazelApexBundleFactory() android.Module {
+ module := &bazelApexBundle{}
+ module.AddProperties(&module.bazelApexBundleAttributes)
+ android.InitBazelTargetModule(module)
+ return module
+}
+
+func ApexBundleBp2Build(ctx android.TopDownMutatorContext) {
+ module, ok := ctx.Module().(*apexBundle)
+ if !ok {
+ // Not an APEX bundle
+ return
+ }
+ if !module.ConvertWithBp2build(ctx) {
+ return
+ }
+ if ctx.ModuleType() != "apex" {
+ return
+ }
+
+ apexBundleBp2BuildInternal(ctx, module)
+}
+
+func apexBundleBp2BuildInternal(ctx android.TopDownMutatorContext, module *apexBundle) {
+ var manifestLabelAttribute bazel.LabelAttribute
+
+ manifestStringPtr := module.properties.Manifest
+ if module.properties.Manifest != nil {
+ manifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *manifestStringPtr))
+ }
+
+ attrs := &bazelApexBundleAttributes{
+ Manifest: manifestLabelAttribute,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "apex",
+ Bzl_load_location: "//build/bazel/rules:apex.bzl",
+ }
+
+ ctx.CreateBazelTargetModule(BazelApexBundleFactory, module.Name(), props, attrs)
+}
+
+func (m *bazelApexBundle) Name() string {
+ return m.BaseModuleName()
+}
+
+func (m *bazelApexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 0e6030e..dded14b 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -19,6 +19,7 @@
],
deps: [
"soong-android",
+ "soong-apex",
"soong-bazel",
"soong-cc",
"soong-cc-config",
@@ -27,6 +28,7 @@
"soong-sh",
],
testSrcs: [
+ "apex_conversion_test.go",
"build_conversion_test.go",
"bzl_conversion_test.go",
"cc_library_conversion_test.go",
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
new file mode 100644
index 0000000..fbf6fa2
--- /dev/null
+++ b/bp2build/apex_conversion_test.go
@@ -0,0 +1,48 @@
+// 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 (
+ "android/soong/android"
+ "android/soong/apex"
+ "testing"
+)
+
+func runApexTestCase(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ runBp2BuildTestCase(t, registerApexModuleTypes, tc)
+}
+
+func registerApexModuleTypes(ctx android.RegistrationContext) {
+}
+
+func TestApexBundleSimple(t *testing.T) {
+ runApexTestCase(t, bp2buildTestCase{
+ description: "apex - simple example",
+ moduleTypeUnderTest: "apex",
+ moduleTypeUnderTestFactory: apex.BundleFactory,
+ moduleTypeUnderTestBp2BuildMutator: apex.ApexBundleBp2Build,
+ filesystem: map[string]string{},
+ blueprint: `
+apex {
+ name: "apogee",
+ manifest: "manifest.json",
+}
+`,
+ expectedBazelTargets: []string{`apex(
+ name = "apogee",
+ manifest = "manifest.json",
+)`}})
+}
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index 57f75ea..8ede226 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -46,6 +46,7 @@
blueprint: `cc_object {
name: "foo",
local_include_dirs: ["include"],
+ default_shared_libs: [],
cflags: [
"-Wno-gcc-compat",
"-Wall",
@@ -83,6 +84,7 @@
moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
blueprint: `cc_object {
name: "foo",
+ default_shared_libs: [],
local_include_dirs: ["include"],
srcs: [
"a/b/*.h",
@@ -135,12 +137,14 @@
},
blueprint: `cc_object {
name: "foo",
+ default_shared_libs: [],
srcs: ["a/b/c.c"],
objs: ["bar"],
}
cc_object {
name: "bar",
+ default_shared_libs: [],
srcs: ["x/y/z.c"],
}
`,
@@ -178,6 +182,7 @@
},
blueprint: `cc_object {
name: "foo",
+ default_shared_libs: [],
srcs: ["a/b/c.c"],
include_build_directory: false,
}
@@ -199,6 +204,7 @@
moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
blueprint: `cc_object {
name: "foo",
+ default_shared_libs: [],
include_build_directory: false,
product_variables: {
platform_sdk_version: {
@@ -227,6 +233,7 @@
moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
blueprint: `cc_object {
name: "foo",
+ default_shared_libs: [],
srcs: ["a.cpp"],
arch: {
x86: {
@@ -266,6 +273,7 @@
moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
blueprint: `cc_object {
name: "foo",
+ default_shared_libs: [],
srcs: ["base.cpp"],
arch: {
x86: {
@@ -321,6 +329,7 @@
moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
blueprint: `cc_object {
name: "foo",
+ default_shared_libs: [],
srcs: ["base.cpp"],
target: {
android: {
diff --git a/cc/cc.go b/cc/cc.go
index 0aa1014..1f73149 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -337,6 +337,7 @@
// Used by vendor snapshot to record dependencies from snapshot modules.
SnapshotSharedLibs []string `blueprint:"mutated"`
+ SnapshotStaticLibs []string `blueprint:"mutated"`
SnapshotRuntimeLibs []string `blueprint:"mutated"`
Installable *bool
@@ -525,8 +526,6 @@
// feature represents additional (optional) steps to building cc-related modules, such as invocation
// of clang-tidy.
type feature interface {
- begin(ctx BaseModuleContext)
- deps(ctx DepsContext, deps Deps) Deps
flags(ctx ModuleContext, flags Flags) Flags
props() []interface{}
}
@@ -1898,21 +1897,12 @@
if c.coverage != nil {
c.coverage.begin(ctx)
}
- if c.sabi != nil {
- c.sabi.begin(ctx)
- }
- if c.vndkdep != nil {
- c.vndkdep.begin(ctx)
- }
if c.lto != nil {
c.lto.begin(ctx)
}
if c.pgo != nil {
c.pgo.begin(ctx)
}
- for _, feature := range c.features {
- feature.begin(ctx)
- }
if ctx.useSdk() && c.IsSdkVariant() {
version, err := nativeApiLevelFromUser(ctx, ctx.sdkVersion())
if err != nil {
@@ -1936,24 +1926,9 @@
if c.stl != nil {
deps = c.stl.deps(ctx, deps)
}
- if c.sanitize != nil {
- deps = c.sanitize.deps(ctx, deps)
- }
if c.coverage != nil {
deps = c.coverage.deps(ctx, deps)
}
- if c.sabi != nil {
- deps = c.sabi.deps(ctx, deps)
- }
- if c.vndkdep != nil {
- deps = c.vndkdep.deps(ctx, deps)
- }
- if c.lto != nil {
- deps = c.lto.deps(ctx, deps)
- }
- for _, feature := range c.features {
- deps = feature.deps(ctx, deps)
- }
deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs)
deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
@@ -2856,6 +2831,8 @@
c.Properties.AndroidMkStaticLibs = append(
c.Properties.AndroidMkStaticLibs, makeLibName)
}
+ // Record BaseLibName for snapshots.
+ c.Properties.SnapshotStaticLibs = append(c.Properties.SnapshotStaticLibs, BaseLibName(depName))
}
} else if !c.IsStubs() {
// Stubs lib doesn't link to the runtime lib, object, crt, etc. dependencies.
@@ -3179,6 +3156,13 @@
return false
}
+func (c *Module) StaticExecutable() bool {
+ if b, ok := c.linker.(*binaryDecorator); ok {
+ return b.static()
+ }
+ return false
+}
+
func (c *Module) Object() bool {
if o, ok := c.linker.(interface {
object() bool
diff --git a/cc/linkable.go b/cc/linkable.go
index 231626e..dd87334 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -94,6 +94,9 @@
// SnapshotSharedLibs returns the list of shared library dependencies for this module.
SnapshotSharedLibs() []string
+ // SnapshotStaticLibs returns the list of static library dependencies for this module.
+ SnapshotStaticLibs() []string
+
// IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt.
IsSnapshotPrebuilt() bool
}
@@ -226,6 +229,9 @@
// Header returns true if this is a library headers module.
Header() bool
+ // StaticExecutable returns true if this is a binary module with "static_executable: true".
+ StaticExecutable() bool
+
// EverInstallable returns true if the module is ever installable
EverInstallable() bool
diff --git a/cc/lto.go b/cc/lto.go
index a3b28d9..fccb597 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -80,10 +80,6 @@
}
}
-func (lto *lto) deps(ctx BaseModuleContext, deps Deps) Deps {
- return deps
-}
-
func (lto *lto) useClangLld(ctx BaseModuleContext) bool {
if lto.Properties.Use_clang_lld != nil {
return Bool(lto.Properties.Use_clang_lld)
diff --git a/cc/object.go b/cc/object.go
index 39fc43d..9f2db2e 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -67,9 +67,19 @@
}
type ObjectLinkerProperties struct {
+ // list of static library modules that should only provide headers for this module.
+ Static_libs []string `android:"arch_variant,variant_prepend"`
+
+ // list of shared library modules should only provide headers for this module.
+ Shared_libs []string `android:"arch_variant"`
+
// list of modules that should only provide headers for this module.
Header_libs []string `android:"arch_variant,variant_prepend"`
+ // list of default libraries that will provide headers for this module. If unset, generally
+ // defaults to libc, libm, and libdl. Set to [] to prevent using headers from the defaults.
+ Default_shared_libs []string `android:"arch_variant"`
+
// names of other cc_object modules to link into this module using partial linking
Objs []string `android:"arch_variant"`
@@ -84,8 +94,8 @@
Crt *bool
}
-func newObject() *Module {
- module := newBaseModule(android.HostAndDeviceSupported, android.MultilibBoth)
+func newObject(hod android.HostOrDeviceSupported) *Module {
+ module := newBaseModule(hod, android.MultilibBoth)
module.sanitize = &sanitize{}
module.stl = &stl{}
return module
@@ -95,7 +105,7 @@
// necessary, but sometimes used to generate .s files from .c files to use as
// input to a cc_genrule module.
func ObjectFactory() android.Module {
- module := newObject()
+ module := newObject(android.HostAndDeviceSupported)
module.linker = &objectLinker{
baseLinker: NewBaseLinker(module.sanitize),
}
@@ -198,7 +208,18 @@
func (object *objectLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
deps.HeaderLibs = append(deps.HeaderLibs, object.Properties.Header_libs...)
+ deps.SharedLibs = append(deps.SharedLibs, object.Properties.Shared_libs...)
+ deps.StaticLibs = append(deps.StaticLibs, object.Properties.Static_libs...)
deps.ObjFiles = append(deps.ObjFiles, object.Properties.Objs...)
+
+ deps.SystemSharedLibs = object.Properties.Default_shared_libs
+ if deps.SystemSharedLibs == nil {
+ // Provide a default set of shared libraries if default_shared_libs is unspecified.
+ // Note: If an empty list [] is specified, it implies that the module declines the
+ // default shared libraries.
+ deps.SystemSharedLibs = append(deps.SystemSharedLibs, ctx.toolchain().DefaultSharedLibraries()...)
+ }
+ deps.LateSharedLibs = append(deps.LateSharedLibs, deps.SystemSharedLibs...)
return deps
}
@@ -247,6 +268,20 @@
return outputFile
}
+func (object *objectLinker) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
+ specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, object.Properties.Shared_libs...)
+
+ // Must distinguish nil and [] in default_shared_libs - ensure that [] in
+ // either input list doesn't come out as nil.
+ if specifiedDeps.defaultSharedLibs == nil {
+ specifiedDeps.defaultSharedLibs = object.Properties.Default_shared_libs
+ } else {
+ specifiedDeps.defaultSharedLibs = append(specifiedDeps.defaultSharedLibs, object.Properties.Default_shared_libs...)
+ }
+
+ return specifiedDeps
+}
+
func (object *objectLinker) unstrippedOutputFilePath() android.Path {
return nil
}
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index fd310a2..f7154ec 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -388,8 +388,8 @@
return true
}
-func newPrebuiltObject() *Module {
- module := newObject()
+func NewPrebuiltObject(hod android.HostOrDeviceSupported) *Module {
+ module := newObject(hod)
prebuilt := &prebuiltObjectLinker{
objectLinker: objectLinker{
baseLinker: NewBaseLinker(nil),
@@ -403,7 +403,7 @@
}
func prebuiltObjectFactory() android.Module {
- module := newPrebuiltObject()
+ module := NewPrebuiltObject(android.HostAndDeviceSupported)
return module.Init()
}
diff --git a/cc/sabi.go b/cc/sabi.go
index 1f331cb..5fd6f5d 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -45,12 +45,6 @@
return []interface{}{&sabi.Properties}
}
-func (sabi *sabi) begin(ctx BaseModuleContext) {}
-
-func (sabi *sabi) deps(ctx BaseModuleContext, deps Deps) Deps {
- return deps
-}
-
func (sabi *sabi) flags(ctx ModuleContext, flags Flags) Flags {
// Filter out flags which libTooling don't understand.
// This is here for legacy reasons and future-proof, in case the version of libTooling and clang
diff --git a/cc/sanitize.go b/cc/sanitize.go
index b0eb0c6..cdd7dfb 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -499,14 +499,6 @@
}
}
-func (sanitize *sanitize) deps(ctx BaseModuleContext, deps Deps) Deps {
- if !sanitize.Properties.SanitizerEnabled { // || c.static() {
- return deps
- }
-
- return deps
-}
-
func toDisableImplicitIntegerChange(flags []string) bool {
// Returns true if any flag is fsanitize*integer, and there is
// no explicit flag about sanitize=implicit-integer-sign-change.
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 3a382a1..fb89224 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -931,7 +931,7 @@
// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_object
// overrides the vendor variant of the cc object with the same name, if BOARD_VNDK_VERSION is set.
func VendorSnapshotObjectFactory() android.Module {
- module := newObject()
+ module := newObject(android.DeviceSupported)
prebuilt := &snapshotObjectLinker{
objectLinker: objectLinker{
@@ -949,7 +949,7 @@
// development/vendor_snapshot/update.py. As a part of recovery snapshot, recovery_snapshot_object
// overrides the recovery variant of the cc object with the same name, if BOARD_VNDK_VERSION is set.
func RecoverySnapshotObjectFactory() android.Module {
- module := newObject()
+ module := newObject(android.DeviceSupported)
prebuilt := &snapshotObjectLinker{
objectLinker: objectLinker{
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index a6c8ed5..b0538be 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -53,6 +53,10 @@
return m.Properties.SnapshotSharedLibs
}
+func (m *Module) SnapshotStaticLibs() []string {
+ return m.Properties.SnapshotStaticLibs
+}
+
// snapshotLibraryInterface is an interface for libraries captured to VNDK / vendor snapshots.
type snapshotLibraryInterface interface {
libraryInterface
diff --git a/cc/testing.go b/cc/testing.go
index 80cc0ef..b9d84f6 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -367,6 +367,7 @@
stl: "none",
min_sdk_version: "16",
crt: true,
+ default_shared_libs: [],
apex_available: [
"//apex_available:platform",
"//apex_available:anyapex",
diff --git a/cc/tidy.go b/cc/tidy.go
index 616cf8a..b2382e8 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -61,13 +61,6 @@
return []interface{}{&tidy.Properties}
}
-func (tidy *tidyFeature) begin(ctx BaseModuleContext) {
-}
-
-func (tidy *tidyFeature) deps(ctx DepsContext, deps Deps) Deps {
- return deps
-}
-
func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags {
CheckBadTidyFlags(ctx, "tidy_flags", tidy.Properties.Tidy_flags)
CheckBadTidyChecks(ctx, "tidy_checks", tidy.Properties.Tidy_checks)
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 5a303c8..7ba2363 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -242,10 +242,12 @@
SanitizeUbsanDep bool `json:",omitempty"`
// binary flags
- Symlinks []string `json:",omitempty"`
+ Symlinks []string `json:",omitempty"`
+ StaticExecutable bool `json:",omitempty"`
// dependencies
SharedLibs []string `json:",omitempty"`
+ StaticLibs []string `json:",omitempty"`
RuntimeLibs []string `json:",omitempty"`
Required []string `json:",omitempty"`
@@ -381,6 +383,8 @@
if m.Shared() {
prop.SharedLibs = m.SnapshotSharedLibs()
}
+ // static libs dependencies are required to collect the NOTICE files.
+ prop.StaticLibs = m.SnapshotStaticLibs()
if sanitizable, ok := m.(PlatformSanitizeable); ok {
if sanitizable.Static() && sanitizable.SanitizePropDefined() {
prop.SanitizeMinimalDep = sanitizable.MinimalRuntimeDep() || sanitizable.MinimalRuntimeNeeded()
@@ -426,8 +430,10 @@
} else if m.Binary() {
// binary flags
prop.Symlinks = m.Symlinks()
+ prop.StaticExecutable = m.StaticExecutable()
prop.SharedLibs = m.SnapshotSharedLibs()
-
+ // static libs dependencies are required to collect the NOTICE files.
+ prop.StaticLibs = m.SnapshotStaticLibs()
// install bin
binPath := m.OutputFile().Path()
snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
diff --git a/cc/vndk.go b/cc/vndk.go
index 0b40076..499d428 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -100,12 +100,6 @@
return []interface{}{&vndk.Properties}
}
-func (vndk *vndkdep) begin(ctx BaseModuleContext) {}
-
-func (vndk *vndkdep) deps(ctx BaseModuleContext, deps Deps) Deps {
- return deps
-}
-
func (vndk *vndkdep) isVndk() bool {
return Bool(vndk.Properties.Vndk.Enabled)
}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 87c8186..ebd22cf 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -537,27 +537,18 @@
global := dexpreopt.GetGlobalConfig(ctx)
- // Convert content names to their appropriate stems, in case a test library is overriding an actual boot jar
- var stems []string
- for _, name := range b.properties.Contents {
- dep := ctx.GetDirectDepWithTag(name, bootclasspathFragmentContentDepTag)
- if m, ok := dep.(ModuleWithStem); ok {
- stems = append(stems, m.Stem())
- } else {
- ctx.PropertyErrorf("contents", "%v is not a ModuleWithStem", name)
- }
- }
+ possibleUpdatableModules := gatherPossibleUpdatableModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag)
// Only create configs for updatable boot jars. Non-updatable boot jars must be part of the
// platform_bootclasspath's classpath proto config to guarantee that they come before any
// updatable jars at runtime.
- jars := global.UpdatableBootJars.Filter(stems)
+ jars := global.UpdatableBootJars.Filter(possibleUpdatableModules)
// TODO(satayev): for apex_test we want to include all contents unconditionally to classpaths
// config. However, any test specific jars would not be present in UpdatableBootJars. Instead,
// we should check if we are creating a config for apex_test via ApexInfo and amend the values.
// This is an exception to support end-to-end test for SdkExtensions, until such support exists.
- if android.InList("test_framework-sdkextensions", stems) {
+ if android.InList("test_framework-sdkextensions", possibleUpdatableModules) {
jars = jars.Append("com.android.sdkext", "test_framework-sdkextensions")
}
return jars
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index f7a200a..12bb711 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -91,6 +91,29 @@
maxSdkVersion int32
}
+// gatherPossibleUpdatableModuleNamesAndStems returns a set of module and stem names from the
+// supplied contents that may be in the updatable boot jars.
+//
+// The module names are included because sometimes the stem is set to just change the name of
+// the installed file and it expects the configuration to still use the actual module name.
+//
+// The stem names are included because sometimes the stem is set to change the effective name of the
+// module that is used in the configuration as well,e .g. when a test library is overriding an
+// actual boot jar
+func gatherPossibleUpdatableModuleNamesAndStems(ctx android.ModuleContext, contents []string, tag blueprint.DependencyTag) []string {
+ set := map[string]struct{}{}
+ for _, name := range contents {
+ dep := ctx.GetDirectDepWithTag(name, tag)
+ set[name] = struct{}{}
+ if m, ok := dep.(ModuleWithStem); ok {
+ set[m.Stem()] = struct{}{}
+ } else {
+ ctx.PropertyErrorf("contents", "%v is not a ModuleWithStem", name)
+ }
+ }
+ return android.SortedStringKeys(set)
+}
+
// Converts android.ConfiguredJarList into a list of classpathJars for each given classpathType.
func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars android.ConfiguredJarList, classpaths ...classpathType) []classpathJar {
paths := configuredJars.DevicePaths(ctx.Config(), android.Android)
diff --git a/java/droidstubs.go b/java/droidstubs.go
index d348b55..ec1b04a 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -128,12 +128,15 @@
// whicih can be used for scheduling purposes
High_mem *bool
- // is set to true, Metalava will allow framework SDK to contain API levels annotations.
+ // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Api_levels_annotations_enabled *bool
// the dirs which Metalava extracts API levels annotations from.
Api_levels_annotations_dirs []string
+ // the sdk kind which Metalava extracts API levels annotations from. Supports 'public' and 'system' for now; defaults to public.
+ Api_levels_sdk_type *string
+
// the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
Api_levels_jar_filename *string
@@ -367,6 +370,7 @@
filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
+ var dirs []string
ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
if t, ok := m.(*ExportedDroiddocDir); ok {
for _, dep := range t.deps {
@@ -383,12 +387,32 @@
cmd.Implicit(dep)
}
}
- cmd.FlagWithArg("--android-jar-pattern ", t.dir.String()+"/%/public/"+filename)
+
+ dirs = append(dirs, t.dir.String())
} else {
ctx.PropertyErrorf("api_levels_annotations_dirs",
"module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
}
})
+
+ // Add all relevant --android-jar-pattern patterns for Metalava.
+ // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
+ // an actual file present on disk (in the order the patterns were passed). For system APIs for
+ // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
+ // for older releases.
+ if sdkType := proptools.StringDefault(d.properties.Api_levels_sdk_type, "public"); sdkType != "public" {
+ if sdkType != "system" {
+ ctx.PropertyErrorf("api_levels_sdk_type", "only 'public' and 'system' are supported")
+ }
+ // If building non public stubs, add all sdkType patterns first...
+ for _, dir := range dirs {
+ cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkType, filename))
+ }
+ }
+ for _, dir := range dirs {
+ // ... and fallback to public ones, for Metalava to use if needed.
+ cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, "public", filename))
+ }
}
func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index db664c1..60d0bea 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -16,6 +16,7 @@
import (
"reflect"
+ "regexp"
"strings"
"testing"
@@ -81,6 +82,46 @@
}
}
+func TestSystemDroidstubs(t *testing.T) {
+ ctx, _ := testJavaWithFS(t, `
+ droiddoc_exported_dir {
+ name: "some-exported-dir",
+ path: "somedir",
+ }
+
+ droiddoc_exported_dir {
+ name: "some-other-exported-dir",
+ path: "someotherdir",
+ }
+
+ droidstubs {
+ name: "foo-stubs",
+ srcs: ["foo-doc/a.java"],
+ api_levels_annotations_dirs: [
+ "some-exported-dir",
+ "some-other-exported-dir",
+ ],
+ api_levels_annotations_enabled: true,
+ api_levels_sdk_type: "system",
+ }
+ `,
+ map[string][]byte{
+ "foo-doc/a.java": nil,
+ })
+
+ m := ctx.ModuleForTests("foo-stubs", "android_common")
+ manifest := m.Output("metalava.sbox.textproto")
+ cmd := String(android.RuleBuilderSboxProtoForTests(t, manifest).Commands[0].Command)
+ r := regexp.MustCompile(`--android-jar-pattern [^ ]+/android.jar`)
+ matches := r.FindAllString(cmd, -1)
+ android.AssertArrayString(t, "order of patterns", []string{
+ "--android-jar-pattern somedir/%/system/android.jar",
+ "--android-jar-pattern someotherdir/%/system/android.jar",
+ "--android-jar-pattern somedir/%/public/android.jar",
+ "--android-jar-pattern someotherdir/%/public/android.jar",
+ }, matches)
+}
+
func TestDroidstubsSandbox(t *testing.T) {
ctx, _ := testJavaWithFS(t, `
genrule {
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 252c615..28a5a2c 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -106,21 +106,12 @@
func (s *SystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
global := dexpreopt.GetGlobalConfig(ctx)
- // Convert content names to their appropriate stems, in case a test library is overriding an actual boot jar
- var stems []string
- for _, name := range s.properties.Contents {
- dep := ctx.GetDirectDepWithTag(name, systemServerClasspathFragmentContentDepTag)
- if m, ok := dep.(ModuleWithStem); ok {
- stems = append(stems, m.Stem())
- } else {
- ctx.PropertyErrorf("contents", "%v is not a ModuleWithStem", name)
- }
- }
+ possibleUpdatableModules := gatherPossibleUpdatableModuleNamesAndStems(ctx, s.properties.Contents, systemServerClasspathFragmentContentDepTag)
// Only create configs for updatable boot jars. Non-updatable system server jars must be part of the
// platform_systemserverclasspath's classpath proto config to guarantee that they come before any
// updatable jars at runtime.
- return global.UpdatableSystemServerJars.Filter(stems)
+ return global.UpdatableSystemServerJars.Filter(possibleUpdatableModules)
}
type systemServerClasspathFragmentContentDependencyTag struct {
diff --git a/rust/rust.go b/rust/rust.go
index 05f6399..a11a04c 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -87,6 +87,7 @@
// Used by vendor snapshot to record dependencies from snapshot modules.
SnapshotSharedLibs []string `blueprint:"mutated"`
+ SnapshotStaticLibs []string `blueprint:"mutated"`
// Make this module available when building for vendor ramdisk.
// On device without a dedicated recovery partition, the module is only
@@ -259,6 +260,13 @@
return false
}
+func (mod *Module) StaticExecutable() bool {
+ if !mod.Binary() {
+ return false
+ }
+ return Bool(mod.compiler.(*binaryDecorator).Properties.Static_executable)
+}
+
func (mod *Module) Object() bool {
// Rust has no modules which produce only object files.
return false
@@ -1097,6 +1105,7 @@
// Record baseLibName for snapshots.
mod.Properties.SnapshotSharedLibs = append(mod.Properties.SnapshotSharedLibs, cc.BaseLibName(depName))
+ mod.Properties.SnapshotStaticLibs = append(mod.Properties.SnapshotStaticLibs, cc.BaseLibName(depName))
mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, makeLibName)
exportDep = true
diff --git a/rust/snapshot_utils.go b/rust/snapshot_utils.go
index bd7ca7f..8dabd9b 100644
--- a/rust/snapshot_utils.go
+++ b/rust/snapshot_utils.go
@@ -57,6 +57,10 @@
return mod.Properties.SnapshotSharedLibs
}
+func (mod *Module) SnapshotStaticLibs() []string {
+ return mod.Properties.SnapshotStaticLibs
+}
+
func (mod *Module) Symlinks() []string {
// TODO update this to return the list of symlinks when Rust supports defining symlinks
return nil
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 98697dc..60fbccf 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -347,6 +347,7 @@
cc_object {
name: "crtobj",
stl: "none",
+ default_shared_libs: [],
sanitize: {
never: true,
},
@@ -364,6 +365,7 @@
apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
+ default_shared_libs: [],
sanitize: {
never: true,
},
@@ -388,6 +390,7 @@
apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
+ default_shared_libs: [],
sanitize: {
never: true,
},
diff --git a/sdk/sdk.go b/sdk/sdk.go
index b1c8aeb..afc6aa4 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -93,6 +93,10 @@
// dropped. Adding a rule to members that have //visibility:private will
// cause the //visibility:private to be discarded.
Prebuilt_visibility []string
+
+ // Specifying whether the generated prebuilt SDK build rule should have the
+ // prefer flag set or not.
+ Prebuilts_prefer *bool // default: false
}
// Contains information about the sdk properties that list sdk members, e.g.
@@ -292,6 +296,10 @@
return s.properties.Snapshot
}
+func (s *sdk) PreferPrebuilts() bool {
+ return proptools.BoolDefault(s.properties.Prebuilts_prefer, false)
+}
+
func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if s.snapshot() {
// We don't need to create a snapshot out of sdk_snapshot.
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index a13b0d7..0933db2 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -662,3 +662,68 @@
)
})
}
+
+// Ensure that sdk prebuilt_prefer works correctly.
+func TestSnapshot_PrebuiltPreferTrue(t *testing.T) {
+ bp := `
+ sdk {
+ name: "mysdk",
+ java_header_libs: ["myjavalib"],
+ prebuilts_prefer: true,
+ }
+
+ java_library {
+ name: "myjavalib",
+ srcs: ["Test.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ host_supported: true,
+ }
+ `
+ preparer := android.GroupFixturePreparers(
+ prepareForSdkTestWithJava,
+ android.FixtureWithRootAndroidBp(bp),
+ )
+
+ checkZipFile := func(t *testing.T, result *android.TestResult, expected string) {
+ zipRule := result.ModuleForTests("mysdk", "common_os").Rule("SnapshotZipFiles")
+ android.AssertStringEquals(t, "snapshot zip file", expected, zipRule.Output.String())
+ }
+
+ t.Run("prefer=true", func(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ preparer,
+ ).RunTest(t)
+
+ checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-current.zip")
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_import {
+ name: "mysdk_myjavalib@current",
+ sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ jars: ["java/myjavalib.jar"],
+}
+
+java_import {
+ name: "myjavalib",
+ prefer: true,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ jars: ["java/myjavalib.jar"],
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ visibility: ["//visibility:public"],
+ java_header_libs: ["mysdk_myjavalib@current"],
+}
+ `),
+ )
+ })
+}
diff --git a/sdk/update.go b/sdk/update.go
index b146b62..2ab45d7 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -32,8 +32,9 @@
// ========================================================
//
// SOONG_SDK_SNAPSHOT_PREFER
-// By default every unversioned module in the generated snapshot has prefer: false. Building it
-// with SOONG_SDK_SNAPSHOT_PREFER=true will force them to use prefer: true.
+// By default every unversioned module in the generated snapshot has prefer set by the
+// sdk.prebuilts_prefer property. Building it with SOONG_SDK_SNAPSHOT_PREFER=true will force
+// them to use prefer: true.
//
// SOONG_SDK_SNAPSHOT_VERSION
// This provides control over the version of the generated snapshot.
@@ -1623,11 +1624,11 @@
// Do not add the prefer property if the member snapshot module is a source module type.
if !memberType.UsesSourceModuleTypeInSnapshot() {
- // Set the prefer based on the environment variable. This is a temporary work around to allow a
- // snapshot to be created that sets prefer: true.
+ // Set the prefer based on the environment variable if present, else the sdk.prefer_prebuilts
+ // value.
// TODO(b/174997203): Remove once the ability to select the modules to prefer can be done
// dynamically at build time not at snapshot generation time.
- prefer := ctx.sdkMemberContext.Config().IsEnvTrue("SOONG_SDK_SNAPSHOT_PREFER")
+ prefer := ctx.sdkMemberContext.Config().IsEnvTrue("SOONG_SDK_SNAPSHOT_PREFER") || s.PreferPrebuilts()
// Set prefer. Setting this to false is not strictly required as that is the default but it does
// provide a convenient hook to post-process the generated Android.bp file, e.g. in tests to