Merge "Collect metrics from inside soong_build"
diff --git a/Android.bp b/Android.bp
index 0da48a2..78ec9d8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -188,14 +188,15 @@
"cc/rs.go",
"cc/sanitize.go",
"cc/sabi.go",
+ "cc/snapshot_utils.go",
"cc/stl.go",
"cc/strip.go",
"cc/sysprop.go",
"cc/tidy.go",
"cc/util.go",
+ "cc/vendor_snapshot.go",
"cc/vndk.go",
"cc/vndk_prebuilt.go",
- "cc/xom.go",
"cc/cflag_artifacts.go",
"cc/cmakelists.go",
@@ -205,8 +206,10 @@
"cc/linker.go",
"cc/binary.go",
+ "cc/binary_sdk_member.go",
"cc/fuzz.go",
"cc/library.go",
+ "cc/library_headers.go",
"cc/library_sdk_member.go",
"cc/object.go",
"cc/test.go",
@@ -232,6 +235,7 @@
"cc/compiler_test.go",
"cc/gen_test.go",
"cc/genrule_test.go",
+ "cc/library_headers_test.go",
"cc/library_test.go",
"cc/object_test.go",
"cc/prebuilt_test.go",
@@ -534,6 +538,7 @@
"sdk/update.go",
],
testSrcs: [
+ "sdk/bp_test.go",
"sdk/cc_sdk_test.go",
"sdk/exports_test.go",
"sdk/java_sdk_test.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index dbf3aa8..a8153cc 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -236,8 +236,8 @@
}
}
- if amod.noticeFile.Valid() {
- a.SetString("LOCAL_NOTICE_FILE", amod.noticeFile.String())
+ if len(amod.noticeFiles) > 0 {
+ a.SetString("LOCAL_NOTICE_FILE", strings.Join(amod.noticeFiles.Strings(), " "))
}
if host {
diff --git a/android/apex.go b/android/apex.go
index a4b6956..43a42df 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -19,6 +19,14 @@
"sync"
)
+type ApexInfo struct {
+ // Name of the apex variant that this module is mutated into
+ ApexName string
+
+ // Whether this apex variant needs to target Android 10
+ LegacyAndroid10Support bool
+}
+
// ApexModule is the interface that a module type is expected to implement if
// the module has to be built differently depending on whether the module
// is destined for an apex or not (installed to one of the regular partitions).
@@ -38,9 +46,12 @@
Module
apexModuleBase() *ApexModuleBase
- // Marks that this module should be built for the APEX of the specified name.
+ // Marks that this module should be built for the specified APEXes.
// Call this before apex.apexMutator is run.
- BuildForApex(apexName string)
+ BuildForApexes(apexes []ApexInfo)
+
+ // Returns the APEXes that this module will be built for
+ ApexVariations() []ApexInfo
// Returns the name of APEX that this module will be built for. Empty string
// is returned when 'IsForPlatform() == true'. Note that a module can be
@@ -66,13 +77,9 @@
IsInstallableToApex() bool
// Mutate this module into one or more variants each of which is built
- // for an APEX marked via BuildForApex().
+ // for an APEX marked via BuildForApexes().
CreateApexVariations(mctx BottomUpMutatorContext) []Module
- // Sets the name of the apex variant of this module. Called inside
- // CreateApexVariations.
- setApexName(apexName string)
-
// Tests if this module is available for the specified APEX or ":platform"
AvailableFor(what string) bool
@@ -88,12 +95,10 @@
//
// "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
// "//apex_available:platform" refers to non-APEX partitions like "system.img".
- // Default is ["//apex_available:platform", "//apex_available:anyapex"].
- // TODO(b/128708192) change the default to ["//apex_available:platform"]
+ // Default is ["//apex_available:platform"].
Apex_available []string
- // Name of the apex variant that this module is mutated into
- ApexName string `blueprint:"mutated"`
+ Info ApexInfo `blueprint:"mutated"`
}
// Provides default implementation for the ApexModule interface. APEX-aware
@@ -104,31 +109,37 @@
canHaveApexVariants bool
apexVariationsLock sync.Mutex // protects apexVariations during parallel apexDepsMutator
- apexVariations []string
+ apexVariations []ApexInfo
}
func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
return m
}
-func (m *ApexModuleBase) BuildForApex(apexName string) {
+func (m *ApexModuleBase) BuildForApexes(apexes []ApexInfo) {
m.apexVariationsLock.Lock()
defer m.apexVariationsLock.Unlock()
- if !InList(apexName, m.apexVariations) {
- m.apexVariations = append(m.apexVariations, apexName)
+nextApex:
+ for _, apex := range apexes {
+ for _, v := range m.apexVariations {
+ if v.ApexName == apex.ApexName {
+ continue nextApex
+ }
+ }
+ m.apexVariations = append(m.apexVariations, apex)
}
}
+func (m *ApexModuleBase) ApexVariations() []ApexInfo {
+ return m.apexVariations
+}
+
func (m *ApexModuleBase) ApexName() string {
- return m.ApexProperties.ApexName
+ return m.ApexProperties.Info.ApexName
}
func (m *ApexModuleBase) IsForPlatform() bool {
- return m.ApexProperties.ApexName == ""
-}
-
-func (m *ApexModuleBase) setApexName(apexName string) {
- m.ApexProperties.ApexName = apexName
+ return m.ApexProperties.Info.ApexName == ""
}
func (m *ApexModuleBase) CanHaveApexVariants() bool {
@@ -177,25 +188,35 @@
}
}
+type byApexName []ApexInfo
+
+func (a byApexName) Len() int { return len(a) }
+func (a byApexName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a byApexName) Less(i, j int) bool { return a[i].ApexName < a[j].ApexName }
+
func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []Module {
if len(m.apexVariations) > 0 {
m.checkApexAvailableProperty(mctx)
- sort.Strings(m.apexVariations)
+
+ sort.Sort(byApexName(m.apexVariations))
variations := []string{}
- availableForPlatform := mctx.Module().(ApexModule).AvailableFor(AvailableToPlatform) || mctx.Host()
- if availableForPlatform {
- variations = append(variations, "") // Original variation for platform
+ variations = append(variations, "") // Original variation for platform
+ for _, apex := range m.apexVariations {
+ variations = append(variations, apex.ApexName)
}
- variations = append(variations, m.apexVariations...)
defaultVariation := ""
mctx.SetDefaultDependencyVariation(&defaultVariation)
+
modules := mctx.CreateVariations(variations...)
- for i, m := range modules {
- if availableForPlatform && i == 0 {
- continue
+ for i, mod := range modules {
+ platformVariation := i == 0
+ if platformVariation && !mctx.Host() && !mod.(ApexModule).AvailableFor(AvailableToPlatform) {
+ mod.SkipInstall()
}
- m.(ApexModule).setApexName(variations[i])
+ if !platformVariation {
+ mod.(ApexModule).apexModuleBase().ApexProperties.Info = m.apexVariations[i-1]
+ }
}
return modules
}
@@ -219,18 +240,20 @@
}
// Update the map to mark that a module named moduleName is directly or indirectly
-// depended on by an APEX named apexName. Directly depending means that a module
+// depended on by the specified APEXes. Directly depending means that a module
// is explicitly listed in the build definition of the APEX via properties like
// native_shared_libs, java_libs, etc.
-func UpdateApexDependency(apexName string, moduleName string, directDep bool) {
+func UpdateApexDependency(apexes []ApexInfo, moduleName string, directDep bool) {
apexNamesMapMutex.Lock()
defer apexNamesMapMutex.Unlock()
- apexNames, ok := apexNamesMap()[moduleName]
- if !ok {
- apexNames = make(map[string]bool)
- apexNamesMap()[moduleName] = apexNames
+ for _, apex := range apexes {
+ apexesForModule, ok := apexNamesMap()[moduleName]
+ if !ok {
+ apexesForModule = make(map[string]bool)
+ apexNamesMap()[moduleName] = apexesForModule
+ }
+ apexesForModule[apex.ApexName] = apexesForModule[apex.ApexName] || directDep
}
- apexNames[apexName] = apexNames[apexName] || directDep
}
// TODO(b/146393795): remove this when b/146393795 is fixed
diff --git a/android/arch.go b/android/arch.go
index 3657e6d..73a490d 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -765,7 +765,7 @@
}
if len(moduleOSList) == 0 {
- base.commonProperties.Enabled = boolPtr(false)
+ base.Disable()
return
}
@@ -869,7 +869,7 @@
}
if len(targets) == 0 {
- base.commonProperties.Enabled = boolPtr(false)
+ base.Disable()
return
}
@@ -1521,12 +1521,7 @@
// hasArmAbi returns true if arch has at least one arm ABI
func hasArmAbi(arch Arch) bool {
- for _, abi := range arch.Abi {
- if strings.HasPrefix(abi, "arm") {
- return true
- }
- }
- return false
+ return PrefixInList(arch.Abi, "arm")
}
// hasArmArch returns true if targets has at least non-native_bridge arm Android arch
diff --git a/android/config.go b/android/config.go
index d0ac4c3..b2bda2a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -265,7 +265,7 @@
config.Targets = map[OsType][]Target{
Fuchsia: []Target{
- {Fuchsia, Arch{ArchType: Arm64, ArchVariant: ""}, NativeBridgeDisabled, "", ""},
+ {Fuchsia, Arch{ArchType: Arm64, ArchVariant: "", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""},
},
BuildOs: []Target{
{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", ""},
@@ -570,8 +570,8 @@
return String(c.productVariables.BuildId)
}
-func (c *config) BuildNumberFromFile() string {
- return String(c.productVariables.BuildNumberFromFile)
+func (c *config) BuildNumberFile(ctx PathContext) Path {
+ return PathForOutput(ctx, String(c.productVariables.BuildNumberFile))
}
// DeviceName returns the name of the current device target
@@ -790,14 +790,6 @@
return Bool(c.productVariables.DisableScudo)
}
-func (c *config) EnableXOM() bool {
- if c.productVariables.EnableXOM == nil {
- return true
- } else {
- return Bool(c.productVariables.EnableXOM)
- }
-}
-
func (c *config) Android64() bool {
for _, t := range c.Targets[Android] {
if t.Arch.ArchType.Multilib == "lib64" {
@@ -898,11 +890,7 @@
func (c *config) EnforceRROExcludedOverlay(path string) bool {
excluded := c.productVariables.EnforceRROExcludedOverlays
if excluded != nil {
- for _, exclude := range excluded {
- if strings.HasPrefix(path, exclude) {
- return true
- }
- }
+ return HasAnyPrefix(path, excluded)
}
return false
}
@@ -923,8 +911,23 @@
return c.productVariables.ModulesLoadedByPrivilegedModules
}
+// Expected format for apexJarValue = <apex name>:<jar name>
+func SplitApexJarPair(apexJarValue string) (string, string) {
+ var apexJarPair []string = strings.SplitN(apexJarValue, ":", 2)
+ if apexJarPair == nil || len(apexJarPair) != 2 {
+ panic(fmt.Errorf("malformed apexJarValue: %q, expected format: <apex>:<jar>",
+ apexJarValue))
+ }
+ return apexJarPair[0], apexJarPair[1]
+}
+
func (c *config) BootJars() []string {
- return c.productVariables.BootJars
+ jars := c.productVariables.BootJars
+ for _, p := range c.productVariables.UpdatableBootJars {
+ _, jar := SplitApexJarPair(p)
+ jars = append(jars, jar)
+ }
+ return jars
}
func (c *config) DexpreoptGlobalConfig(ctx PathContext) ([]byte, error) {
@@ -1043,12 +1046,12 @@
func (c *deviceConfig) CoverageEnabledForPath(path string) bool {
coverage := false
if c.config.productVariables.CoveragePaths != nil {
- if InList("*", c.config.productVariables.CoveragePaths) || PrefixInList(path, c.config.productVariables.CoveragePaths) {
+ if InList("*", c.config.productVariables.CoveragePaths) || HasAnyPrefix(path, c.config.productVariables.CoveragePaths) {
coverage = true
}
}
if coverage && c.config.productVariables.CoverageExcludePaths != nil {
- if PrefixInList(path, c.config.productVariables.CoverageExcludePaths) {
+ if HasAnyPrefix(path, c.config.productVariables.CoverageExcludePaths) {
coverage = false
}
}
@@ -1121,28 +1124,21 @@
if c.productVariables.IntegerOverflowExcludePaths == nil {
return false
}
- return PrefixInList(path, c.productVariables.IntegerOverflowExcludePaths)
+ return HasAnyPrefix(path, c.productVariables.IntegerOverflowExcludePaths)
}
func (c *config) CFIDisabledForPath(path string) bool {
if c.productVariables.CFIExcludePaths == nil {
return false
}
- return PrefixInList(path, c.productVariables.CFIExcludePaths)
+ return HasAnyPrefix(path, c.productVariables.CFIExcludePaths)
}
func (c *config) CFIEnabledForPath(path string) bool {
if c.productVariables.CFIIncludePaths == nil {
return false
}
- return PrefixInList(path, c.productVariables.CFIIncludePaths)
-}
-
-func (c *config) XOMDisabledForPath(path string) bool {
- if c.productVariables.XOMExcludePaths == nil {
- return false
- }
- return PrefixInList(path, c.productVariables.XOMExcludePaths)
+ return HasAnyPrefix(path, c.productVariables.CFIIncludePaths)
}
func (c *config) VendorConfig(name string) VendorConfig {
diff --git a/android/defaults.go b/android/defaults.go
index 7597446..fd707a4 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -15,6 +15,8 @@
package android
import (
+ "reflect"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -30,16 +32,18 @@
}
type DefaultableModuleBase struct {
- defaultsProperties defaultsProperties
- defaultableProperties []interface{}
+ defaultsProperties defaultsProperties
+ defaultableProperties []interface{}
+ defaultableVariableProperties interface{}
}
func (d *DefaultableModuleBase) defaults() *defaultsProperties {
return &d.defaultsProperties
}
-func (d *DefaultableModuleBase) setProperties(props []interface{}) {
+func (d *DefaultableModuleBase) setProperties(props []interface{}, variableProperties interface{}) {
d.defaultableProperties = props
+ d.defaultableVariableProperties = variableProperties
}
// Interface that must be supported by any module to which defaults can be applied.
@@ -48,7 +52,7 @@
defaults() *defaultsProperties
// Set the property structures into which defaults will be added.
- setProperties([]interface{})
+ setProperties(props []interface{}, variableProperties interface{})
// Apply defaults from the supplied Defaults to the property structures supplied to
// setProperties(...).
@@ -63,7 +67,10 @@
var _ Defaultable = (*DefaultableModuleBase)(nil)
func InitDefaultableModule(module DefaultableModule) {
- module.setProperties(module.(Module).GetProperties())
+ if module.(Module).base().module == nil {
+ panic("InitAndroidModule must be called before InitDefaultableModule")
+ }
+ module.setProperties(module.(Module).GetProperties(), module.(Module).base().variableProperties)
module.AddProperties(module.defaults())
}
@@ -114,6 +121,8 @@
// Get the structures containing the properties for which defaults can be provided.
properties() []interface{}
+ productVariableProperties() interface{}
+
// Return the defaults common properties.
common() *commonProperties
@@ -134,6 +143,10 @@
return d.defaultableProperties
}
+func (d *DefaultsModuleBase) productVariableProperties() interface{} {
+ return d.defaultableVariableProperties
+}
+
func (d *DefaultsModuleBase) common() *commonProperties {
return &d.commonProperties
}
@@ -151,9 +164,10 @@
module.AddProperties(
&hostAndDeviceProperties{},
commonProperties,
- &variableProperties{},
&ApexProperties{})
+ initAndroidModuleBase(module)
+ initProductVariableModule(module)
InitArchModule(module)
InitDefaultableModule(module)
@@ -185,16 +199,57 @@
for _, defaults := range defaultsList {
for _, prop := range defaultable.defaultableProperties {
- for _, def := range defaults.properties() {
- if proptools.TypeEqual(prop, def) {
- err := proptools.PrependProperties(prop, def, nil)
- if err != nil {
- if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
- ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
- } else {
- panic(err)
- }
- }
+ if prop == defaultable.defaultableVariableProperties {
+ defaultable.applyDefaultVariableProperties(ctx, defaults, prop)
+ } else {
+ defaultable.applyDefaultProperties(ctx, defaults, prop)
+ }
+ }
+ }
+}
+
+// Product variable properties need special handling, the type of the filtered product variable
+// property struct may not be identical between the defaults module and the defaultable module.
+// Use PrependMatchingProperties to apply whichever properties match.
+func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx TopDownMutatorContext,
+ defaults Defaults, defaultableProp interface{}) {
+ if defaultableProp == nil {
+ return
+ }
+
+ defaultsProp := defaults.productVariableProperties()
+ if defaultsProp == nil {
+ return
+ }
+
+ dst := []interface{}{
+ defaultableProp,
+ // Put an empty copy of the src properties into dst so that properties in src that are not in dst
+ // don't cause a "failed to find property to extend" error.
+ proptools.CloneEmptyProperties(reflect.ValueOf(defaultsProp)).Interface(),
+ }
+
+ err := proptools.PrependMatchingProperties(dst, defaultsProp, nil)
+ if err != nil {
+ if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+ ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+ } else {
+ panic(err)
+ }
+ }
+}
+
+func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx TopDownMutatorContext,
+ defaults Defaults, defaultableProp interface{}) {
+
+ for _, def := range defaults.properties() {
+ if proptools.TypeEqual(defaultableProp, def) {
+ err := proptools.PrependProperties(defaultableProp, def, nil)
+ if err != nil {
+ if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+ ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+ } else {
+ panic(err)
}
}
}
diff --git a/android/defaults_test.go b/android/defaults_test.go
index ba607ef..d096b2f 100644
--- a/android/defaults_test.go
+++ b/android/defaults_test.go
@@ -15,6 +15,7 @@
package android
import (
+ "reflect"
"testing"
"github.com/google/blueprint/proptools"
@@ -40,8 +41,8 @@
func defaultsTestModuleFactory() Module {
module := &defaultsTestModule{}
module.AddProperties(&module.properties)
- InitDefaultableModule(module)
InitAndroidModule(module)
+ InitDefaultableModule(module)
return module
}
@@ -57,6 +58,49 @@
return defaults
}
+func TestDefaults(t *testing.T) {
+ bp := `
+ defaults {
+ name: "transitive",
+ foo: ["transitive"],
+ }
+
+ defaults {
+ name: "defaults",
+ defaults: ["transitive"],
+ foo: ["defaults"],
+ }
+
+ test {
+ name: "foo",
+ defaults: ["defaults"],
+ foo: ["module"],
+ }
+ `
+
+ config := TestConfig(buildDir, nil, bp, nil)
+
+ ctx := NewTestContext()
+
+ ctx.RegisterModuleType("test", defaultsTestModuleFactory)
+ ctx.RegisterModuleType("defaults", defaultsTestDefaultsFactory)
+
+ ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
+
+ ctx.Register(config)
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ FailIfErrored(t, errs)
+
+ foo := ctx.ModuleForTests("foo", "").Module().(*defaultsTestModule)
+
+ if g, w := foo.properties.Foo, []string{"transitive", "defaults", "module"}; !reflect.DeepEqual(g, w) {
+ t.Errorf("expected foo %q, got %q", w, g)
+ }
+}
+
func TestDefaultsAllowMissingDependencies(t *testing.T) {
bp := `
defaults {
diff --git a/android/module.go b/android/module.go
index 96c2e1e..1026bdf 100644
--- a/android/module.go
+++ b/android/module.go
@@ -172,6 +172,7 @@
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
+ InstallForceOS() *OsType
RequiredModuleNames() []string
HostRequiredModuleNames() []string
@@ -204,6 +205,7 @@
DepsMutator(BottomUpMutatorContext)
base() *ModuleBase
+ Disable()
Enabled() bool
Target() Target
InstallInData() bool
@@ -213,9 +215,12 @@
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
+ InstallForceOS() *OsType
SkipInstall()
ExportedToMake() bool
- NoticeFile() OptionalPath
+ InitRc() Paths
+ VintfFragments() Paths
+ NoticeFiles() Paths
AddProperties(props ...interface{})
GetProperties() []interface{}
@@ -239,6 +244,8 @@
RequiredModuleNames() []string
HostRequiredModuleNames() []string
TargetRequiredModuleNames() []string
+
+ filesToInstall() InstallPaths
}
// Qualified id for a module
@@ -291,6 +298,12 @@
type commonProperties struct {
// emit build rules for this module
+ //
+ // Disabling a module should only be done for those modules that cannot be built
+ // in the current environment. Modules that can build in the current environment
+ // but are not usually required (e.g. superceded by a prebuilt) should not be
+ // disabled as that will prevent them from being built by the checkbuild target
+ // and so prevent early detection of changes that have broken those modules.
Enabled *bool `android:"arch_variant"`
// Controls the visibility of this module to other modules. Allowable values are one or more of
@@ -537,16 +550,7 @@
&base.nameProperties,
&base.commonProperties)
- // Allow tests to override the default product variables
- if base.variableProperties == nil {
- base.variableProperties = zeroProductVariables
- }
-
- // Filter the product variables properties to the ones that exist on this module
- base.variableProperties = createVariableProperties(m.GetProperties(), base.variableProperties)
- if base.variableProperties != nil {
- m.AddProperties(base.variableProperties)
- }
+ initProductVariableModule(m)
base.generalProperties = m.GetProperties()
base.customizableProperties = m.GetProperties()
@@ -643,9 +647,9 @@
primaryVisibilityProperty visibilityProperty
noAddressSanitizer bool
- installFiles Paths
+ installFiles InstallPaths
checkbuildFiles Paths
- noticeFile OptionalPath
+ noticeFiles Paths
// Used by buildTargetSingleton to create checkbuild and per-directory build targets
// Only set on the final variant of each module
@@ -662,6 +666,9 @@
ruleParams map[blueprint.Rule]blueprint.RuleParams
variables map[string]string
+ initRcPaths Paths
+ vintfFragmentsPaths Paths
+
prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool
}
@@ -834,6 +841,10 @@
return *m.commonProperties.Enabled
}
+func (m *ModuleBase) Disable() {
+ m.commonProperties.Enabled = proptools.BoolPtr(false)
+}
+
func (m *ModuleBase) SkipInstall() {
m.commonProperties.SkipInstall = true
}
@@ -842,22 +853,20 @@
return m.commonProperties.NamespaceExportedToMake
}
-func (m *ModuleBase) computeInstallDeps(
- ctx blueprint.ModuleContext) Paths {
+func (m *ModuleBase) computeInstallDeps(ctx blueprint.ModuleContext) InstallPaths {
- result := Paths{}
+ var result InstallPaths
// TODO(ccross): we need to use WalkDeps and have some way to know which dependencies require installation
- ctx.VisitDepsDepthFirstIf(isFileInstaller,
- func(m blueprint.Module) {
- fileInstaller := m.(fileInstaller)
- files := fileInstaller.filesToInstall()
- result = append(result, files...)
- })
+ ctx.VisitDepsDepthFirst(func(m blueprint.Module) {
+ if a, ok := m.(Module); ok {
+ result = append(result, a.filesToInstall()...)
+ }
+ })
return result
}
-func (m *ModuleBase) filesToInstall() Paths {
+func (m *ModuleBase) filesToInstall() InstallPaths {
return m.installFiles
}
@@ -893,12 +902,16 @@
return false
}
+func (m *ModuleBase) InstallForceOS() *OsType {
+ return nil
+}
+
func (m *ModuleBase) Owner() string {
return String(m.commonProperties.Owner)
}
-func (m *ModuleBase) NoticeFile() OptionalPath {
- return m.noticeFile
+func (m *ModuleBase) NoticeFiles() Paths {
+ return m.noticeFiles
}
func (m *ModuleBase) setImageVariation(variant string) {
@@ -932,9 +945,17 @@
return m.base().commonProperties.Target_required
}
+func (m *ModuleBase) InitRc() Paths {
+ return append(Paths{}, m.initRcPaths...)
+}
+
+func (m *ModuleBase) VintfFragments() Paths {
+ return append(Paths{}, m.vintfFragmentsPaths...)
+}
+
func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
- allInstalledFiles := Paths{}
- allCheckbuildFiles := Paths{}
+ var allInstalledFiles InstallPaths
+ var allCheckbuildFiles Paths
ctx.VisitAllModuleVariants(func(module Module) {
a := module.base()
allInstalledFiles = append(allInstalledFiles, a.installFiles...)
@@ -953,7 +974,7 @@
ctx.Build(pctx, BuildParams{
Rule: blueprint.Phony,
Output: name,
- Implicits: allInstalledFiles,
+ Implicits: allInstalledFiles.Paths(),
Default: !ctx.Config().EmbeddedInMake(),
})
deps = append(deps, name)
@@ -1097,6 +1118,9 @@
if !ctx.PrimaryArch() {
suffix = append(suffix, ctx.Arch().ArchType.String())
}
+ if apex, ok := m.module.(ApexModule); ok && !apex.IsForPlatform() {
+ suffix = append(suffix, apex.ApexName())
+ }
ctx.Variable(pctx, "moduleDesc", desc)
@@ -1133,12 +1157,25 @@
}
})
- notice := proptools.StringDefault(m.commonProperties.Notice, "NOTICE")
+ m.noticeFiles = make([]Path, 0)
+ optPath := OptionalPath{}
+ notice := proptools.StringDefault(m.commonProperties.Notice, "")
if module := SrcIsModule(notice); module != "" {
- m.noticeFile = ctx.ExpandOptionalSource(¬ice, "notice")
- } else {
+ optPath = ctx.ExpandOptionalSource(¬ice, "notice")
+ } else if notice != "" {
noticePath := filepath.Join(ctx.ModuleDir(), notice)
- m.noticeFile = ExistentPathForSource(ctx, noticePath)
+ optPath = ExistentPathForSource(ctx, noticePath)
+ }
+ if optPath.Valid() {
+ m.noticeFiles = append(m.noticeFiles, optPath.Path())
+ } else {
+ for _, notice = range []string{"LICENSE", "LICENCE", "NOTICE"} {
+ noticePath := filepath.Join(ctx.ModuleDir(), notice)
+ optPath = ExistentPathForSource(ctx, noticePath)
+ if optPath.Valid() {
+ m.noticeFiles = append(m.noticeFiles, optPath.Path())
+ }
+ }
}
m.module.GenerateAndroidBuildActions(ctx)
@@ -1148,6 +1185,8 @@
m.installFiles = append(m.installFiles, ctx.installFiles...)
m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
+ m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
+ m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
} else if ctx.Config().AllowMissingDependencies() {
// If the module is not enabled it will not create any build rules, nothing will call
// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled
@@ -1261,7 +1300,7 @@
func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string { return b.bp.OtherModuleName(m) }
func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
- b.bp.OtherModuleErrorf(m, fmt, args)
+ b.bp.OtherModuleErrorf(m, fmt, args...)
}
func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
return b.bp.OtherModuleDependencyTag(m)
@@ -1276,8 +1315,8 @@
type moduleContext struct {
bp blueprint.ModuleContext
baseModuleContext
- installDeps Paths
- installFiles Paths
+ installDeps InstallPaths
+ installFiles InstallPaths
checkbuildFiles Paths
module Module
@@ -1683,6 +1722,10 @@
return m.module.InstallBypassMake()
}
+func (m *moduleContext) InstallForceOS() *OsType {
+ return m.module.InstallForceOS()
+}
+
func (m *moduleContext) skipInstall(fullInstallPath InstallPath) bool {
if m.module.base().commonProperties.SkipInstall {
return true
@@ -1726,7 +1769,7 @@
if !m.skipInstall(fullInstallPath) {
- deps = append(deps, m.installDeps...)
+ deps = append(deps, m.installDeps.Paths()...)
var implicitDeps, orderOnlyDeps Paths
@@ -1807,20 +1850,6 @@
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
}
-type fileInstaller interface {
- filesToInstall() Paths
-}
-
-func isFileInstaller(m blueprint.Module) bool {
- _, ok := m.(fileInstaller)
- return ok
-}
-
-func isAndroidModule(m blueprint.Module) bool {
- _, ok := m.(Module)
- return ok
-}
-
func findStringInSlice(str string, slice []string) int {
for i, s := range slice {
if s == str {
diff --git a/android/neverallow.go b/android/neverallow.go
index cef73fb..0cb2029 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -111,7 +111,9 @@
// TODO(b/67974785): always enforce the manifest
NeverAllow().
- Without("name", "libhidltransport-impl-internal").
+ Without("name", "libhidlbase-combined-impl").
+ Without("name", "libhidlbase").
+ Without("name", "libhidlbase_pgo").
With("product_variables.enforce_vintf_manifest.cflags", "*").
Because("manifest enforcement should be independent of ."),
@@ -405,8 +407,8 @@
}
func (r *rule) appliesToPath(dir string) bool {
- includePath := len(r.paths) == 0 || hasAnyPrefix(dir, r.paths)
- excludePath := hasAnyPrefix(dir, r.unlessPaths)
+ includePath := len(r.paths) == 0 || HasAnyPrefix(dir, r.paths)
+ excludePath := HasAnyPrefix(dir, r.unlessPaths)
return includePath && !excludePath
}
@@ -472,15 +474,6 @@
return names
}
-func hasAnyPrefix(s string, prefixes []string) bool {
- for _, prefix := range prefixes {
- if strings.HasPrefix(s, prefix) {
- return true
- }
- }
- return false
-}
-
func hasAnyProperty(properties []interface{}, props []ruleProperty) bool {
for _, v := range props {
if hasProperty(properties, v) {
diff --git a/android/paths.go b/android/paths.go
index 66725c6..8b373da 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -53,6 +53,7 @@
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
+ InstallForceOS() *OsType
}
var _ ModuleInstallPathContext = ModuleContext(nil)
@@ -1205,22 +1206,40 @@
// PathForModuleInstall returns a Path representing the install path for the
// module appended with paths...
func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string) InstallPath {
+ os := ctx.Os()
+ if forceOS := ctx.InstallForceOS(); forceOS != nil {
+ os = *forceOS
+ }
+ partition := modulePartition(ctx, os)
+
+ ret := pathForInstall(ctx, os, partition, ctx.Debug(), pathComponents...)
+
+ if ctx.InstallBypassMake() && ctx.Config().EmbeddedInMake() {
+ ret = ret.ToMakePath()
+ }
+
+ return ret
+}
+
+func pathForInstall(ctx PathContext, os OsType, partition string, debug bool,
+ pathComponents ...string) InstallPath {
+
var outPaths []string
- if ctx.Device() {
- partition := modulePartition(ctx)
+
+ if os.Class == Device {
outPaths = []string{"target", "product", ctx.Config().DeviceName(), partition}
} else {
- switch ctx.Os() {
+ switch os {
case Linux:
- outPaths = []string{"host", "linux-x86"}
+ outPaths = []string{"host", "linux-x86", partition}
case LinuxBionic:
// TODO: should this be a separate top level, or shared with linux-x86?
- outPaths = []string{"host", "linux_bionic-x86"}
+ outPaths = []string{"host", "linux_bionic-x86", partition}
default:
- outPaths = []string{"host", ctx.Os().String() + "-x86"}
+ outPaths = []string{"host", os.String() + "-x86", partition}
}
}
- if ctx.Debug() {
+ if debug {
outPaths = append([]string{"debug"}, outPaths...)
}
outPaths = append(outPaths, pathComponents...)
@@ -1231,9 +1250,6 @@
}
ret := InstallPath{basePath{path, ctx.Config(), ""}, ""}
- if ctx.InstallBypassMake() && ctx.Config().EmbeddedInMake() {
- ret = ret.ToMakePath()
- }
return ret
}
@@ -1253,47 +1269,76 @@
return "/" + rel
}
-func modulePartition(ctx ModuleInstallPathContext) string {
+func modulePartition(ctx ModuleInstallPathContext, os OsType) string {
var partition string
- if ctx.InstallInData() {
- partition = "data"
- } else if ctx.InstallInTestcases() {
+ if ctx.InstallInTestcases() {
+ // "testcases" install directory can be used for host or device modules.
partition = "testcases"
- } else if ctx.InstallInRamdisk() {
- if ctx.DeviceConfig().BoardUsesRecoveryAsBoot() {
- partition = "recovery/root/first_stage_ramdisk"
+ } else if os.Class == Device {
+ if ctx.InstallInData() {
+ partition = "data"
+ } else if ctx.InstallInRamdisk() {
+ if ctx.DeviceConfig().BoardUsesRecoveryAsBoot() {
+ partition = "recovery/root/first_stage_ramdisk"
+ } else {
+ partition = "ramdisk"
+ }
+ if !ctx.InstallInRoot() {
+ partition += "/system"
+ }
+ } else if ctx.InstallInRecovery() {
+ if ctx.InstallInRoot() {
+ partition = "recovery/root"
+ } else {
+ // the layout of recovery partion is the same as that of system partition
+ partition = "recovery/root/system"
+ }
+ } else if ctx.SocSpecific() {
+ partition = ctx.DeviceConfig().VendorPath()
+ } else if ctx.DeviceSpecific() {
+ partition = ctx.DeviceConfig().OdmPath()
+ } else if ctx.ProductSpecific() {
+ partition = ctx.DeviceConfig().ProductPath()
+ } else if ctx.SystemExtSpecific() {
+ partition = ctx.DeviceConfig().SystemExtPath()
+ } else if ctx.InstallInRoot() {
+ partition = "root"
} else {
- partition = "ramdisk"
+ partition = "system"
}
- if !ctx.InstallInRoot() {
- partition += "/system"
+ if ctx.InstallInSanitizerDir() {
+ partition = "data/asan/" + partition
}
- } else if ctx.InstallInRecovery() {
- if ctx.InstallInRoot() {
- partition = "recovery/root"
- } else {
- // the layout of recovery partion is the same as that of system partition
- partition = "recovery/root/system"
- }
- } else if ctx.SocSpecific() {
- partition = ctx.DeviceConfig().VendorPath()
- } else if ctx.DeviceSpecific() {
- partition = ctx.DeviceConfig().OdmPath()
- } else if ctx.ProductSpecific() {
- partition = ctx.DeviceConfig().ProductPath()
- } else if ctx.SystemExtSpecific() {
- partition = ctx.DeviceConfig().SystemExtPath()
- } else if ctx.InstallInRoot() {
- partition = "root"
- } else {
- partition = "system"
- }
- if ctx.InstallInSanitizerDir() {
- partition = "data/asan/" + partition
}
return partition
}
+type InstallPaths []InstallPath
+
+// Paths returns the InstallPaths as a Paths
+func (p InstallPaths) Paths() Paths {
+ if p == nil {
+ return nil
+ }
+ ret := make(Paths, len(p))
+ for i, path := range p {
+ ret[i] = path
+ }
+ return ret
+}
+
+// Strings returns the string forms of the install paths.
+func (p InstallPaths) Strings() []string {
+ if p == nil {
+ return nil
+ }
+ ret := make([]string, len(p))
+ for i, path := range p {
+ ret[i] = path.String()
+ }
+ return ret
+}
+
// validateSafePath validates a path that we trust (may contain ninja variables).
// Ensures that each path component does not attempt to leave its component.
func validateSafePath(pathComponents ...string) (string, error) {
diff --git a/android/paths_test.go b/android/paths_test.go
index 7a32026..f1908ac 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -205,6 +205,7 @@
inRamdisk bool
inRecovery bool
inRoot bool
+ forceOS *OsType
}
func (m moduleInstallPathContextImpl) Config() Config {
@@ -241,6 +242,10 @@
return false
}
+func (m moduleInstallPathContextImpl) InstallForceOS() *OsType {
+ return m.forceOS
+}
+
func pathTestConfig(buildDir string) Config {
return TestConfig(buildDir, nil, "", nil)
}
@@ -598,6 +603,40 @@
},
in: []string{"nativetest", "my_test"},
out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ }, {
+ name: "device testcases",
+ ctx: &moduleInstallPathContextImpl{
+ baseModuleContext: baseModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
+ inTestcases: true,
+ },
+ in: []string{"my_test", "my_test_bin"},
+ out: "target/product/test_device/testcases/my_test/my_test_bin",
+ }, {
+ name: "host testcases",
+ ctx: &moduleInstallPathContextImpl{
+ baseModuleContext: baseModuleContext{
+ os: hostTarget.Os,
+ target: hostTarget,
+ },
+ inTestcases: true,
+ },
+ in: []string{"my_test", "my_test_bin"},
+ out: "host/linux-x86/testcases/my_test/my_test_bin",
+ }, {
+ name: "forced host testcases",
+ ctx: &moduleInstallPathContextImpl{
+ baseModuleContext: baseModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
+ inTestcases: true,
+ forceOS: &Linux,
+ },
+ in: []string{"my_test", "my_test_bin"},
+ out: "host/linux-x86/testcases/my_test/my_test_bin",
},
}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index c780cb2..2d16f65 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -62,6 +62,10 @@
return "prebuilt_" + name
}
+func (p *Prebuilt) ForcePrefer() {
+ p.properties.Prefer = proptools.BoolPtr(true)
+}
+
// The below source-related functions and the srcs, src fields are based on an assumption that
// prebuilt modules have a static source property at the moment. Currently there is only one
// exception, android_app_import, which chooses a source file depending on the product's DPI
diff --git a/android/rule_builder.go b/android/rule_builder.go
index b4f144a..9005f07 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -162,9 +162,10 @@
r.Command().Text("rm").Flag("-f").Outputs(temporariesList)
}
-// Inputs returns the list of paths that were passed to the RuleBuilderCommand methods that take input paths, such
-// as RuleBuilderCommand.Input, RuleBuilderComand.Implicit, or RuleBuilderCommand.FlagWithInput. Inputs to a command
-// that are also outputs of another command in the same RuleBuilder are filtered out.
+// Inputs returns the list of paths that were passed to the RuleBuilderCommand methods that take
+// input paths, such as RuleBuilderCommand.Input, RuleBuilderComand.Implicit, or
+// RuleBuilderCommand.FlagWithInput. Inputs to a command that are also outputs of another command
+// in the same RuleBuilder are filtered out. The list is sorted and duplicates removed.
func (r *RuleBuilder) Inputs() Paths {
outputs := r.outputSet()
depFiles := r.depFileSet()
@@ -193,6 +194,28 @@
return inputList
}
+// OrderOnlys returns the list of paths that were passed to the RuleBuilderCommand.OrderOnly or
+// RuleBuilderCommand.OrderOnlys. The list is sorted and duplicates removed.
+func (r *RuleBuilder) OrderOnlys() Paths {
+ orderOnlys := make(map[string]Path)
+ for _, c := range r.commands {
+ for _, orderOnly := range c.orderOnlys {
+ orderOnlys[orderOnly.String()] = orderOnly
+ }
+ }
+
+ var orderOnlyList Paths
+ for _, orderOnly := range orderOnlys {
+ orderOnlyList = append(orderOnlyList, orderOnly)
+ }
+
+ sort.Slice(orderOnlyList, func(i, j int) bool {
+ return orderOnlyList[i].String() < orderOnlyList[j].String()
+ })
+
+ return orderOnlyList
+}
+
func (r *RuleBuilder) outputSet() map[string]WritablePath {
outputs := make(map[string]WritablePath)
for _, c := range r.commands {
@@ -203,8 +226,9 @@
return outputs
}
-// Outputs returns the list of paths that were passed to the RuleBuilderCommand methods that take output paths, such
-// as RuleBuilderCommand.Output, RuleBuilderCommand.ImplicitOutput, or RuleBuilderCommand.FlagWithInput.
+// Outputs returns the list of paths that were passed to the RuleBuilderCommand methods that take
+// output paths, such as RuleBuilderCommand.Output, RuleBuilderCommand.ImplicitOutput, or
+// RuleBuilderCommand.FlagWithInput. The list is sorted and duplicates removed.
func (r *RuleBuilder) Outputs() WritablePaths {
outputs := r.outputSet()
@@ -262,7 +286,8 @@
return tools
}
-// Tools returns the list of paths that were passed to the RuleBuilderCommand.Tool method.
+// Tools returns the list of paths that were passed to the RuleBuilderCommand.Tool method. The
+// list is sorted and duplicates removed.
func (r *RuleBuilder) Tools() Paths {
toolsSet := r.toolsSet()
@@ -337,6 +362,7 @@
ctx.Build(pctx, BuildParams{
Rule: ErrorRule,
Outputs: r.Outputs(),
+ OrderOnly: r.OrderOnlys(),
Description: desc,
Args: map[string]string{
"error": "missing dependencies: " + strings.Join(r.missingDeps, ", "),
@@ -453,6 +479,7 @@
type RuleBuilderCommand struct {
buf strings.Builder
inputs Paths
+ orderOnlys Paths
outputs WritablePaths
depFiles WritablePaths
tools Paths
@@ -475,6 +502,10 @@
return path.String()
}
+func (c *RuleBuilderCommand) addOrderOnly(path Path) {
+ c.orderOnlys = append(c.orderOnlys, path)
+}
+
func (c *RuleBuilderCommand) outputStr(path Path) string {
if c.sbox {
// Errors will be handled in RuleBuilder.Build where we have a context to report them
@@ -604,6 +635,22 @@
return c
}
+// OrderOnly adds the specified input path to the dependencies returned by RuleBuilder.OrderOnlys
+// without modifying the command line.
+func (c *RuleBuilderCommand) OrderOnly(path Path) *RuleBuilderCommand {
+ c.addOrderOnly(path)
+ return c
+}
+
+// OrderOnlys adds the specified input paths to the dependencies returned by RuleBuilder.OrderOnlys
+// without modifying the command line.
+func (c *RuleBuilderCommand) OrderOnlys(paths Paths) *RuleBuilderCommand {
+ for _, path := range paths {
+ c.addOrderOnly(path)
+ }
+ return c
+}
+
// Output adds the specified output path to the command line. The path will also be added to the outputs returned by
// RuleBuilder.Outputs.
func (c *RuleBuilderCommand) Output(path WritablePath) *RuleBuilderCommand {
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index acf8127..c41b067 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -265,14 +265,16 @@
func TestRuleBuilder(t *testing.T) {
fs := map[string][]byte{
- "dep_fixer": nil,
- "input": nil,
- "Implicit": nil,
- "Input": nil,
- "Tool": nil,
- "input2": nil,
- "tool2": nil,
- "input3": nil,
+ "dep_fixer": nil,
+ "input": nil,
+ "Implicit": nil,
+ "Input": nil,
+ "OrderOnly": nil,
+ "OrderOnlys": nil,
+ "Tool": nil,
+ "input2": nil,
+ "tool2": nil,
+ "input3": nil,
}
ctx := PathContextForTesting(TestConfig("out", nil, "", fs))
@@ -290,6 +292,7 @@
ImplicitOutput(PathForOutput(ctx, "ImplicitOutput")).
Input(PathForSource(ctx, "Input")).
Output(PathForOutput(ctx, "Output")).
+ OrderOnly(PathForSource(ctx, "OrderOnly")).
Text("Text").
Tool(PathForSource(ctx, "Tool"))
@@ -298,6 +301,7 @@
DepFile(PathForOutput(ctx, "depfile2")).
Input(PathForSource(ctx, "input2")).
Output(PathForOutput(ctx, "output2")).
+ OrderOnlys(PathsForSource(ctx, []string{"OrderOnlys"})).
Tool(PathForSource(ctx, "tool2"))
// Test updates to the first command after the second command has been started
@@ -317,6 +321,7 @@
wantOutputs := PathsForOutput(ctx, []string{"ImplicitOutput", "Output", "output", "output2", "output3"})
wantDepFiles := PathsForOutput(ctx, []string{"DepFile", "depfile", "ImplicitDepFile", "depfile2"})
wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
+ wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"})
t.Run("normal", func(t *testing.T) {
rule := NewRuleBuilder()
@@ -346,6 +351,9 @@
if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.Tools() = %#v\n got %#v", w, g)
}
+ if g, w := rule.OrderOnlys(), wantOrderOnlys; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.OrderOnlys() = %#v\n got %#v", w, g)
+ }
if g, w := rule.depFileMergerCmd(ctx, rule.DepFiles()).String(), wantDepMergerCommand; g != w {
t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
@@ -380,6 +388,9 @@
if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.Tools() = %#v\n got %#v", w, g)
}
+ if g, w := rule.OrderOnlys(), wantOrderOnlys; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.OrderOnlys() = %#v\n got %#v", w, g)
+ }
if g, w := rule.depFileMergerCmd(ctx, rule.DepFiles()).String(), wantDepMergerCommand; g != w {
t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
diff --git a/android/sdk.go b/android/sdk.go
index 27756ce..d13ad7d 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -180,6 +180,15 @@
// will only be used if the equivalently named non-prebuilt module is not
// present.
AddPrebuiltModule(member SdkMember, moduleType string) BpModule
+
+ // The property tag to use when adding a property to a BpModule that contains
+ // references to other sdk members. Using this will ensure that the reference
+ // is correctly output for both versioned and unversioned prebuilts in the
+ // snapshot.
+ //
+ // e.g.
+ // bpPropertySet.AddPropertyWithTag("libs", []string{"member1", "member2"}, builder.SdkMemberReferencePropertyTag())
+ SdkMemberReferencePropertyTag() BpPropertyTag
}
type BpPropertyTag interface{}
@@ -264,6 +273,13 @@
// True if the member type supports the sdk/sdk_snapshot, false otherwise.
UsableWithSdkAndSdkSnapshot() bool
+ // Return true if modules of this type can have dependencies which should be
+ // treated as if they are sdk members.
+ //
+ // Any dependency that is to be treated as a member of the sdk needs to implement
+ // SdkAware and be added with an SdkMemberTypeDependencyTag tag.
+ HasTransitiveSdkMembers() bool
+
// Add dependencies from the SDK module to all the variants the member
// contributes to the SDK. The exact set of variants required is determined
// by the SDK and its properties. The dependencies must be added with the
@@ -291,8 +307,9 @@
// Base type for SdkMemberType implementations.
type SdkMemberTypeBase struct {
- PropertyName string
- SupportsSdk bool
+ PropertyName string
+ SupportsSdk bool
+ TransitiveSdkMembers bool
}
func (b *SdkMemberTypeBase) SdkPropertyName() string {
@@ -303,6 +320,10 @@
return b.SupportsSdk
}
+func (b *SdkMemberTypeBase) HasTransitiveSdkMembers() bool {
+ return b.TransitiveSdkMembers
+}
+
// Encapsulates the information about registered SdkMemberTypes.
type SdkMemberTypesRegistry struct {
// The list of types sorted by property name.
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index f54e774..198108d 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -303,6 +303,7 @@
}
return ctx.Config().Once(key, func() interface{} {
+ ctx.AddNinjaFileDeps(from)
r, err := ctx.Config().fs.Open(from)
if err != nil {
ctx.PropertyErrorf("from", "failed to open %q: %s", from, err)
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index 66feba8..6ad88a2 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -43,7 +43,7 @@
name: "acme_test_defaults",
module_type: "test_defaults",
config_namespace: "acme",
- variables: ["board", "feature1", "feature2", "feature3"],
+ variables: ["board", "feature1", "feature2", "FEATURE3"],
properties: ["cflags", "srcs"],
}
@@ -61,7 +61,7 @@
}
soong_config_bool_variable {
- name: "feature3",
+ name: "FEATURE3",
}
`
@@ -91,7 +91,7 @@
feature2: {
cflags: ["-DFEATURE2"],
},
- feature3: {
+ FEATURE3: {
cflags: ["-DFEATURE3"],
},
},
diff --git a/android/util.go b/android/util.go
index e985fc1..ade851e 100644
--- a/android/util.go
+++ b/android/util.go
@@ -122,7 +122,7 @@
}
// Returns true if the given string s is prefixed with any string in the given prefix list.
-func PrefixInList(s string, prefixList []string) bool {
+func HasAnyPrefix(s string, prefixList []string) bool {
for _, prefix := range prefixList {
if strings.HasPrefix(s, prefix) {
return true
@@ -132,7 +132,7 @@
}
// Returns true if any string in the given list has the given prefix.
-func PrefixedStringInList(list []string, prefix string) bool {
+func PrefixInList(list []string, prefix string) bool {
for _, s := range list {
if strings.HasPrefix(s, prefix) {
return true
diff --git a/android/util_test.go b/android/util_test.go
index 90fefee..1f9ca36 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -252,7 +252,7 @@
for _, testCase := range testcases {
t.Run(testCase.str, func(t *testing.T) {
- out := PrefixInList(testCase.str, prefixes)
+ out := HasAnyPrefix(testCase.str, prefixes)
if out != testCase.expected {
t.Errorf("incorrect output:")
t.Errorf(" str: %#v", testCase.str)
diff --git a/android/variable.go b/android/variable.go
index 9625a87..25c94bc 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -25,7 +25,7 @@
func init() {
PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("variable", variableMutator).Parallel()
+ ctx.BottomUp("variable", VariableMutator).Parallel()
})
}
@@ -127,21 +127,21 @@
} `android:"arch_variant"`
Native_coverage struct {
+ Src *string `android:"arch_variant"`
Srcs []string `android:"arch_variant"`
Exclude_srcs []string `android:"arch_variant"`
} `android:"arch_variant"`
} `android:"arch_variant"`
}
-var zeroProductVariables interface{} = variableProperties{}
+var defaultProductVariables interface{} = variableProperties{}
type productVariables struct {
// Suffix to add to generated Makefiles
Make_suffix *string `json:",omitempty"`
- BuildId *string `json:",omitempty"`
- BuildNumberFromFile *string `json:",omitempty"`
- DateFromFile *string `json:",omitempty"`
+ BuildId *string `json:",omitempty"`
+ BuildNumberFile *string `json:",omitempty"`
Platform_version_name *string `json:",omitempty"`
Platform_sdk_version *int `json:",omitempty"`
@@ -229,7 +229,8 @@
UncompressPrivAppDex *bool `json:",omitempty"`
ModulesLoadedByPrivilegedModules []string `json:",omitempty"`
- BootJars []string `json:",omitempty"`
+ BootJars []string `json:",omitempty"`
+ UpdatableBootJars []string `json:",omitempty"`
IntegerOverflowExcludePaths []string `json:",omitempty"`
@@ -239,9 +240,6 @@
DisableScudo *bool `json:",omitempty"`
- EnableXOM *bool `json:",omitempty"`
- XOMExcludePaths []string `json:",omitempty"`
-
Experimental_mte *bool `json:",omitempty"`
VendorPath *string `json:",omitempty"`
@@ -346,7 +344,7 @@
func (v *productVariables) SetDefaultConfig() {
*v = productVariables{
- BuildNumberFromFile: stringPtr("123456789"),
+ BuildNumberFile: stringPtr("build_number.txt"),
Platform_version_name: stringPtr("Q"),
Platform_sdk_version: intPtr(28),
@@ -384,7 +382,7 @@
}
}
-func variableMutator(mctx BottomUpMutatorContext) {
+func VariableMutator(mctx BottomUpMutatorContext) {
var module Module
var ok bool
if module, ok = mctx.Module().(Module); !ok {
@@ -399,11 +397,9 @@
}
variableValues := reflect.ValueOf(a.variableProperties).Elem().FieldByName("Product_variables")
- zeroValues := reflect.ValueOf(zeroProductVariables).FieldByName("Product_variables")
for i := 0; i < variableValues.NumField(); i++ {
variableValue := variableValues.Field(i)
- zeroValue := zeroValues.Field(i)
name := variableValues.Type().Field(i).Name
property := "product_variables." + proptools.PropertyNameForField(name)
@@ -421,10 +417,9 @@
}
// Check if any properties were set for the module
- if reflect.DeepEqual(variableValue.Interface(), zeroValue.Interface()) {
+ if variableValue.IsZero() {
continue
}
-
a.setVariableProperties(mctx, property, variableValue, val.Interface())
}
}
@@ -542,6 +537,20 @@
return ret.Interface()
}
+func initProductVariableModule(m Module) {
+ base := m.base()
+
+ // Allow tests to override the default product variables
+ if base.variableProperties == nil {
+ base.variableProperties = defaultProductVariables
+ }
+ // Filter the product variables properties to the ones that exist on this module
+ base.variableProperties = createVariableProperties(m.GetProperties(), base.variableProperties)
+ if base.variableProperties != nil {
+ m.AddProperties(base.variableProperties)
+ }
+}
+
// createVariableProperties takes the list of property structs for a module and returns a property struct that
// contains the product variable properties that exist in the property structs, or nil if there are none. It
// caches the result.
diff --git a/android/variable_test.go b/android/variable_test.go
index cde2b1a..9cafedd 100644
--- a/android/variable_test.go
+++ b/android/variable_test.go
@@ -171,7 +171,7 @@
Foo []string
}{}))
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("variable", variableMutator).Parallel()
+ ctx.BottomUp("variable", VariableMutator).Parallel()
})
// Test that a module can use one product variable even if it doesn't have all the properties
@@ -209,6 +209,115 @@
FailIfErrored(t, errs)
}
+var testProductVariableDefaultsProperties = struct {
+ Product_variables struct {
+ Eng struct {
+ Foo []string
+ Bar []string
+ }
+ }
+}{}
+
+type productVariablesDefaultsTestProperties struct {
+ Foo []string
+}
+
+type productVariablesDefaultsTestProperties2 struct {
+ Foo []string
+ Bar []string
+}
+
+type productVariablesDefaultsTestModule struct {
+ ModuleBase
+ DefaultableModuleBase
+ properties productVariablesDefaultsTestProperties
+}
+
+func (d *productVariablesDefaultsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ ctx.Build(pctx, BuildParams{
+ Rule: Touch,
+ Output: PathForModuleOut(ctx, "out"),
+ })
+}
+
+func productVariablesDefaultsTestModuleFactory() Module {
+ module := &productVariablesDefaultsTestModule{}
+ module.AddProperties(&module.properties)
+ module.variableProperties = testProductVariableDefaultsProperties
+ InitAndroidModule(module)
+ InitDefaultableModule(module)
+ return module
+}
+
+type productVariablesDefaultsTestDefaults struct {
+ ModuleBase
+ DefaultsModuleBase
+}
+
+func productVariablesDefaultsTestDefaultsFactory() Module {
+ defaults := &productVariablesDefaultsTestDefaults{}
+ defaults.AddProperties(&productVariablesDefaultsTestProperties{})
+ defaults.AddProperties(&productVariablesDefaultsTestProperties2{})
+ defaults.variableProperties = testProductVariableDefaultsProperties
+ InitDefaultsModule(defaults)
+ return defaults
+}
+
+// Test a defaults module that supports more product variable properties than the target module.
+func TestProductVariablesDefaults(t *testing.T) {
+ bp := `
+ defaults {
+ name: "defaults",
+ product_variables: {
+ eng: {
+ foo: ["product_variable_defaults"],
+ bar: ["product_variable_defaults"],
+ },
+ },
+ foo: ["defaults"],
+ bar: ["defaults"],
+ }
+
+ test {
+ name: "foo",
+ defaults: ["defaults"],
+ foo: ["module"],
+ product_variables: {
+ eng: {
+ foo: ["product_variable_module"],
+ },
+ },
+ }
+ `
+
+ config := TestConfig(buildDir, nil, bp, nil)
+ config.TestProductVariables.Eng = boolPtr(true)
+
+ ctx := NewTestContext()
+
+ ctx.RegisterModuleType("test", productVariablesDefaultsTestModuleFactory)
+ ctx.RegisterModuleType("defaults", productVariablesDefaultsTestDefaultsFactory)
+
+ ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("variable", VariableMutator).Parallel()
+ })
+
+ ctx.Register(config)
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ FailIfErrored(t, errs)
+
+ foo := ctx.ModuleForTests("foo", "").Module().(*productVariablesDefaultsTestModule)
+
+ want := []string{"defaults", "module", "product_variable_defaults", "product_variable_module"}
+ if g, w := foo.properties.Foo, want; !reflect.DeepEqual(g, w) {
+ t.Errorf("expected foo %q, got %q", w, g)
+ }
+}
+
func BenchmarkSliceToTypeArray(b *testing.B) {
for _, n := range []int{1, 2, 4, 8, 100} {
var propStructs []interface{}
diff --git a/android/visibility.go b/android/visibility.go
index a597687..3f04123 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -186,8 +186,8 @@
var visibilityRuleMap = NewOnceKey("visibilityRuleMap")
// The map from qualifiedModuleName to visibilityRule.
-func moduleToVisibilityRuleMap(ctx BaseModuleContext) *sync.Map {
- return ctx.Config().Once(visibilityRuleMap, func() interface{} {
+func moduleToVisibilityRuleMap(config Config) *sync.Map {
+ return config.Once(visibilityRuleMap, func() interface{} {
return &sync.Map{}
}).(*sync.Map)
}
@@ -304,7 +304,7 @@
if visibility := m.visibility(); visibility != nil {
rule := parseRules(ctx, currentPkg, m.visibility())
if rule != nil {
- moduleToVisibilityRuleMap(ctx).Store(qualifiedModuleId, rule)
+ moduleToVisibilityRuleMap(ctx.Config()).Store(qualifiedModuleId, rule)
}
}
}
@@ -312,6 +312,7 @@
func parseRules(ctx BaseModuleContext, currentPkg string, visibility []string) compositeRule {
rules := make(compositeRule, 0, len(visibility))
hasPrivateRule := false
+ hasPublicRule := false
hasNonPrivateRule := false
for _, v := range visibility {
ok, pkg, name := splitRule(v, currentPkg)
@@ -328,6 +329,7 @@
isPrivateRule = true
case "public":
r = publicRule{}
+ hasPublicRule = true
}
} else {
switch name {
@@ -355,6 +357,11 @@
return compositeRule{privateRule{}}
}
+ if hasPublicRule {
+ // Public overrides all other rules so just return it.
+ return compositeRule{publicRule{}}
+ }
+
return rules
}
@@ -415,21 +422,21 @@
return
}
- rule := effectiveVisibilityRules(ctx, depQualified)
+ rule := effectiveVisibilityRules(ctx.Config(), depQualified)
if rule != nil && !rule.matches(qualified) {
ctx.ModuleErrorf("depends on %s which is not visible to this module", depQualified)
}
})
}
-func effectiveVisibilityRules(ctx BaseModuleContext, qualified qualifiedModuleName) compositeRule {
- moduleToVisibilityRule := moduleToVisibilityRuleMap(ctx)
+func effectiveVisibilityRules(config Config, qualified qualifiedModuleName) compositeRule {
+ moduleToVisibilityRule := moduleToVisibilityRuleMap(config)
value, ok := moduleToVisibilityRule.Load(qualified)
var rule compositeRule
if ok {
rule = value.(compositeRule)
} else {
- rule = packageDefaultVisibility(ctx, qualified)
+ rule = packageDefaultVisibility(config, qualified)
}
return rule
}
@@ -441,8 +448,8 @@
return qualified
}
-func packageDefaultVisibility(ctx BaseModuleContext, moduleId qualifiedModuleName) compositeRule {
- moduleToVisibilityRule := moduleToVisibilityRuleMap(ctx)
+func packageDefaultVisibility(config Config, moduleId qualifiedModuleName) compositeRule {
+ moduleToVisibilityRule := moduleToVisibilityRuleMap(config)
packageQualifiedId := moduleId.getContainingPackageId()
for {
value, ok := moduleToVisibilityRule.Load(packageQualifiedId)
@@ -469,7 +476,7 @@
dir := ctx.OtherModuleDir(module)
qualified := qualifiedModuleName{dir, moduleName}
- rule := effectiveVisibilityRules(ctx, qualified)
+ rule := effectiveVisibilityRules(ctx.Config(), qualified)
return rule.Strings()
}
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 6006072..8dd6a8f 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -1,15 +1,17 @@
package android
import (
+ "reflect"
"testing"
"github.com/google/blueprint"
)
var visibilityTests = []struct {
- name string
- fs map[string][]byte
- expectedErrors []string
+ name string
+ fs map[string][]byte
+ expectedErrors []string
+ effectiveVisibility map[qualifiedModuleName][]string
}{
{
name: "invalid visibility: empty list",
@@ -493,6 +495,9 @@
deps: ["libexample"],
}`),
},
+ effectiveVisibility: map[qualifiedModuleName][]string{
+ qualifiedModuleName{pkg: "top", name: "libexample"}: {"//visibility:public"},
+ },
},
{
name: "//visibility:public mixed with other from different defaults 1",
@@ -903,13 +908,27 @@
func TestVisibility(t *testing.T) {
for _, test := range visibilityTests {
t.Run(test.name, func(t *testing.T) {
- _, errs := testVisibility(buildDir, test.fs)
+ ctx, errs := testVisibility(buildDir, test.fs)
CheckErrorsAgainstExpectations(t, errs, test.expectedErrors)
+
+ if test.effectiveVisibility != nil {
+ checkEffectiveVisibility(t, ctx, test.effectiveVisibility)
+ }
})
}
}
+func checkEffectiveVisibility(t *testing.T, ctx *TestContext, effectiveVisibility map[qualifiedModuleName][]string) {
+ for moduleName, expectedRules := range effectiveVisibility {
+ rule := effectiveVisibilityRules(ctx.config, moduleName)
+ stringRules := rule.Strings()
+ if !reflect.DeepEqual(expectedRules, stringRules) {
+ t.Errorf("effective rules mismatch: expected %q, found %q", expectedRules, stringRules)
+ }
+ }
+}
+
func testVisibility(buildDir string, fs map[string][]byte) (*TestContext, []error) {
// Create a new config per test as visibility information is stored in the config.
diff --git a/android/vts_config.go b/android/vts_config.go
index 86f6e72..9a1df7c 100644
--- a/android/vts_config.go
+++ b/android/vts_config.go
@@ -17,6 +17,7 @@
import (
"fmt"
"io"
+ "strings"
)
func init() {
@@ -26,6 +27,8 @@
type vtsConfigProperties struct {
// Override the default (AndroidTest.xml) test manifest file name.
Test_config *string
+ // Additional test suites to add the test to.
+ Test_suites []string `android:"arch_variant"`
}
type VtsConfig struct {
@@ -50,7 +53,8 @@
fmt.Fprintf(w, "LOCAL_TEST_CONFIG := %s\n",
*me.properties.Test_config)
}
- fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE := vts")
+ fmt.Fprintf(w, "LOCAL_COMPATIBILITY_SUITE := vts %s\n",
+ strings.Join(me.properties.Test_suites, " "))
},
}
return androidMkData
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 8860984..b7c54b1 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -383,11 +383,15 @@
if err != nil {
return err
}
- if val.(*bpparser.Bool).Value {
+ boolValue, ok := val.(*bpparser.Bool)
+ if !ok {
+ return fmt.Errorf("value should evaluate to boolean literal")
+ }
+ if boolValue.Value {
thirtyTwo := &bpparser.String{
Value: "32",
}
- setVariable(ctx.file, false, ctx.prefix, "compile_multilib", thirtyTwo, true)
+ return setVariable(ctx.file, false, ctx.prefix, "compile_multilib", thirtyTwo, true)
}
return nil
}
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 7e1a72c..3e1d486 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1341,6 +1341,25 @@
}
`,
},
+ {
+ desc: "undefined_boolean_var",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= a.cpp
+LOCAL_MODULE:= test
+LOCAL_32_BIT_ONLY := $(FLAG)
+include $(BUILD_EXECUTABLE)
+`,
+ expected: `
+cc_binary {
+ name: "test",
+ srcs: ["a.cpp"],
+ // ANDROIDMK TRANSLATION ERROR: value should evaluate to boolean literal
+ // LOCAL_32_BIT_ONLY := $(FLAG)
+
+}
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 8929910..5c15e8e 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -42,7 +42,11 @@
}}
}
-func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string) []string {
+func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, moduleDir string) []string {
+ // apexBundleName comes from the 'name' property; apexName comes from 'apex_name' property.
+ // An apex is installed to /system/apex/<apexBundleName> and is activated at /apex/<apexName>
+ // In many cases, the two names are the same, but could be different in general.
+
moduleNames := []string{}
apexType := a.properties.ApexType
// To avoid creating duplicate build rules, run this function only when primaryApexType is true
@@ -52,12 +56,21 @@
return moduleNames
}
+ // b/140136207. When there are overriding APEXes for a VNDK APEX, the symbols file for the overridden
+ // APEX and the overriding APEX will have the same installation paths at /apex/com.android.vndk.v<ver>
+ // as their apexName will be the same. To avoid the path conflicts, skip installing the symbol files
+ // for the overriding VNDK APEXes.
+ symbolFilesNotNeeded := a.vndkApex && len(a.overridableProperties.Overrides) > 0
+ if symbolFilesNotNeeded && apexType != flattenedApex {
+ return moduleNames
+ }
+
var postInstallCommands []string
for _, fi := range a.filesInfo {
if a.linkToSystemLib && fi.transitiveDep && fi.AvailableToPlatform() {
// TODO(jiyong): pathOnDevice should come from fi.module, not being calculated here
linkTarget := filepath.Join("/system", fi.Path())
- linkPath := filepath.Join(a.installDir.ToMakePath().String(), apexName, fi.Path())
+ linkPath := filepath.Join(a.installDir.ToMakePath().String(), apexBundleName, fi.Path())
mkdirCmd := "mkdir -p " + filepath.Dir(linkPath)
linkCmd := "ln -sfn " + linkTarget + " " + linkPath
postInstallCommands = append(postInstallCommands, mkdirCmd, linkCmd)
@@ -75,7 +88,7 @@
if linkToSystemLib {
moduleName = fi.moduleName
} else {
- moduleName = fi.moduleName + "." + apexName + a.suffix
+ moduleName = fi.moduleName + "." + apexBundleName + a.suffix
}
if !android.InList(moduleName, moduleNames) {
@@ -99,16 +112,16 @@
if apexType == flattenedApex {
// /system/apex/<name>/{lib|framework|...}
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join(a.installDir.ToMakePath().String(),
- apexName, fi.installDir))
- if a.primaryApexType {
+ apexBundleName, fi.installDir))
+ if a.primaryApexType && !symbolFilesNotNeeded {
fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
}
if len(fi.symlinks) > 0 {
fmt.Fprintln(w, "LOCAL_MODULE_SYMLINKS :=", strings.Join(fi.symlinks, " "))
}
- if fi.module != nil && fi.module.NoticeFile().Valid() {
- fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", fi.module.NoticeFile().Path().String())
+ if fi.module != nil && len(fi.module.NoticeFiles()) > 0 {
+ fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(fi.module.NoticeFiles().Strings(), " "))
}
} else {
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", pathWhenActivated)
@@ -204,6 +217,12 @@
}
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
}
+
+ // m <module_name> will build <module_name>.<apex_name> as well.
+ if fi.moduleName != moduleName && a.primaryApexType {
+ fmt.Fprintln(w, ".PHONY: "+fi.moduleName)
+ fmt.Fprintln(w, fi.moduleName+": "+moduleName)
+ }
}
return moduleNames
}
@@ -236,7 +255,7 @@
apexType := a.properties.ApexType
if a.installable() {
apexName := proptools.StringDefault(a.properties.Apex_name, name)
- moduleNames = a.androidMkForFiles(w, apexName, moduleDir)
+ moduleNames = a.androidMkForFiles(w, name, apexName, moduleDir)
}
if apexType == flattenedApex {
@@ -289,7 +308,7 @@
}
if a.installedFilesFile != nil {
- goal := "droidcore"
+ goal := "checkbuild"
distFile := name + "-installed-files.txt"
fmt.Fprintln(w, ".PHONY:", goal)
fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
diff --git a/apex/apex.go b/apex/apex.go
index 53bdc12..c791162 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -45,18 +45,22 @@
type dependencyTag struct {
blueprint.BaseDependencyTag
name string
+
+ // determines if the dependent will be part of the APEX payload
+ payload bool
}
var (
- sharedLibTag = dependencyTag{name: "sharedLib"}
- executableTag = dependencyTag{name: "executable"}
- javaLibTag = dependencyTag{name: "javaLib"}
- prebuiltTag = dependencyTag{name: "prebuilt"}
- testTag = dependencyTag{name: "test"}
+ sharedLibTag = dependencyTag{name: "sharedLib", payload: true}
+ jniLibTag = dependencyTag{name: "jniLib", payload: true}
+ executableTag = dependencyTag{name: "executable", payload: true}
+ javaLibTag = dependencyTag{name: "javaLib", payload: true}
+ prebuiltTag = dependencyTag{name: "prebuilt", payload: true}
+ testTag = dependencyTag{name: "test", payload: true}
keyTag = dependencyTag{name: "key"}
certificateTag = dependencyTag{name: "certificate"}
usesTag = dependencyTag{name: "uses"}
- androidAppTag = dependencyTag{name: "androidApp"}
+ androidAppTag = dependencyTag{name: "androidApp", payload: true}
apexAvailWl = makeApexAvailableWhitelist()
)
@@ -70,107 +74,322 @@
//
// Module separator
//
- m["com.android.adbd"] = []string{"adbd", "libcrypto"}
+ m["com.android.adbd"] = []string{
+ "adbd",
+ "bcm_object",
+ "fmtlib",
+ "libadbconnection_server",
+ "libadbd",
+ "libadbd_auth",
+ "libadbd_core",
+ "libadbd_services",
+ "libasyncio",
+ "libbacktrace_headers",
+ "libbase",
+ "libbase_headers",
+ "libbuildversion",
+ "libc++",
+ "libcap",
+ "libcrypto",
+ "libcrypto_utils",
+ "libcutils",
+ "libcutils_headers",
+ "libdiagnose_usb",
+ "liblog_headers",
+ "libmdnssd",
+ "libminijail",
+ "libminijail_gen_constants",
+ "libminijail_gen_constants_obj",
+ "libminijail_gen_syscall",
+ "libminijail_gen_syscall_obj",
+ "libminijail_generated",
+ "libpackagelistparser",
+ "libpcre2",
+ "libprocessgroup_headers",
+ "libqemu_pipe",
+ "libselinux",
+ "libsystem_headers",
+ "libutils_headers",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.appsearch"] = []string{
+ "icing-java-proto-lite",
+ "libprotobuf-java-lite",
+ }
//
// Module separator
//
m["com.android.art"] = []string{
+ "art_cmdlineparser_headers",
+ "art_disassembler_headers",
+ "art_libartbase_headers",
+ "bcm_object",
+ "bionic_libc_platform_headers",
+ "core-repackaged-icu4j",
+ "cpp-define-generator-asm-support",
+ "cpp-define-generator-definitions",
+ "crtbegin_dynamic",
+ "crtbegin_dynamic1",
+ "crtbegin_so1",
+ "crtbrand",
+ "conscrypt.module.intra.core.api.stubs",
+ "dex2oat_headers",
+ "dt_fd_forward_export",
+ "fmtlib",
+ "icu4c_extra_headers",
"jacocoagent",
+ "javavm_headers",
+ "jni_platform_headers",
+ "libPlatformProperties",
+ "libadbconnection_client",
"libadbconnection_server",
+ "libandroidicuinit",
+ "libart_runtime_headers_ndk",
"libartd-disassembler",
+ "libasync_safe",
"libbacktrace",
"libbase",
+ "libbase_headers",
"libc++",
+ "libc++_static",
+ "libc++abi",
+ "libc++demangle",
+ "libc_headers",
"libcrypto",
+ "libdexfile_all_headers",
+ "libdexfile_external_headers",
"libdexfile_support",
+ "libdmabufinfo",
"libexpat",
+ "libfdlibm",
+ "libgtest_prod",
+ "libicui18n_headers",
"libicuuc",
+ "libicuuc_headers",
+ "libicuuc_stubdata",
+ "libjdwp_headers",
+ "liblog_headers",
+ "liblz4",
"liblzma",
"libmeminfo",
+ "libnativebridge-headers",
+ "libnativehelper_header_only",
+ "libnativeloader-headers",
+ "libnpt_headers",
+ "libopenjdkjvmti_headers",
+ "libperfetto_client_experimental",
"libprocinfo",
+ "libprotobuf-cpp-lite",
+ "libunwind_llvm",
"libunwindstack",
+ "libv8",
+ "libv8base",
+ "libv8gen",
+ "libv8platform",
+ "libv8sampler",
+ "libv8src",
"libvixl",
"libvixld",
"libz",
"libziparchive",
- "prebuilt_libclang_rt",
+ "perfetto_trace_protos",
}
//
// Module separator
//
m["com.android.bluetooth.updatable"] = []string{
"android.hardware.audio.common@5.0",
- "android.hardware.bluetooth@1.0",
- "android.hardware.bluetooth@1.1",
"android.hardware.bluetooth.a2dp@1.0",
"android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth@1.0",
+ "android.hardware.bluetooth@1.1",
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
+ "android.hardware.media@1.0",
"android.hidl.safe_union@1.0",
+ "android.hidl.token@1.0",
+ "android.hidl.token@1.0-utils",
+ "avrcp-target-service",
+ "avrcp_headers",
+ "bcm_object",
+ "bluetooth-protos-lite",
+ "bluetooth.mapsapi",
+ "com.android.vcard",
+ "fmtlib",
+ "guava",
+ "internal_include_headers",
+ "lib-bt-packets",
+ "lib-bt-packets-avrcp",
+ "lib-bt-packets-base",
+ "libFraunhoferAAC",
+ "libaudio-a2dp-hw-utils",
+ "libaudio-hearing-aid-hw-utils",
+ "libbacktrace_headers",
"libbase",
- "libbinderthreadstate",
+ "libbase_headers",
+ "libbinder_headers",
"libbluetooth",
+ "libbluetooth-types",
+ "libbluetooth-types-header",
+ "libbluetooth_gd",
+ "libbluetooth_headers",
"libbluetooth_jni",
+ "libbt-audio-hal-interface",
+ "libbt-bta",
+ "libbt-common",
+ "libbt-hci",
+ "libbt-platform-protos-lite",
+ "libbt-protos-lite",
+ "libbt-sbc-decoder",
+ "libbt-sbc-encoder",
+ "libbt-stack",
+ "libbt-utils",
+ "libbtcore",
+ "libbtdevice",
+ "libbte",
+ "libbtif",
"libc++",
"libchrome",
"libcrypto",
"libcutils",
+ "libcutils_headers",
"libevent",
"libfmq",
+ "libg722codec",
+ "libgtest_prod",
+ "libgui_headers",
"libhidlbase",
+ "libhidlbase-impl-internal",
+ "libhidltransport-impl-internal",
+ "libhwbinder-impl-internal",
+ "libjsoncpp",
+ "liblog_headers",
+ "libmedia_headers",
+ "libmodpb64",
+ "libosi",
"libprocessgroup",
+ "libprocessgroup_headers",
"libprotobuf-cpp-lite",
+ "libprotobuf-java-lite",
+ "libprotobuf-java-micro",
+ "libstagefright_foundation_headers",
+ "libstagefright_headers",
"libstatslog",
+ "libstatssocket",
+ "libsystem_headers",
"libtinyxml2",
- "libutils",
+ "libudrv-uipc",
+ "libutils_headers",
"libz",
+ "media_plugin_headers",
+ "sap-api-java-static",
+ "services.net",
}
//
// Module separator
//
- m["com.android.conscrypt"] = []string{"boringssl_self_test", "libc++", "libcrypto", "libssl"}
+ m["com.android.cellbroadcast"] = []string{"CellBroadcastApp", "CellBroadcastServiceModule"}
//
// Module separator
//
- m["com.android.cronet"] = []string{"org.chromium.net.cronet", "prebuilt_libcronet.80.0.3986.0"}
+ m["com.android.conscrypt"] = []string{
+ "bcm_object",
+ "boringssl_self_test",
+ "libc++",
+ "libcrypto",
+ "libnativehelper_header_only",
+ "libssl",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.extservices"] = []string{
+ "flatbuffer_headers",
+ "liblua",
+ "libtextclassifier",
+ "libtextclassifier_hash_static",
+ "libtflite_static",
+ "libutf",
+ "libz_current",
+ "tensorflow_headers",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.cronet"] = []string{
+ "cronet_impl_common_java",
+ "cronet_impl_native_java",
+ "cronet_impl_platform_java",
+ "libcronet.80.0.3986.0",
+ "org.chromium.net.cronet",
+ "prebuilt_libcronet.80.0.3986.0",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.neuralnetworks"] = []string{
+ "android.hardware.neuralnetworks@1.0",
+ "android.hardware.neuralnetworks@1.1",
+ "android.hardware.neuralnetworks@1.2",
+ "android.hardware.neuralnetworks@1.3",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory.token@1.0",
+ "android.hidl.memory@1.0",
+ "android.hidl.safe_union@1.0",
+ "bcm_object",
+ "fmtlib",
+ "gemmlowp_headers",
+ "libarect",
+ "libbacktrace_headers",
+ "libbase",
+ "libbase_headers",
+ "libbuildversion",
+ "libc++",
+ "libcrypto",
+ "libcrypto_static",
+ "libcutils",
+ "libcutils_headers",
+ "libeigen",
+ "libfmq",
+ "libhidlbase",
+ "libhidlbase-impl-internal",
+ "libhidlmemory",
+ "libhidltransport-impl-internal",
+ "libhwbinder-impl-internal",
+ "libjsoncpp",
+ "liblog_headers",
+ "libmath",
+ "libneuralnetworks_common",
+ "libneuralnetworks_headers",
+ "libprocessgroup",
+ "libprocessgroup_headers",
+ "libprocpartition",
+ "libsync",
+ "libsystem_headers",
+ "libtextclassifier_hash",
+ "libtextclassifier_hash_headers",
+ "libtextclassifier_hash_static",
+ "libtflite_kernel_utils",
+ "libutils_headers",
+ "philox_random",
+ "philox_random_headers",
+ "tensorflow_headers",
+ }
//
// Module separator
//
m["com.android.media"] = []string{
- "android.hardware.cas@1.0",
- "android.hardware.cas.native@1.0",
- "android.hidl.allocator@1.0",
- "android.hidl.memory@1.0",
- "android.hidl.memory.token@1.0",
- "android.hidl.token@1.0",
- "android.hidl.token@1.0-utils",
- "libaacextractor",
- "libamrextractor",
- "libbase",
- "libbinderthreadstate",
- "libc++",
- "libcrypto",
- "libcutils",
- "libflacextractor",
- "libhidlbase",
- "libhidlmemory",
- "libmidiextractor",
- "libmkvextractor",
- "libmp3extractor",
- "libmp4extractor",
- "libmpeg2extractor",
- "liboggextractor",
- "libprocessgroup",
- "libutils",
- "libwavextractor",
- "updatable-media",
- }
- //
- // Module separator
- //
- m["com.android.media.swcodec"] = []string{
"android.frameworks.bufferhub@1.0",
+ "android.hardware.cas.native@1.0",
+ "android.hardware.cas@1.0",
+ "android.hardware.configstore-utils",
"android.hardware.configstore@1.0",
"android.hardware.configstore@1.1",
- "android.hardware.configstore-utils",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.bufferqueue@1.0",
@@ -181,23 +400,196 @@
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
+ "android.hardware.media.omx@1.0",
"android.hardware.media@1.0",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory.token@1.0",
+ "android.hidl.memory@1.0",
+ "android.hidl.token@1.0",
+ "android.hidl.token@1.0-utils",
+ "bcm_object",
+ "bionic_libc_platform_headers",
+ "fmtlib",
+ "gl_headers",
+ "libEGL",
+ "libEGL_blobCache",
+ "libEGL_getProcAddress",
+ "libFLAC",
+ "libFLAC-config",
+ "libFLAC-headers",
+ "libGLESv2",
+ "libaacextractor",
+ "libamrextractor",
+ "libarect",
+ "libasync_safe",
+ "libaudio_system_headers",
+ "libaudioclient",
+ "libaudioclient_headers",
+ "libaudiofoundation",
+ "libaudiofoundation_headers",
+ "libaudiomanager",
+ "libaudiopolicy",
+ "libaudioutils",
+ "libaudioutils_fixedfft",
+ "libbacktrace",
+ "libbacktrace_headers",
+ "libbase",
+ "libbase_headers",
+ "libbinder_headers",
+ "libbluetooth-types-header",
+ "libbufferhub",
+ "libbufferhub_headers",
+ "libbufferhubqueue",
+ "libc++",
+ "libc_headers",
+ "libc_malloc_debug_backtrace",
+ "libcamera_client",
+ "libcamera_metadata",
+ "libcrypto",
+ "libcutils",
+ "libcutils_headers",
+ "libdexfile_external_headers",
+ "libdexfile_support",
+ "libdvr_headers",
+ "libexpat",
+ "libfifo",
+ "libflacextractor",
+ "libgrallocusage",
+ "libgraphicsenv",
+ "libgui",
+ "libgui_headers",
+ "libhardware_headers",
+ "libhidlbase",
+ "libhidlbase-impl-internal",
+ "libhidlmemory",
+ "libhidltransport-impl-internal",
+ "libhwbinder-impl-internal",
+ "libinput",
+ "libjsoncpp",
+ "liblog_headers",
+ "liblzma",
+ "libmath",
+ "libmedia",
+ "libmedia_codeclist",
+ "libmedia_headers",
+ "libmedia_helper",
+ "libmedia_helper_headers",
+ "libmedia_midiiowrapper",
+ "libmedia_omx",
+ "libmediautils",
+ "libmidiextractor",
+ "libmkvextractor",
+ "libmp3extractor",
+ "libmp4extractor",
+ "libmpeg2extractor",
+ "libnativebase_headers",
+ "libnativebridge-headers",
+ "libnativebridge_lazy",
+ "libnativeloader-headers",
+ "libnativeloader_lazy",
+ "libnativewindow_headers",
+ "libnblog",
+ "liboggextractor",
+ "libpackagelistparser",
+ "libpcre2",
+ "libpdx",
+ "libpdx_default_transport",
+ "libpdx_headers",
+ "libpdx_uds",
+ "libprocessgroup",
+ "libprocessgroup_headers",
+ "libprocinfo",
+ "libselinux",
+ "libsonivox",
+ "libspeexresampler",
+ "libspeexresampler",
+ "libstagefright_esds",
+ "libstagefright_flacdec",
+ "libstagefright_flacdec",
+ "libstagefright_foundation",
+ "libstagefright_foundation_headers",
+ "libstagefright_foundation_without_imemory",
+ "libstagefright_headers",
+ "libstagefright_id3",
+ "libstagefright_metadatautils",
+ "libstagefright_mpeg2extractor",
+ "libstagefright_mpeg2support",
+ "libsync",
+ "libsystem_headers",
+ "libui",
+ "libui_headers",
+ "libunwindstack",
+ "libutils_headers",
+ "libvibrator",
+ "libvorbisidec",
+ "libwavextractor",
+ "libwebm",
+ "media_ndk_headers",
+ "media_plugin_headers",
+ "updatable-media",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.media.swcodec"] = []string{
+ "android.frameworks.bufferhub@1.0",
+ "android.hardware.common-ndk_platform",
+ "android.hardware.configstore-utils",
+ "android.hardware.configstore@1.0",
+ "android.hardware.configstore@1.1",
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.graphics.common-ndk_platform",
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.1",
+ "android.hardware.graphics.mapper@3.0",
+ "android.hardware.graphics.mapper@4.0",
"android.hardware.media.bufferpool@2.0",
"android.hardware.media.c2@1.0",
"android.hardware.media.omx@1.0",
- "android.hidl.memory@1.0",
+ "android.hardware.media@1.0",
+ "android.hardware.media@1.0",
"android.hidl.memory.token@1.0",
+ "android.hidl.memory@1.0",
"android.hidl.safe_union@1.0",
"android.hidl.token@1.0",
"android.hidl.token@1.0-utils",
+ "fmtlib",
+ "libEGL",
+ "libFLAC",
+ "libFLAC-config",
+ "libFLAC-headers",
+ "libFraunhoferAAC",
+ "libarect",
+ "libasync_safe",
+ "libaudio_system_headers",
+ "libaudioutils",
+ "libaudioutils",
+ "libaudioutils_fixedfft",
+ "libavcdec",
+ "libavcenc",
+ "libavservices_minijail",
"libavservices_minijail",
"libbacktrace",
+ "libbacktrace_headers",
"libbase",
- "libbinderthreadstate",
+ "libbase_headers",
+ "libbinder_headers",
+ "libbluetooth-types-header",
+ "libbufferhub_headers",
"libc++",
+ "libc_scudo",
"libcap",
"libcodec2",
+ "libcodec2_headers",
"libcodec2_hidl@1.0",
+ "libcodec2_hidl@1.1",
+ "libcodec2_internal",
"libcodec2_soft_aacdec",
"libcodec2_soft_aacenc",
"libcodec2_soft_amrnbdec",
@@ -230,73 +622,373 @@
"libcodec2_soft_vp9dec",
"libcodec2_soft_vp9enc",
"libcodec2_vndk",
- "libc_scudo",
"libcutils",
+ "libcutils_headers",
"libdexfile_support",
- "libEGL",
+ "libdvr_headers",
"libfmq",
+ "libfmq",
+ "libgav1",
+ "libgralloctypes",
+ "libgrallocusage",
"libgraphicsenv",
+ "libgsm",
+ "libgui_bufferqueue_static",
+ "libgui_headers",
"libhardware",
+ "libhardware_headers",
+ "libhevcdec",
+ "libhevcenc",
"libhidlbase",
+ "libhidlbase-impl-internal",
"libhidlmemory",
+ "libhidltransport-impl-internal",
+ "libhwbinder-impl-internal",
"libion",
+ "libjpeg",
+ "libjsoncpp",
+ "liblog_headers",
"liblzma",
+ "libmath",
"libmedia_codecserviceregistrant",
+ "libmedia_headers",
"libminijail",
+ "libminijail_gen_constants",
+ "libminijail_gen_constants_obj",
+ "libminijail_gen_syscall",
+ "libminijail_gen_syscall_obj",
+ "libminijail_generated",
+ "libmpeg2dec",
+ "libnativebase_headers",
"libnativebridge_lazy",
"libnativeloader_lazy",
+ "libnativewindow_headers",
"libopus",
+ "libpdx_headers",
"libprocessgroup",
+ "libprocessgroup_headers",
"libscudo_wrapper",
"libsfplugin_ccodec_utils",
"libstagefright_amrnb_common",
+ "libstagefright_amrnbdec",
+ "libstagefright_amrnbenc",
+ "libstagefright_amrwbdec",
+ "libstagefright_amrwbenc",
"libstagefright_bufferpool@2.0.1",
"libstagefright_bufferqueue_helper",
"libstagefright_enc_common",
"libstagefright_flacdec",
"libstagefright_foundation",
+ "libstagefright_foundation_headers",
+ "libstagefright_headers",
+ "libstagefright_m4vh263dec",
+ "libstagefright_m4vh263enc",
+ "libstagefright_mp3dec",
"libsync",
+ "libsystem_headers",
"libui",
+ "libui_headers",
"libunwindstack",
- "libutils",
+ "libutils_headers",
"libvorbisidec",
"libvpx",
+ "libyuv",
+ "libyuv_static",
+ "media_ndk_headers",
+ "media_plugin_headers",
"mediaswcodec",
- "prebuilt_libclang_rt",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.mediaprovider"] = []string{
+ "MediaProvider",
+ "MediaProviderGoogle",
+ "fmtlib_ndk",
+ "guava",
+ "libbase_ndk",
+ "libfuse",
+ "libfuse_jni",
+ "libnativehelper_header_only",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.permission"] = []string{
+ "androidx.annotation_annotation",
+ "androidx.annotation_annotation-nodeps",
+ "androidx.lifecycle_lifecycle-common",
+ "androidx.lifecycle_lifecycle-common-java8",
+ "androidx.lifecycle_lifecycle-common-java8-nodeps",
+ "androidx.lifecycle_lifecycle-common-nodeps",
+ "kotlin-annotations",
+ "kotlin-stdlib",
+ "kotlin-stdlib-jdk7",
+ "kotlin-stdlib-jdk8",
+ "kotlinx-coroutines-android",
+ "kotlinx-coroutines-android-nodeps",
+ "kotlinx-coroutines-core",
+ "kotlinx-coroutines-core-nodeps",
+ "libprotobuf-java-lite",
+ "permissioncontroller-statsd",
}
//
// Module separator
//
m["com.android.runtime"] = []string{
+ "bionic_libc_platform_headers",
+ "fmtlib",
+ "libarm-optimized-routines-math",
+ "libasync_safe",
+ "libasync_safe_headers",
+ "libbacktrace_headers",
+ "libbase",
+ "libbase_headers",
+ "libc++",
+ "libc_aeabi",
+ "libc_bionic",
+ "libc_bionic_ndk",
+ "libc_bootstrap",
+ "libc_common",
+ "libc_common_shared",
+ "libc_common_static",
+ "libc_dns",
+ "libc_dynamic_dispatch",
+ "libc_fortify",
+ "libc_freebsd",
+ "libc_freebsd_large_stack",
+ "libc_gdtoa",
+ "libc_headers",
+ "libc_init_dynamic",
+ "libc_init_static",
+ "libc_jemalloc_wrapper",
+ "libc_netbsd",
+ "libc_nomalloc",
+ "libc_nopthread",
+ "libc_openbsd",
+ "libc_openbsd_large_stack",
+ "libc_openbsd_ndk",
+ "libc_pthread",
+ "libc_static_dispatch",
+ "libc_syscalls",
+ "libc_tzcode",
+ "libc_unwind_static",
+ "libcutils",
+ "libcutils_headers",
+ "libdebuggerd",
+ "libdebuggerd_common_headers",
+ "libdebuggerd_handler_core",
+ "libdebuggerd_handler_fallback",
+ "libdexfile_external_headers",
+ "libdexfile_support",
+ "libdexfile_support_static",
+ "libgtest_prod",
+ "libjemalloc5",
+ "liblinker_main",
+ "liblinker_malloc",
+ "liblog_headers",
+ "liblz4",
+ "liblzma",
+ "libprocessgroup_headers",
+ "libprocinfo",
+ "libpropertyinfoparser",
+ "libscudo",
+ "libstdc++",
+ "libsystem_headers",
+ "libsystemproperties",
+ "libtombstoned_client_static",
+ "libunwindstack",
+ "libutils_headers",
+ "libz",
+ "libziparchive",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.resolv"] = []string{
+ "bcm_object",
+ "dnsresolver_aidl_interface-unstable-ndk_platform",
+ "fmtlib",
+ "libbacktrace_headers",
+ "libbase",
+ "libbase_headers",
+ "libc++",
+ "libcrypto",
+ "libcutils",
+ "libcutils_headers",
+ "libgtest_prod",
+ "libjsoncpp",
+ "liblog_headers",
+ "libnativehelper_header_only",
+ "libnetd_client_headers",
+ "libnetd_resolv",
+ "libnetdutils",
+ "libprocessgroup",
+ "libprocessgroup_headers",
+ "libprotobuf-cpp-lite",
+ "libssl",
+ "libstatslog_resolv",
+ "libstatspush_compat",
+ "libstatssocket",
+ "libstatssocket_headers",
+ "libsystem_headers",
+ "libsysutils",
+ "libutils_headers",
+ "netd_event_listener_interface-ndk_platform",
+ "server_configurable_flags",
+ "stats_proto",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.tethering"] = []string{
"libbase",
"libc++",
- "libdexfile_support",
- "liblzma",
- "libunwindstack",
- "prebuilt_libclang_rt",
+ "libnativehelper_compat_libc++",
+ "android.hardware.tetheroffload.config@1.0",
+ "fmtlib",
+ "libbacktrace_headers",
+ "libbase_headers",
+ "libcgrouprc",
+ "libcgrouprc_format",
+ "libcutils",
+ "libcutils_headers",
+ "libhidlbase",
+ "libhidlbase-impl-internal",
+ "libhidltransport-impl-internal",
+ "libhwbinder-impl-internal",
+ "libjsoncpp",
+ "liblog_headers",
+ "libprocessgroup",
+ "libprocessgroup_headers",
+ "libsystem_headers",
+ "libtetherutilsjni",
+ "libutils_headers",
+ "libvndksupport",
+ "tethering-aidl-interfaces-java",
}
//
// Module separator
//
- m["com.android.resolv"] = []string{"libcrypto", "libnetd_resolv", "libssl"}
- //
- // Module separator
- //
- m["com.android.tethering"] = []string{"libbase", "libc++", "libnativehelper_compat_libc++"}
- //
- // Module separator
- //
- m["com.android.vndk"] = []string{
- "libbacktrace",
- "libbinderthreadstate",
- "libblas",
- "libcompiler_rt",
- "libgui",
- "libunwind",
+ m["com.android.wifi"] = []string{
+ "PlatformProperties",
+ "android.hardware.wifi-V1.0-java",
+ "android.hardware.wifi-V1.1-java",
+ "android.hardware.wifi-V1.2-java",
+ "android.hardware.wifi-V1.3-java",
+ "android.hardware.wifi-V1.4-java",
+ "android.hardware.wifi.hostapd-V1.0-java",
+ "android.hardware.wifi.hostapd-V1.1-java",
+ "android.hardware.wifi.hostapd-V1.2-java",
+ "android.hardware.wifi.supplicant-V1.0-java",
+ "android.hardware.wifi.supplicant-V1.1-java",
+ "android.hardware.wifi.supplicant-V1.2-java",
+ "android.hardware.wifi.supplicant-V1.3-java",
+ "android.hidl.base-V1.0-java",
+ "android.hidl.manager-V1.0-java",
+ "android.hidl.manager-V1.1-java",
+ "android.hidl.manager-V1.2-java",
+ "androidx.annotation_annotation",
+ "androidx.annotation_annotation-nodeps",
+ "bouncycastle-unbundled",
+ "dnsresolver_aidl_interface-V2-java",
+ "error_prone_annotations",
+ "ipmemorystore-aidl-interfaces-V3-java",
+ "ipmemorystore-aidl-interfaces-java",
+ "ksoap2",
+ "libbacktrace_headers",
+ "libbase",
+ "libbase_headers",
+ "libc++",
+ "libcutils",
+ "libcutils_headers",
+ "liblog_headers",
+ "libnanohttpd",
+ "libprocessgroup",
+ "libprocessgroup_headers",
+ "libprotobuf-java-lite",
+ "libprotobuf-java-nano",
+ "libsystem_headers",
+ "libutils_headers",
+ "libwifi-jni",
+ "net-utils-services-common",
+ "netd_aidl_interface-V2-java",
+ "netd_aidl_interface-unstable-java",
+ "netd_event_listener_interface-java",
+ "netlink-client",
+ "networkstack-aidl-interfaces-unstable-java",
+ "networkstack-client",
+ "services.net",
+ "wifi-lite-protos",
+ "wifi-nano-protos",
+ "wifi-service-pre-jarjar",
+ "wifi-service-resources",
+ "prebuilt_androidx.annotation_annotation-nodeps",
}
//
// Module separator
//
+ m["com.android.sdkext"] = []string{
+ "fmtlib_ndk",
+ "libbase_ndk",
+ "libprotobuf-cpp-lite-ndk",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.os.statsd"] = []string{
+ "libbacktrace_headers",
+ "libbase_headers",
+ "libc++",
+ "libcutils",
+ "libcutils_headers",
+ "liblog_headers",
+ "libprocessgroup_headers",
+ "libstatssocket",
+ "libsystem_headers",
+ "libutils_headers",
+ }
+ //
+ // Module separator
+ //
+ m["//any"] = []string{
+ "crtbegin_dynamic",
+ "crtbegin_dynamic1",
+ "crtbegin_so",
+ "crtbegin_so1",
+ "crtbegin_static",
+ "crtbrand",
+ "crtend_android",
+ "crtend_so",
+ "libatomic",
+ "libc++_static",
+ "libc++abi",
+ "libc++demangle",
+ "libc_headers",
+ "libclang_rt",
+ "libgcc_stripped",
+ "libprofile-clang-extras",
+ "libprofile-clang-extras_ndk",
+ "libprofile-extras",
+ "libprofile-extras_ndk",
+ "libunwind_llvm",
+ "ndk_crtbegin_dynamic.27",
+ "ndk_crtbegin_so.16",
+ "ndk_crtbegin_so.19",
+ "ndk_crtbegin_so.21",
+ "ndk_crtbegin_so.24",
+ "ndk_crtbegin_so.27",
+ "ndk_crtend_android.27",
+ "ndk_crtend_so.16",
+ "ndk_crtend_so.19",
+ "ndk_crtend_so.21",
+ "ndk_crtend_so.24",
+ "ndk_crtend_so.27",
+ "ndk_libandroid_support",
+ "ndk_libc++_static",
+ "ndk_libc++abi",
+ "ndk_libunwind",
+ }
return m
}
@@ -324,7 +1016,7 @@
}
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("apex_deps", apexDepsMutator)
+ ctx.TopDown("apex_deps", apexDepsMutator)
ctx.BottomUp("apex", apexMutator).Parallel()
ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
@@ -332,29 +1024,29 @@
// Mark the direct and transitive dependencies of apex bundles so that they
// can be built for the apex bundles.
-func apexDepsMutator(mctx android.BottomUpMutatorContext) {
+func apexDepsMutator(mctx android.TopDownMutatorContext) {
+ var apexBundles []android.ApexInfo
+ var directDep bool
if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex {
- apexBundleName := mctx.ModuleName()
- mctx.WalkDeps(func(child, parent android.Module) bool {
- depName := mctx.OtherModuleName(child)
- // If the parent is apexBundle, this child is directly depended.
- _, directDep := parent.(*apexBundle)
- if a.installable() && !a.testApex {
- // TODO(b/123892969): Workaround for not having any way to annotate test-apexs
- // non-installable apex's cannot be installed and so should not prevent libraries from being
- // installed to the system.
- android.UpdateApexDependency(apexBundleName, depName, directDep)
- }
-
- if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() &&
- (directDep || am.DepIsInSameApex(mctx, child)) {
- am.BuildForApex(apexBundleName)
- return true
- } else {
- return false
- }
- })
+ apexBundles = []android.ApexInfo{{mctx.ModuleName(), proptools.Bool(a.properties.Legacy_android10_support)}}
+ directDep = true
+ } else if am, ok := mctx.Module().(android.ApexModule); ok {
+ apexBundles = am.ApexVariations()
+ directDep = false
}
+
+ if len(apexBundles) == 0 {
+ return
+ }
+
+ mctx.VisitDirectDeps(func(child android.Module) {
+ depName := mctx.OtherModuleName(child)
+ if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() &&
+ (directDep || am.DepIsInSameApex(mctx, child)) {
+ android.UpdateApexDependency(apexBundles, depName, directDep)
+ am.BuildForApexes(apexBundles)
+ }
+ })
}
// Create apex variations if a module is included in APEX(s).
@@ -464,10 +1156,13 @@
})
}
-type apexNativeDependencies struct {
+type ApexNativeDependencies struct {
// List of native libraries
Native_shared_libs []string
+ // List of JNI libraries
+ Jni_libs []string
+
// List of native executables
Binaries []string
@@ -477,19 +1172,19 @@
type apexMultilibProperties struct {
// Native dependencies whose compile_multilib is "first"
- First apexNativeDependencies
+ First ApexNativeDependencies
// Native dependencies whose compile_multilib is "both"
- Both apexNativeDependencies
+ Both ApexNativeDependencies
// Native dependencies whose compile_multilib is "prefer32"
- Prefer32 apexNativeDependencies
+ Prefer32 ApexNativeDependencies
// Native dependencies whose compile_multilib is "32"
- Lib32 apexNativeDependencies
+ Lib32 ApexNativeDependencies
// Native dependencies whose compile_multilib is "64"
- Lib64 apexNativeDependencies
+ Lib64 ApexNativeDependencies
}
type apexBundleProperties struct {
@@ -511,11 +1206,7 @@
// Default: /system/sepolicy/apex/<module_name>_file_contexts.
File_contexts *string `android:"path"`
- // List of native shared libs that are embedded inside this APEX bundle
- Native_shared_libs []string
-
- // List of executables that are embedded inside this APEX bundle
- Binaries []string
+ ApexNativeDependencies
// List of java libraries that are embedded inside this APEX bundle
Java_libs []string
@@ -523,9 +1214,6 @@
// List of prebuilt files that are embedded inside this APEX bundle
Prebuilts []string
- // List of tests that are embedded inside this APEX bundle
- Tests []string
-
// Name of the apex_key module that provides the private key to sign APEX
Key *string
@@ -584,6 +1272,14 @@
Legacy_android10_support *bool
IsCoverageVariant bool `blueprint:"mutated"`
+
+ // Whether this APEX is considered updatable or not. When set to true, this will enforce additional
+ // rules for making sure that the APEX is truely updatable. This will also disable the size optimizations
+ // like symlinking to the system libs. Default is false.
+ Updatable *bool
+
+ // The minimum SDK version that this apex must be compatibile with.
+ Min_sdk_version *string
}
type apexTargetBundleProperties struct {
@@ -620,6 +1316,9 @@
// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
// from PRODUCT_PACKAGES.
Overrides []string
+
+ // Logging Parent value
+ Logging_parent string
}
type apexPackaging int
@@ -711,6 +1410,8 @@
jacocoReportClassesFile android.Path // only for javalibs and apps
certificate java.Certificate // only for apps
+
+ isJniLib bool
}
func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, moduleName string, installDir string, class apexFileClass, module android.Module) apexFile {
@@ -758,6 +1459,12 @@
return false
}
+type depInfo struct {
+ to string
+ from []string
+ isExternal bool
+}
+
type apexBundle struct {
android.ModuleBase
android.DefaultableModuleBase
@@ -791,10 +1498,8 @@
// list of module names that should be installed along with this APEX
requiredDeps []string
- // list of module names that this APEX is depending on (to be shown via *-deps-info target)
- externalDeps []string
// list of module names that this APEX is including (to be shown via *-deps-info target)
- internalDeps []string
+ depInfos map[string]depInfo
testApex bool
vndkApex bool
@@ -825,7 +1530,7 @@
}
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
- native_shared_libs []string, binaries []string, tests []string,
+ nativeModules ApexNativeDependencies,
target android.Target, imageVariation string) {
// Use *FarVariation* to be able to depend on modules having
// conflicting variations with this module. This is required since
@@ -835,16 +1540,22 @@
{Mutator: "image", Variation: imageVariation},
{Mutator: "link", Variation: "shared"},
{Mutator: "version", Variation: ""}, // "" is the non-stub variant
- }...), sharedLibTag, native_shared_libs...)
+ }...), sharedLibTag, nativeModules.Native_shared_libs...)
+
+ ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
+ {Mutator: "image", Variation: imageVariation},
+ {Mutator: "link", Variation: "shared"},
+ {Mutator: "version", Variation: ""}, // "" is the non-stub variant
+ }...), jniLibTag, nativeModules.Jni_libs...)
ctx.AddFarVariationDependencies(append(target.Variations(),
blueprint.Variation{Mutator: "image", Variation: imageVariation}),
- executableTag, binaries...)
+ executableTag, nativeModules.Binaries...)
ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
{Mutator: "image", Variation: imageVariation},
{Mutator: "test_per_src", Variation: ""}, // "" is the all-tests variant
- }...), testTag, tests...)
+ }...), testTag, nativeModules.Tests...)
}
func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
@@ -877,41 +1588,39 @@
}
}
for i, target := range targets {
- // When multilib.* is omitted for native_shared_libs, it implies
- // multilib.both.
- ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
- {Mutator: "image", Variation: a.getImageVariation(config)},
- {Mutator: "link", Variation: "shared"},
- }...), sharedLibTag, a.properties.Native_shared_libs...)
-
- // When multilib.* is omitted for tests, it implies
- // multilib.both.
- ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
- {Mutator: "image", Variation: a.getImageVariation(config)},
- {Mutator: "test_per_src", Variation: ""}, // "" is the all-tests variant
- }...), testTag, a.properties.Tests...)
+ // When multilib.* is omitted for native_shared_libs/jni_libs/tests, it implies
+ // multilib.both
+ addDependenciesForNativeModules(ctx,
+ ApexNativeDependencies{
+ Native_shared_libs: a.properties.Native_shared_libs,
+ Tests: a.properties.Tests,
+ Jni_libs: a.properties.Jni_libs,
+ Binaries: nil,
+ },
+ target, a.getImageVariation(config))
// Add native modules targetting both ABIs
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Both.Native_shared_libs,
- a.properties.Multilib.Both.Binaries,
- a.properties.Multilib.Both.Tests,
+ a.properties.Multilib.Both,
target,
a.getImageVariation(config))
isPrimaryAbi := i == 0
if isPrimaryAbi {
// When multilib.* is omitted for binaries, it implies
- // multilib.first.
- ctx.AddFarVariationDependencies(append(target.Variations(),
- blueprint.Variation{Mutator: "image", Variation: a.getImageVariation(config)}),
- executableTag, a.properties.Binaries...)
+ // multilib.first
+ addDependenciesForNativeModules(ctx,
+ ApexNativeDependencies{
+ Native_shared_libs: nil,
+ Tests: nil,
+ Jni_libs: nil,
+ Binaries: a.properties.Binaries,
+ },
+ target, a.getImageVariation(config))
// Add native modules targetting the first ABI
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.First.Native_shared_libs,
- a.properties.Multilib.First.Binaries,
- a.properties.Multilib.First.Tests,
+ a.properties.Multilib.First,
target,
a.getImageVariation(config))
}
@@ -920,32 +1629,24 @@
case "lib32":
// Add native modules targetting 32-bit ABI
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Lib32.Native_shared_libs,
- a.properties.Multilib.Lib32.Binaries,
- a.properties.Multilib.Lib32.Tests,
+ a.properties.Multilib.Lib32,
target,
a.getImageVariation(config))
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Prefer32.Native_shared_libs,
- a.properties.Multilib.Prefer32.Binaries,
- a.properties.Multilib.Prefer32.Tests,
+ a.properties.Multilib.Prefer32,
target,
a.getImageVariation(config))
case "lib64":
// Add native modules targetting 64-bit ABI
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Lib64.Native_shared_libs,
- a.properties.Multilib.Lib64.Binaries,
- a.properties.Multilib.Lib64.Tests,
+ a.properties.Multilib.Lib64,
target,
a.getImageVariation(config))
if !has32BitTarget {
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Prefer32.Native_shared_libs,
- a.properties.Multilib.Prefer32.Binaries,
- a.properties.Multilib.Prefer32.Tests,
+ a.properties.Multilib.Prefer32,
target,
a.getImageVariation(config))
}
@@ -954,8 +1655,8 @@
for _, sanitizer := range ctx.Config().SanitizeDevice() {
if sanitizer == "hwaddress" {
addDependenciesForNativeModules(ctx,
- []string{"libclang_rt.hwasan-aarch64-android"},
- nil, nil, target, a.getImageVariation(config))
+ ApexNativeDependencies{[]string{"libclang_rt.hwasan-aarch64-android"}, nil, nil, nil},
+ target, a.getImageVariation(config))
break
}
}
@@ -1228,6 +1929,78 @@
return true
}
+// Visit dependencies that contributes to the payload of this APEX
+func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext,
+ do func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool)) {
+ ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
+ am, ok := child.(android.ApexModule)
+ if !ok || !am.CanHaveApexVariants() {
+ return false
+ }
+
+ // Check for the direct dependencies that contribute to the payload
+ if dt, ok := ctx.OtherModuleDependencyTag(child).(dependencyTag); ok {
+ if dt.payload {
+ do(ctx, parent, am, false /* externalDep */)
+ return true
+ }
+ return false
+ }
+
+ // Check for the indirect dependencies if it is considered as part of the APEX
+ if am.DepIsInSameApex(ctx, am) {
+ do(ctx, parent, am, false /* externalDep */)
+ return true
+ }
+
+ do(ctx, parent, am, true /* externalDep */)
+
+ // As soon as the dependency graph crosses the APEX boundary, don't go further.
+ return false
+ })
+}
+
+// Ensures that the dependencies are marked as available for this APEX
+func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
+ // Let's be practical. Availability for test, host, and the VNDK apex isn't important
+ if ctx.Host() || a.testApex || a.vndkApex {
+ return
+ }
+
+ a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+ apexName := ctx.ModuleName()
+ if externalDep || to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, to) {
+ return
+ }
+ ctx.ModuleErrorf("requires %q that is not available for the APEX.", to.Name())
+ })
+}
+
+// Collects the list of module names that directly or indirectly contributes to the payload of this APEX
+func (a *apexBundle) collectDepsInfo(ctx android.ModuleContext) {
+ a.depInfos = make(map[string]depInfo)
+ a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+ if from.Name() == to.Name() {
+ // This can happen for cc.reuseObjTag. We are not interested in tracking this.
+ return
+ }
+
+ if info, exists := a.depInfos[to.Name()]; exists {
+ if !android.InList(from.Name(), info.from) {
+ info.from = append(info.from, from.Name())
+ }
+ info.isExternal = info.isExternal && externalDep
+ a.depInfos[to.Name()] = info
+ } else {
+ a.depInfos[to.Name()] = depInfo{
+ to: to.Name(),
+ from: []string{from.Name()},
+ isExternal: externalDep,
+ }
+ }
+ })
+}
+
func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
switch a.properties.ApexType {
@@ -1263,6 +2036,10 @@
return
}
+ a.checkApexAvailability(ctx)
+
+ a.collectDepsInfo(ctx)
+
handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
// native lib dependencies
@@ -1294,23 +2071,29 @@
})
var filesInfo []apexFile
+ // TODO(jiyong) do this using walkPayloadDeps
ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
depTag := ctx.OtherModuleDependencyTag(child)
depName := ctx.OtherModuleName(child)
if _, isDirectDep := parent.(*apexBundle); isDirectDep {
- if depTag != keyTag && depTag != certificateTag {
- a.internalDeps = append(a.internalDeps, depName)
- }
switch depTag {
- case sharedLibTag:
- if cc, ok := child.(*cc.Module); ok {
- if cc.HasStubsVariants() {
- provideNativeLibs = append(provideNativeLibs, cc.OutputFile().Path().Base())
+ case sharedLibTag, jniLibTag:
+ isJniLib := depTag == jniLibTag
+ if c, ok := child.(*cc.Module); ok {
+ // bootstrap bionic libs are treated as provided by system
+ if c.HasStubsVariants() && !cc.InstallToBootstrap(c.BaseModuleName(), ctx.Config()) {
+ provideNativeLibs = append(provideNativeLibs, c.OutputFile().Path().Base())
}
- filesInfo = append(filesInfo, apexFileForNativeLibrary(ctx, cc, handleSpecialLibs))
+ fi := apexFileForNativeLibrary(ctx, c, handleSpecialLibs)
+ fi.isJniLib = isJniLib
+ filesInfo = append(filesInfo, fi)
return true // track transitive dependencies
} else {
- ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
+ propertyName := "native_shared_libs"
+ if isJniLib {
+ propertyName = "jni_libs"
+ }
+ ctx.PropertyErrorf(propertyName, "%q is not a cc_library or cc_library_shared module", depName)
}
case executableTag:
if cc, ok := child.(*cc.Module); ok {
@@ -1341,13 +2124,6 @@
return false
}
filesInfo = append(filesInfo, af)
-
- pf, _ := sdkLib.OutputFiles(".xml")
- if len(pf) != 1 {
- ctx.PropertyErrorf("java_libs", "%q failed to generate permission XML", depName)
- return false
- }
- filesInfo = append(filesInfo, newApexFile(ctx, pf[0], pf[0].Base(), "etc/permissions", etc, nil))
return true // track transitive dependencies
} else {
ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
@@ -1436,7 +2212,6 @@
if !android.DirectlyInAnyApex(ctx, cc.Name()) && !android.InList(cc.Name(), a.requiredDeps) {
a.requiredDeps = append(a.requiredDeps, cc.Name())
}
- a.externalDeps = append(a.externalDeps, depName)
requireNativeLibs = append(requireNativeLibs, cc.OutputFile().Path().Base())
// Don't track further
return false
@@ -1444,8 +2219,6 @@
af := apexFileForNativeLibrary(ctx, cc, handleSpecialLibs)
af.transitiveDep = true
filesInfo = append(filesInfo, af)
- a.internalDeps = append(a.internalDeps, depName)
- a.internalDeps = append(a.internalDeps, cc.AllStaticDeps()...)
return true // track transitive dependencies
}
} else if cc.IsTestPerSrcDepTag(depTag) {
@@ -1462,10 +2235,12 @@
return true // track transitive dependencies
}
} else if java.IsJniDepTag(depTag) {
- a.externalDeps = append(a.externalDeps, depName)
- return true
- } else if java.IsStaticLibDepTag(depTag) {
- a.internalDeps = append(a.internalDeps, depName)
+ // Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps
+ return false
+ } else if java.IsXmlPermissionsFileDepTag(depTag) {
+ if prebuilt, ok := child.(android.PrebuiltEtcModule); ok {
+ filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
+ }
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
ctx.ModuleErrorf("unexpected tag %q for indirect dependency %q", depTag, depName)
}
@@ -1520,23 +2295,6 @@
return filesInfo[i].builtFile.String() < filesInfo[j].builtFile.String()
})
- // check apex_available requirements
- if !ctx.Host() && !a.testApex {
- for _, fi := range filesInfo {
- if am, ok := fi.module.(android.ApexModule); ok {
- // vndk {enabled:true} implies visibility to the vndk apex
- if ccm, ok := fi.module.(*cc.Module); ok && ccm.IsVndk() && a.vndkApex {
- continue
- }
-
- if !am.AvailableFor(ctx.ModuleName()) && !whitelistedApexAvailable(ctx.ModuleName(), a.vndkApex, fi.module) {
- ctx.ModuleErrorf("requires %q that is not available for the APEX", fi.module.Name())
- // don't stop so that we can report other violations in the same run
- }
- }
- }
- }
-
a.installDir = android.PathForModuleInstall(ctx, "apex")
a.filesInfo = filesInfo
@@ -1565,6 +2323,17 @@
a.installable() &&
!proptools.Bool(a.properties.Use_vendor)
+ // We don't need the optimization for updatable APEXes, as it might give false signal
+ // to the system health when the APEXes are still bundled (b/149805758)
+ if proptools.Bool(a.properties.Updatable) && a.properties.ApexType == imageApex {
+ a.linkToSystemLib = false
+ }
+
+ // We also don't want the optimization for host APEXes, because it doesn't make sense.
+ if ctx.Host() {
+ a.linkToSystemLib = false
+ }
+
// prepare apex_manifest.json
a.buildManifest(ctx, provideNativeLibs, requireNativeLibs)
@@ -1580,22 +2349,31 @@
a.buildApexDependencyInfo(ctx)
}
-func whitelistedApexAvailable(apex string, is_vndk bool, module android.Module) bool {
+func whitelistedApexAvailable(apex string, module android.Module) bool {
key := apex
key = strings.Replace(key, "test_", "", 1)
key = strings.Replace(key, "com.android.art.debug", "com.android.art", 1)
key = strings.Replace(key, "com.android.art.release", "com.android.art", 1)
moduleName := module.Name()
- if strings.Contains(moduleName, "prebuilt_libclang_rt") {
- // This module has variants that depend on the product being built.
- moduleName = "prebuilt_libclang_rt"
+ // Prebuilt modules (e.g. java_import, etc.) have "prebuilt_" prefix added by the build
+ // system. Trim the prefix for the check since they are confusing
+ moduleName = strings.TrimPrefix(moduleName, "prebuilt_")
+ if strings.HasPrefix(moduleName, "libclang_rt.") {
+ // This module has many arch variants that depend on the product being built.
+ // We don't want to list them all
+ moduleName = "libclang_rt"
}
if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
return true
}
+ key = "//any"
+ if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
+ return true
+ }
+
return false
}
@@ -1621,12 +2399,16 @@
return bundle
}
+// apex_test is an APEX for testing. The difference from the ordinary apex module type is that
+// certain compatibility checks such as apex_available are not done for apex_test.
func testApexBundleFactory() android.Module {
bundle := newApexBundle()
bundle.testApex = true
return bundle
}
+// apex packages other modules into an APEX file which is a packaging format for system-level
+// components like binaries, shared libraries, etc.
func BundleFactory() android.Module {
return newApexBundle()
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 22f0f6f..8c5ca8b 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -99,112 +99,6 @@
android.ClearApexDependency()
bp = bp + `
- toolchain_library {
- name: "libcompiler_rt-extras",
- src: "",
- vendor_available: true,
- recovery_available: true,
- }
-
- toolchain_library {
- name: "libatomic",
- src: "",
- vendor_available: true,
- recovery_available: true,
- native_bridge_supported: true,
- }
-
- toolchain_library {
- name: "libgcc",
- src: "",
- vendor_available: true,
- recovery_available: true,
- }
-
- toolchain_library {
- name: "libgcc_stripped",
- src: "",
- vendor_available: true,
- recovery_available: true,
- native_bridge_supported: true,
- }
-
- toolchain_library {
- name: "libclang_rt.builtins-aarch64-android",
- src: "",
- vendor_available: true,
- recovery_available: true,
- native_bridge_supported: true,
- }
-
- toolchain_library {
- name: "libclang_rt.builtins-arm-android",
- src: "",
- vendor_available: true,
- recovery_available: true,
- native_bridge_supported: true,
- }
-
- toolchain_library {
- name: "libclang_rt.builtins-x86_64-android",
- src: "",
- vendor_available: true,
- recovery_available: true,
- native_bridge_supported: true,
- }
-
- toolchain_library {
- name: "libclang_rt.builtins-i686-android",
- src: "",
- vendor_available: true,
- recovery_available: true,
- native_bridge_supported: true,
- }
-
- cc_object {
- name: "crtbegin_so",
- stl: "none",
- vendor_available: true,
- recovery_available: true,
- native_bridge_supported: true,
- }
-
- cc_object {
- name: "crtend_so",
- stl: "none",
- vendor_available: true,
- recovery_available: true,
- native_bridge_supported: true,
- }
-
- cc_object {
- name: "crtbegin_static",
- stl: "none",
- }
-
- cc_object {
- name: "crtend_android",
- stl: "none",
- }
-
- llndk_library {
- name: "libc",
- symbol_file: "",
- native_bridge_supported: true,
- }
-
- llndk_library {
- name: "libm",
- symbol_file: "",
- native_bridge_supported: true,
- }
-
- llndk_library {
- name: "libdl",
- symbol_file: "",
- native_bridge_supported: true,
- }
-
filegroup {
name: "myapex-file_contexts",
srcs: [
@@ -213,6 +107,8 @@
}
`
+ bp = bp + cc.GatherRequiredDepsForTest(android.Android)
+
bp = bp + java.GatherRequiredDepsForTest()
fs := map[string][]byte{
@@ -223,6 +119,7 @@
"apex_manifest.json": nil,
"AndroidManifest.xml": nil,
"system/sepolicy/apex/myapex-file_contexts": nil,
+ "system/sepolicy/apex/myapex.updatable-file_contexts": nil,
"system/sepolicy/apex/myapex2-file_contexts": nil,
"system/sepolicy/apex/otherapex-file_contexts": nil,
"system/sepolicy/apex/commonapex-file_contexts": nil,
@@ -258,6 +155,8 @@
"dummy.txt": nil,
}
+ cc.GatherRequiredFilesForTest(fs)
+
for _, handler := range handlers {
// The fs now needs to be populated before creating the config, call handlers twice
// for now, once to get any fs changes, and later after the config was created to
@@ -327,6 +226,14 @@
os.RemoveAll(buildDir)
}
+// ensure that 'result' equals 'expected'
+func ensureEquals(t *testing.T, result string, expected string) {
+ t.Helper()
+ if result != expected {
+ t.Errorf("%q != %q", expected, result)
+ }
+}
+
// ensure that 'result' contains 'expected'
func ensureContains(t *testing.T, result string, expected string) {
t.Helper()
@@ -453,7 +360,6 @@
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
- compile_dex: true,
static_libs: ["myotherjar"],
libs: ["mysharedjar"],
// TODO: remove //apex_available:platform
@@ -468,7 +374,11 @@
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
- compile_dex: true,
+ // TODO: remove //apex_available:platform
+ apex_available: [
+ "//apex_available:platform",
+ "myapex",
+ ],
}
java_library {
@@ -476,7 +386,6 @@
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
- compile_dex: true,
}
`)
@@ -544,10 +453,11 @@
ensureListContains(t, noticeInputs, "custom_notice")
depsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("myapex-deps-info.txt").Args["content"], "\\n")
- ensureListContains(t, depsInfo, "internal myjar")
- ensureListContains(t, depsInfo, "internal mylib")
- ensureListContains(t, depsInfo, "internal mylib2")
- ensureListContains(t, depsInfo, "internal myotherjar")
+ ensureListContains(t, depsInfo, "myjar <- myapex")
+ ensureListContains(t, depsInfo, "mylib <- myapex")
+ ensureListContains(t, depsInfo, "mylib2 <- mylib")
+ ensureListContains(t, depsInfo, "myotherjar <- myjar")
+ ensureListContains(t, depsInfo, "mysharedjar (external) <- myjar")
}
func TestDefaults(t *testing.T) {
@@ -589,7 +499,6 @@
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
- compile_dex: true,
apex_available: [ "myapex" ],
}
@@ -760,7 +669,7 @@
ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12_myapex/mylib3.so")
// Ensure that stubs libs are built without -include flags
- mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+ mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylib2Cflags, "-include ")
// Ensure that genstub is invoked with --apex
@@ -791,6 +700,7 @@
name: "mylib",
srcs: ["mylib.cpp"],
shared_libs: ["libfoo#10"],
+ static_libs: ["libbaz"],
system_shared_libs: [],
stl: "none",
apex_available: [ "myapex2" ],
@@ -814,6 +724,14 @@
stl: "none",
}
+ cc_library_static {
+ name: "libbaz",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex2" ],
+ }
+
`)
apexRule := ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Rule("apexRule")
@@ -841,10 +759,10 @@
ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
depsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("myapex2-deps-info.txt").Args["content"], "\\n")
- ensureListContains(t, depsInfo, "internal mylib")
- ensureListContains(t, depsInfo, "external libfoo")
- ensureListNotContains(t, depsInfo, "internal libfoo")
- ensureListNotContains(t, depsInfo, "external mylib")
+
+ ensureListContains(t, depsInfo, "mylib <- myapex2")
+ ensureListContains(t, depsInfo, "libbaz <- mylib")
+ ensureListContains(t, depsInfo, "libfoo (external) <- mylib")
}
func TestApexWithRuntimeLibsDependency(t *testing.T) {
@@ -886,6 +804,7 @@
stubs: {
versions: ["10", "20", "30"],
},
+ apex_available: [ "myapex" ],
}
cc_library {
@@ -1001,47 +920,6 @@
}
cc_library {
- name: "libc",
- no_libcrt: true,
- nocrt: true,
- system_shared_libs: [],
- stl: "none",
- stubs: {
- versions: ["27", "28", "29"],
- },
- }
-
- cc_library {
- name: "libm",
- no_libcrt: true,
- nocrt: true,
- system_shared_libs: [],
- stl: "none",
- stubs: {
- versions: ["27", "28", "29"],
- },
- apex_available: [
- "//apex_available:platform",
- "myapex"
- ],
- }
-
- cc_library {
- name: "libdl",
- no_libcrt: true,
- nocrt: true,
- system_shared_libs: [],
- stl: "none",
- stubs: {
- versions: ["27", "28", "29"],
- },
- apex_available: [
- "//apex_available:platform",
- "myapex"
- ],
- }
-
- cc_library {
name: "libBootstrap",
srcs: ["mylib.cpp"],
stl: "none",
@@ -1573,6 +1451,7 @@
export_include_dirs: ["my_include"],
system_shared_libs: [],
stl: "none",
+ apex_available: [ "myapex" ],
}
cc_library {
@@ -1661,13 +1540,17 @@
var surplus []string
filesMatched := make(map[string]bool)
for _, file := range getFiles(t, ctx, moduleName, variant) {
+ mactchFound := false
for _, expected := range files {
if matched, _ := path.Match(expected, file.path); matched {
filesMatched[expected] = true
- return
+ mactchFound = true
+ break
}
}
- surplus = append(surplus, file.path)
+ if !mactchFound {
+ surplus = append(surplus, file.path)
+ }
}
if len(surplus) > 0 {
@@ -1734,8 +1617,10 @@
ensureExactContents(t, ctx, "myapex", "android_common_image", []string{
"lib/libvndk.so",
"lib/libvndksp.so",
+ "lib/libc++.so",
"lib64/libvndk.so",
"lib64/libvndksp.so",
+ "lib64/libc++.so",
"etc/llndk.libraries.VER.txt",
"etc/vndkcore.libraries.VER.txt",
"etc/vndksp.libraries.VER.txt",
@@ -1795,6 +1680,8 @@
"lib/libvndk.so",
"lib/libvndk.arm.so",
"lib64/libvndk.so",
+ "lib/libc++.so",
+ "lib64/libc++.so",
"etc/*",
})
}
@@ -2006,6 +1893,8 @@
ensureExactContents(t, ctx, "myapex", "android_common_image", []string{
"lib/libvndk.so",
"lib64/libvndk.so",
+ "lib/libc++.so",
+ "lib64/libc++.so",
"etc/*",
})
}
@@ -2210,11 +2099,12 @@
}
func TestApexName(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx, config := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
apex_name: "com.android.myapex",
+ native_shared_libs: ["mylib"],
}
apex_key {
@@ -2222,6 +2112,17 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [
+ "//apex_available:platform",
+ "myapex",
+ ],
+ }
`)
module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
@@ -2229,6 +2130,16 @@
ensureContains(t, apexManifestRule.Args["opt"], "-v name com.android.myapex")
apexRule := module.Rule("apexRule")
ensureContains(t, apexRule.Args["opt_flags"], "--do_not_check_keyname")
+
+ apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
+ data := android.AndroidMkDataForTest(t, config, "", apexBundle)
+ name := apexBundle.BaseModuleName()
+ prefix := "TARGET_"
+ var builder strings.Builder
+ data.Custom(&builder, name, prefix, "", data)
+ androidMk := builder.String()
+ ensureContains(t, androidMk, "LOCAL_MODULE := mylib.myapex\n")
+ ensureNotContains(t, androidMk, "LOCAL_MODULE := mylib.com.android.myapex\n")
}
func TestNonTestApex(t *testing.T) {
@@ -2332,11 +2243,6 @@
// Ensure that the platform variant ends with _shared
ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_shared")
-
- if android.InAnyApex("mylib_common_test") {
- t.Log("Found mylib_common_test in some apex!")
- t.Fail()
- }
}
func TestApexWithTarget(t *testing.T) {
@@ -2958,7 +2864,6 @@
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
- compile_dex: true,
enabled: false,
}
`)
@@ -2984,26 +2889,39 @@
android_app {
name: "AppFoo",
srcs: ["foo/bar/MyClass.java"],
- sdk_version: "none",
+ sdk_version: "current",
system_modules: "none",
jni_libs: ["libjni"],
+ stl: "none",
apex_available: [ "myapex" ],
}
android_app {
name: "AppFooPriv",
srcs: ["foo/bar/MyClass.java"],
- sdk_version: "none",
+ sdk_version: "current",
system_modules: "none",
privileged: true,
+ stl: "none",
apex_available: [ "myapex" ],
}
cc_library_shared {
name: "libjni",
srcs: ["mylib.cpp"],
+ shared_libs: ["libfoo"],
stl: "none",
system_shared_libs: [],
+ apex_available: [ "myapex" ],
+ sdk_version: "current",
+ }
+
+ cc_library_shared {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: [ "myapex" ],
+ sdk_version: "current",
}
`)
@@ -3014,16 +2932,19 @@
ensureContains(t, copyCmds, "image.apex/app/AppFoo/AppFoo.apk")
ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv/AppFooPriv.apk")
- // JNI libraries are embedded inside APK
- appZipRule := ctx.ModuleForTests("AppFoo", "android_common_myapex").Description("zip jni lib")
- libjniOutput := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared_myapex").Module().(*cc.Module).OutputFile()
- ensureListContains(t, appZipRule.Implicits.Strings(), libjniOutput.String())
- // ... uncompressed
+ appZipRule := ctx.ModuleForTests("AppFoo", "android_common_myapex").Description("zip jni libs")
+ // JNI libraries are uncompressed
if args := appZipRule.Args["jarArgs"]; !strings.Contains(args, "-L 0") {
- t.Errorf("jni lib is not uncompressed for AppFoo")
+ t.Errorf("jni libs are not uncompressed for AppFoo")
}
- // ... and not directly inside the APEX
- ensureNotContains(t, copyCmds, "image.apex/lib64/libjni.so")
+ // JNI libraries including transitive deps are
+ for _, jni := range []string{"libjni", "libfoo"} {
+ jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_shared_myapex").Module().(*cc.Module).OutputFile()
+ // ... embedded inside APK (jnilibs.zip)
+ ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String())
+ // ... and not directly inside the APEX
+ ensureNotContains(t, copyCmds, "image.apex/lib64/"+jni+".so")
+ }
}
func TestApexWithAppImports(t *testing.T) {
@@ -3259,10 +3180,15 @@
}`)
// check that libfoo and libbar are created only for myapex, but not for the platform
- ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
- ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
- ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_myapex")
- ensureListNotContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared")
+ // TODO(jiyong) the checks for the platform variant are removed because we now create
+ // the platform variant regardless of the apex_availability. Instead, we will make sure that
+ // the platform variants are not used from other platform modules. When that is done,
+ // these checks will be replaced by expecting a specific error message that will be
+ // emitted when the platform variant is used.
+ // ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
+ // ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
+ // ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_myapex")
+ // ensureListNotContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared")
ctx, _ = testApex(t, `
apex {
@@ -3311,11 +3237,16 @@
}`)
// shared variant of libfoo is only available to myapex
- ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
- ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
- // but the static variant is available to both myapex and the platform
- ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static_myapex")
- ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static")
+ // TODO(jiyong) the checks for the platform variant are removed because we now create
+ // the platform variant regardless of the apex_availability. Instead, we will make sure that
+ // the platform variants are not used from other platform modules. When that is done,
+ // these checks will be replaced by expecting a specific error message that will be
+ // emitted when the platform variant is used.
+ // ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
+ // ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
+ // // but the static variant is available to both myapex and the platform
+ // ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static_myapex")
+ // ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static")
}
func TestOverrideApex(t *testing.T) {
@@ -3332,6 +3263,7 @@
base: "myapex",
apps: ["override_app"],
overrides: ["unknownapex"],
+ logging_parent: "com.foo.bar",
}
apex_key {
@@ -3378,6 +3310,10 @@
t.Errorf("name should be \"override_myapex\", but was %q", name)
}
+ if apexBundle.overridableProperties.Logging_parent != "com.foo.bar" {
+ t.Errorf("override_myapex should have logging parent (com.foo.bar), but was %q.", apexBundle.overridableProperties.Logging_parent)
+ }
+
data := android.AndroidMkDataForTest(t, config, "", apexBundle)
var builder strings.Builder
data.Custom(&builder, name, "TARGET_", "", data)
@@ -3397,6 +3333,7 @@
apex {
name: "myapex",
key: "myapex.key",
+ native_shared_libs: ["mylib"],
legacy_android10_support: true,
}
@@ -3405,12 +3342,32 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
- `)
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ stl: "libc++",
+ system_shared_libs: [],
+ apex_available: [ "myapex" ],
+ }
+ `, withUnbundledBuild)
module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
args := module.Rule("apexRule").Args
ensureContains(t, args["opt_flags"], "--manifest_json "+module.Output("apex_manifest.json").Output.String())
ensureNotContains(t, args["opt_flags"], "--no_hashtree")
+
+ // The copies of the libraries in the apex should have one more dependency than
+ // the ones outside the apex, namely the unwinder. Ideally we should check
+ // the dependency names directly here but for some reason the names are blank in
+ // this test.
+ for _, lib := range []string{"libc++", "mylib"} {
+ apexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared_myapex").Rule("ld").Implicits
+ nonApexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld").Implicits
+ if len(apexImplicits) != len(nonApexImplicits)+1 {
+ t.Errorf("%q missing unwinder dep", lib)
+ }
+ }
}
func TestJavaSDKLibrary(t *testing.T) {
@@ -3448,8 +3405,8 @@
"etc/permissions/foo.xml",
})
// Permission XML should point to the activated path of impl jar of java_sdk_library
- xml := ctx.ModuleForTests("foo", "android_common_myapex").Output("foo.xml")
- ensureContains(t, xml.Args["content"], `<library name="foo" file="/apex/myapex/javalib/foo.jar"`)
+ sdkLibrary := ctx.ModuleForTests("foo.xml", "android_common_myapex").Rule("java_sdk_xml")
+ ensureContains(t, sdkLibrary.RuleParams.Command, `<library name=\"foo\" file=\"/apex/myapex/javalib/foo.jar\"`)
}
func TestCompatConfig(t *testing.T) {
@@ -3477,7 +3434,6 @@
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
- compile_dex: true,
apex_available: [ "myapex" ],
}
`)
@@ -3506,6 +3462,7 @@
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
+ compile_dex: false,
}
`)
}
@@ -3557,6 +3514,14 @@
java_libs: ["myjar"],
}
+ apex {
+ name: "myapex.updatable",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ java_libs: ["myjar"],
+ updatable: true,
+ }
+
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
@@ -3571,6 +3536,7 @@
stl: "none",
apex_available: [
"myapex",
+ "myapex.updatable",
"//apex_available:platform",
],
}
@@ -3582,6 +3548,7 @@
stl: "none",
apex_available: [
"myapex",
+ "myapex.updatable",
"//apex_available:platform",
],
}
@@ -3592,9 +3559,9 @@
sdk_version: "none",
system_modules: "none",
libs: ["myotherjar"],
- compile_dex: true,
apex_available: [
"myapex",
+ "myapex.updatable",
"//apex_available:platform",
],
}
@@ -3606,6 +3573,7 @@
system_modules: "none",
apex_available: [
"myapex",
+ "myapex.updatable",
"//apex_available:platform",
],
}
@@ -3635,17 +3603,94 @@
t.Errorf("%q is not found", file)
}
+ // For unbundled build, symlink shouldn't exist regardless of whether an APEX
+ // is updatable or not
ctx, _ := testApex(t, bp, withUnbundledBuild)
files := getFiles(t, ctx, "myapex", "android_common_myapex_image")
ensureRealfileExists(t, files, "javalib/myjar.jar")
ensureRealfileExists(t, files, "lib64/mylib.so")
ensureRealfileExists(t, files, "lib64/myotherlib.so")
+ files = getFiles(t, ctx, "myapex.updatable", "android_common_myapex.updatable_image")
+ ensureRealfileExists(t, files, "javalib/myjar.jar")
+ ensureRealfileExists(t, files, "lib64/mylib.so")
+ ensureRealfileExists(t, files, "lib64/myotherlib.so")
+
+ // For bundled build, symlink to the system for the non-updatable APEXes only
ctx, _ = testApex(t, bp)
files = getFiles(t, ctx, "myapex", "android_common_myapex_image")
ensureRealfileExists(t, files, "javalib/myjar.jar")
ensureRealfileExists(t, files, "lib64/mylib.so")
ensureSymlinkExists(t, files, "lib64/myotherlib.so") // this is symlink
+
+ files = getFiles(t, ctx, "myapex.updatable", "android_common_myapex.updatable_image")
+ ensureRealfileExists(t, files, "javalib/myjar.jar")
+ ensureRealfileExists(t, files, "lib64/mylib.so")
+ ensureRealfileExists(t, files, "lib64/myotherlib.so") // this is a real file
+}
+
+func TestApexWithJniLibs(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ jni_libs: ["mylib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["mylib2"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ }
+
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ }
+ `)
+
+ rule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
+ // Notice mylib2.so (transitive dep) is not added as a jni_lib
+ ensureEquals(t, rule.Args["opt"], "-a jniLibs mylib.so")
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ "lib64/mylib.so",
+ "lib64/mylib2.so",
+ })
+}
+
+func TestApexWithJniLibs_Errors(t *testing.T) {
+ testApexError(t, `jni_libs: "xxx" is not a cc_library`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ jni_libs: ["xxx"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ prebuilt_etc {
+ name: "xxx",
+ src: "xxx",
+ }
+ `, withFiles(map[string][]byte{
+ "xxx": nil,
+ }))
}
func TestMain(m *testing.M) {
diff --git a/apex/builder.go b/apex/builder.go
index 53f39a6..8c81fb4 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -180,6 +180,17 @@
optCommands = append(optCommands, "-v name "+*a.properties.Apex_name)
}
+ // collect jniLibs. Notice that a.filesInfo is already sorted
+ var jniLibs []string
+ for _, fi := range a.filesInfo {
+ if fi.isJniLib {
+ jniLibs = append(jniLibs, fi.builtFile.Base())
+ }
+ }
+ if len(jniLibs) > 0 {
+ optCommands = append(optCommands, "-a jniLibs "+strings.Join(jniLibs, " "))
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: apexManifestRule,
Input: manifestSrc,
@@ -215,15 +226,15 @@
noticeFiles := []android.Path{}
for _, f := range a.filesInfo {
if f.module != nil {
- notice := f.module.NoticeFile()
- if notice.Valid() {
- noticeFiles = append(noticeFiles, notice.Path())
+ notices := f.module.NoticeFiles()
+ if len(notices) > 0 {
+ noticeFiles = append(noticeFiles, notices...)
}
}
}
// append the notice file specified in the apex module itself
- if a.NoticeFile().Valid() {
- noticeFiles = append(noticeFiles, a.NoticeFile().Path())
+ if len(a.NoticeFiles()) > 0 {
+ noticeFiles = append(noticeFiles, a.NoticeFiles()...)
}
if len(noticeFiles) == 0 {
@@ -239,7 +250,7 @@
rule.Command().
Implicit(builtApex).
Text("(cd " + imageDir.String() + " ; ").
- Text("find . -type f -printf \"%s %p\\n\") ").
+ Text("find . \\( -type f -o -type l \\) -printf \"%s %p\\n\") ").
Text(" | sort -nr > ").
Output(output)
rule.Build(pctx, ctx, "installed-files."+a.Name(), "Installed files")
@@ -383,6 +394,16 @@
targetSdkVersion := ctx.Config().DefaultAppTargetSdk()
minSdkVersion := ctx.Config().DefaultAppTargetSdk()
+
+ if proptools.Bool(a.properties.Legacy_android10_support) {
+ if !java.UseApiFingerprint(ctx, targetSdkVersion) {
+ targetSdkVersion = "29"
+ }
+ if !java.UseApiFingerprint(ctx, minSdkVersion) {
+ minSdkVersion = "29"
+ }
+ }
+
if java.UseApiFingerprint(ctx, targetSdkVersion) {
targetSdkVersion += fmt.Sprintf(".$$(cat %s)", java.ApiFingerprintPath(ctx).String())
implicitInputs = append(implicitInputs, java.ApiFingerprintPath(ctx))
@@ -394,6 +415,10 @@
optFlags = append(optFlags, "--target_sdk_version "+targetSdkVersion)
optFlags = append(optFlags, "--min_sdk_version "+minSdkVersion)
+ if a.overridableProperties.Logging_parent != "" {
+ optFlags = append(optFlags, "--logging_parent ", a.overridableProperties.Logging_parent)
+ }
+
a.mergedNotices = a.buildNoticeFiles(ctx, a.Name()+suffix)
if a.mergedNotices.HtmlGzOutput.Valid() {
// If there's a NOTICE file, embed it as an asset file in the APEX.
@@ -508,13 +533,13 @@
// instead of `android.PathForOutput`) to return the correct path to the flattened
// APEX (as its contents is installed by Make, not Soong).
factx := flattenedApexContext{ctx}
- apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
- a.outputFile = android.PathForModuleInstall(&factx, "apex", apexName)
+ apexBundleName := a.Name()
+ a.outputFile = android.PathForModuleInstall(&factx, "apex", apexBundleName)
if a.installable() && a.GetOverriddenBy() == "" {
- installPath := android.PathForModuleInstall(ctx, "apex", apexName)
+ installPath := android.PathForModuleInstall(ctx, "apex", apexBundleName)
devicePath := android.InstallPathToOnDevicePath(ctx, installPath)
- addFlattenedFileContextsInfos(ctx, apexName+":"+devicePath+":"+a.fileContexts.String())
+ addFlattenedFileContextsInfos(ctx, apexBundleName+":"+devicePath+":"+a.fileContexts.String())
}
a.buildFilesInfo(ctx)
}
@@ -550,9 +575,9 @@
a.filesInfo = append(a.filesInfo, newApexFile(ctx, copiedPubkey, "apex_pubkey", ".", etc, nil))
if a.properties.ApexType == flattenedApex {
- apexName := proptools.StringDefault(a.properties.Apex_name, a.Name())
+ apexBundleName := a.Name()
for _, fi := range a.filesInfo {
- dir := filepath.Join("apex", apexName, fi.installDir)
+ dir := filepath.Join("apex", apexBundleName, fi.installDir)
target := ctx.InstallFile(android.PathForModuleInstall(ctx, dir), fi.builtFile.Base(), fi.builtFile)
for _, sym := range fi.symlinks {
ctx.InstallSymlink(android.PathForModuleInstall(ctx, dir), sym, target)
@@ -596,19 +621,14 @@
return
}
- internalDeps := a.internalDeps
- externalDeps := a.externalDeps
-
- internalDeps = android.SortedUniqueStrings(internalDeps)
- externalDeps = android.SortedUniqueStrings(externalDeps)
- externalDeps = android.RemoveListFromList(externalDeps, internalDeps)
-
var content strings.Builder
- for _, name := range internalDeps {
- fmt.Fprintf(&content, "internal %s\\n", name)
- }
- for _, name := range externalDeps {
- fmt.Fprintf(&content, "external %s\\n", name)
+ for _, key := range android.SortedStringKeys(a.depInfos) {
+ info := a.depInfos[key]
+ toName := info.to
+ if info.isExternal {
+ toName = toName + " (external)"
+ }
+ fmt.Fprintf(&content, "%s <- %s\\n", toName, strings.Join(android.SortedUniqueStrings(info.from), ", "))
}
depsInfoFile := android.PathForOutput(ctx, a.Name()+"-deps-info.txt")
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index dd08f03..a9e26ad 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -68,6 +68,7 @@
cc_library {
name: "libprofile-extras",
vendor_available: true,
+ recovery_available: true,
native_coverage: false,
system_shared_libs: [],
stl: "none",
@@ -76,6 +77,23 @@
cc_library {
name: "libprofile-clang-extras",
vendor_available: true,
+ recovery_available: true,
+ native_coverage: false,
+ system_shared_libs: [],
+ stl: "none",
+ notice: "custom_notice",
+ }
+ cc_library {
+ name: "libprofile-extras_ndk",
+ vendor_available: true,
+ native_coverage: false,
+ system_shared_libs: [],
+ stl: "none",
+ notice: "custom_notice",
+ }
+ cc_library {
+ name: "libprofile-clang-extras_ndk",
+ vendor_available: true,
native_coverage: false,
system_shared_libs: [],
stl: "none",
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 1d792ef..59d1502 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -66,6 +66,8 @@
// The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
"-isystem bionic/libc/kernel/uapi/asm-arm64",
"-isystem bionic/libc/kernel/android/uapi",
+ // TODO(b/149785767): only give access to specific file with AID_* constants
+ "-I system/core/libcutils/include",
"-I system/bpf/progs/include",
"-I " + ctx.ModuleDir(),
}
diff --git a/build_kzip.bash b/build_kzip.bash
index 008030f..0018ea9 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -19,16 +19,20 @@
# The extraction might fail for some source files, so run with -k and then check that
# sufficiently many files were generated.
declare -r out="${OUT_DIR:-out}"
+
# Build extraction files for C++ and Java. Build `merge_zips` which we use later.
build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k merge_zips xref_cxx xref_java
-#Build extraction file for Go files in build/soong directory.
+
+# Build extraction file for Go the files in build/{blueprint,soong} directories.
declare -r abspath_out=$(realpath "${out}")
declare -r go_extractor=$(realpath prebuilts/build-tools/linux-x86/bin/go_extractor)
declare -r go_root=$(realpath prebuilts/go/linux-x86)
+declare -r vnames_path=$(realpath build/soong/vnames.go.json)
+declare -r source_root=$PWD
for dir in blueprint soong; do
(cd "build/$dir";
- "$go_extractor" --goroot="$go_root" --rules=vnames.go.json --canonicalize_package_corpus \
- --output "${abspath_out}/soong/build_${dir}.go.kzip" ./...
+ KYTHE_ROOT_DIRECTORY="${source_root}" "$go_extractor" --goroot="$go_root" --rules="${vnames_path}" \
+ --canonicalize_package_corpus --output "${abspath_out}/soong/build_${dir}.go.kzip" ./...
)
done
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 137cb63..81004da 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -34,7 +34,7 @@
type AndroidMkContext interface {
Name() string
Target() android.Target
- subAndroidMk(*android.AndroidMkData, interface{})
+ subAndroidMk(*android.AndroidMkEntries, interface{})
Arch() android.Arch
Os() android.OsType
Host() bool
@@ -46,29 +46,29 @@
}
type subAndroidMkProvider interface {
- AndroidMk(AndroidMkContext, *android.AndroidMkData)
+ AndroidMkEntries(AndroidMkContext, *android.AndroidMkEntries)
}
-func (c *Module) subAndroidMk(data *android.AndroidMkData, obj interface{}) {
+func (c *Module) subAndroidMk(entries *android.AndroidMkEntries, obj interface{}) {
if c.subAndroidMkOnce == nil {
c.subAndroidMkOnce = make(map[subAndroidMkProvider]bool)
}
if androidmk, ok := obj.(subAndroidMkProvider); ok {
if !c.subAndroidMkOnce[androidmk] {
c.subAndroidMkOnce[androidmk] = true
- androidmk.AndroidMk(c, data)
+ androidmk.AndroidMkEntries(c, entries)
}
}
}
-func (c *Module) AndroidMk() android.AndroidMkData {
+func (c *Module) AndroidMkEntries() []android.AndroidMkEntries {
if c.Properties.HideFromMake || !c.IsForPlatform() {
- return android.AndroidMkData{
+ return []android.AndroidMkEntries{{
Disabled: true,
- }
+ }}
}
- ret := android.AndroidMkData{
+ entries := android.AndroidMkEntries{
OutputFile: c.outputFile,
// TODO(jiyong): add the APEXes providing shared libs to the required modules
// Currently, adding c.Properties.ApexesProvidingSharedLibs is causing multiple
@@ -77,29 +77,29 @@
Required: c.Properties.AndroidMkRuntimeLibs,
Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
- Extra: []android.AndroidMkExtraFunc{
- func(w io.Writer, outputFile android.Path) {
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
if len(c.Properties.Logtags) > 0 {
- fmt.Fprintln(w, "LOCAL_LOGTAGS_FILES :=", strings.Join(c.Properties.Logtags, " "))
+ entries.AddStrings("LOCAL_LOGTAGS_FILES", c.Properties.Logtags...)
}
if len(c.Properties.AndroidMkSharedLibs) > 0 {
- fmt.Fprintln(w, "LOCAL_SHARED_LIBRARIES := "+strings.Join(c.Properties.AndroidMkSharedLibs, " "))
+ entries.AddStrings("LOCAL_SHARED_LIBRARIES", c.Properties.AndroidMkSharedLibs...)
}
if len(c.Properties.AndroidMkStaticLibs) > 0 {
- fmt.Fprintln(w, "LOCAL_STATIC_LIBRARIES := "+strings.Join(c.Properties.AndroidMkStaticLibs, " "))
+ entries.AddStrings("LOCAL_STATIC_LIBRARIES", c.Properties.AndroidMkStaticLibs...)
}
if len(c.Properties.AndroidMkWholeStaticLibs) > 0 {
- fmt.Fprintln(w, "LOCAL_WHOLE_STATIC_LIBRARIES := "+strings.Join(c.Properties.AndroidMkWholeStaticLibs, " "))
+ entries.AddStrings("LOCAL_WHOLE_STATIC_LIBRARIES", c.Properties.AndroidMkWholeStaticLibs...)
}
- fmt.Fprintln(w, "LOCAL_SOONG_LINK_TYPE :=", c.makeLinkType)
+ entries.SetString("LOCAL_SOONG_LINK_TYPE", c.makeLinkType)
if c.UseVndk() {
- fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
+ entries.SetBool("LOCAL_USE_VNDK", true)
if c.IsVndk() && !c.static() {
- fmt.Fprintln(w, "LOCAL_SOONG_VNDK_VERSION := "+c.VndkVersion())
+ entries.SetString("LOCAL_SOONG_VNDK_VERSION", c.VndkVersion())
// VNDK libraries available to vendor are not installed because
// they are packaged in VNDK APEX and installed by APEX packages (apex/apex.go)
if !c.isVndkExt() {
- fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
}
}
}
@@ -108,22 +108,22 @@
}
for _, feature := range c.features {
- c.subAndroidMk(&ret, feature)
+ c.subAndroidMk(&entries, feature)
}
- c.subAndroidMk(&ret, c.compiler)
- c.subAndroidMk(&ret, c.linker)
+ c.subAndroidMk(&entries, c.compiler)
+ c.subAndroidMk(&entries, c.linker)
if c.sanitize != nil {
- c.subAndroidMk(&ret, c.sanitize)
+ c.subAndroidMk(&entries, c.sanitize)
}
- c.subAndroidMk(&ret, c.installer)
+ c.subAndroidMk(&entries, c.installer)
- ret.SubName += c.Properties.SubName
+ entries.SubName += c.Properties.SubName
- return ret
+ return []android.AndroidMkEntries{entries}
}
-func androidMkWriteTestData(data android.Paths, ctx AndroidMkContext, ret *android.AndroidMkData) {
+func androidMkWriteTestData(data android.Paths, ctx AndroidMkContext, entries *android.AndroidMkEntries) {
var testFiles []string
for _, d := range data {
rel := d.Rel()
@@ -135,8 +135,8 @@
testFiles = append(testFiles, path+":"+rel)
}
if len(testFiles) > 0 {
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_TEST_DATA := "+strings.Join(testFiles, " "))
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ entries.AddStrings("LOCAL_TEST_DATA", testFiles...)
})
}
}
@@ -153,7 +153,7 @@
return overrides
}
-func (library *libraryDecorator) androidMkWriteExportedFlags(w io.Writer) {
+func (library *libraryDecorator) androidMkWriteExportedFlags(entries *android.AndroidMkEntries) {
exportedFlags := library.exportedFlags()
for _, dir := range library.exportedDirs() {
exportedFlags = append(exportedFlags, "-I"+dir.String())
@@ -162,75 +162,92 @@
exportedFlags = append(exportedFlags, "-isystem "+dir.String())
}
if len(exportedFlags) > 0 {
- fmt.Fprintln(w, "LOCAL_EXPORT_CFLAGS :=", strings.Join(exportedFlags, " "))
+ entries.AddStrings("LOCAL_EXPORT_CFLAGS", exportedFlags...)
}
exportedDeps := library.exportedDeps()
if len(exportedDeps) > 0 {
- fmt.Fprintln(w, "LOCAL_EXPORT_C_INCLUDE_DEPS :=", strings.Join(exportedDeps.Strings(), " "))
+ entries.AddStrings("LOCAL_EXPORT_C_INCLUDE_DEPS", exportedDeps.Strings()...)
}
}
-func (library *libraryDecorator) androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
+func (library *libraryDecorator) androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries *android.AndroidMkEntries) {
if library.sAbiOutputFile.Valid() {
- fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES +=", library.sAbiOutputFile.String())
+ entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES",
+ "$(LOCAL_ADDITIONAL_DEPENDENCIES) "+library.sAbiOutputFile.String())
if library.sAbiDiff.Valid() && !library.static() {
- fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES +=", library.sAbiDiff.String())
- fmt.Fprintln(w, "HEADER_ABI_DIFFS +=", library.sAbiDiff.String())
+ entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES",
+ "$(LOCAL_ADDITIONAL_DEPENDENCIES) "+library.sAbiDiff.String())
+ entries.SetString("HEADER_ABI_DIFFS",
+ "$(HEADER_ABI_DIFFS) "+library.sAbiDiff.String())
}
}
}
-func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+// TODO(ccross): remove this once apex/androidmk.go is converted to AndroidMkEntries
+func (library *libraryDecorator) androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
+ if library.sAbiOutputFile.Valid() {
+ fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_ADDITIONAL_DEPENDENCIES) ",
+ library.sAbiOutputFile.String())
+ if library.sAbiDiff.Valid() && !library.static() {
+ fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_ADDITIONAL_DEPENDENCIES) ",
+ library.sAbiDiff.String())
+ fmt.Fprintln(w, "HEADER_ABI_DIFFS := $(HEADER_ABI_DIFFS) ",
+ library.sAbiDiff.String())
+ }
+ }
+}
+
+func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
if library.static() {
- ret.Class = "STATIC_LIBRARIES"
+ entries.Class = "STATIC_LIBRARIES"
} else if library.shared() {
- ret.Class = "SHARED_LIBRARIES"
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_SOONG_TOC :=", library.toc().String())
+ entries.Class = "SHARED_LIBRARIES"
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_SOONG_TOC", library.toc().String())
if !library.buildStubs() {
- fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", library.unstrippedOutputFile.String())
+ entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", library.unstrippedOutputFile.String())
}
if len(library.Properties.Overrides) > 0 {
- fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES := "+strings.Join(makeOverrideModuleNames(ctx, library.Properties.Overrides), " "))
+ entries.SetString("LOCAL_OVERRIDES_MODULES", strings.Join(makeOverrideModuleNames(ctx, library.Properties.Overrides), " "))
}
if len(library.post_install_cmds) > 0 {
- fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD := "+strings.Join(library.post_install_cmds, "&& "))
+ entries.SetString("LOCAL_POST_INSTALL_CMD", strings.Join(library.post_install_cmds, "&& "))
}
})
} else if library.header() {
- ret.Class = "HEADER_LIBRARIES"
+ entries.Class = "HEADER_LIBRARIES"
}
- ret.DistFile = library.distFile
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- library.androidMkWriteExportedFlags(w)
- library.androidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
+ entries.DistFile = library.distFile
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ library.androidMkWriteExportedFlags(entries)
+ library.androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries)
- _, _, ext := android.SplitFileExt(outputFile.Base())
+ _, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base())
- fmt.Fprintln(w, "LOCAL_BUILT_MODULE_STEM := $(LOCAL_MODULE)"+ext)
+ entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
if library.coverageOutputFile.Valid() {
- fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", library.coverageOutputFile.String())
+ entries.SetString("LOCAL_PREBUILT_COVERAGE_ARCHIVE", library.coverageOutputFile.String())
}
if library.useCoreVariant {
- fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
- fmt.Fprintln(w, "LOCAL_NO_NOTICE_FILE := true")
- fmt.Fprintln(w, "LOCAL_VNDK_DEPEND_ON_CORE_VARIANT := true")
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
+ entries.SetBool("LOCAL_VNDK_DEPEND_ON_CORE_VARIANT", true)
}
if library.checkSameCoreVariant {
- fmt.Fprintln(w, "LOCAL_CHECK_SAME_VNDK_VARIANTS := true")
+ entries.SetBool("LOCAL_CHECK_SAME_VNDK_VARIANTS", true)
}
})
if library.shared() && !library.buildStubs() {
- ctx.subAndroidMk(ret, library.baseInstaller)
+ ctx.subAndroidMk(entries, library.baseInstaller)
} else {
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
if library.buildStubs() {
- fmt.Fprintln(w, "LOCAL_NO_NOTICE_FILE := true")
+ entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
}
})
}
@@ -238,90 +255,91 @@
android.DirectlyInAnyApex(ctx, ctx.Name()) && !ctx.InRamdisk() && !ctx.InRecovery() && !ctx.UseVndk() &&
!ctx.static() {
if !library.buildStubs() {
- ret.SubName = ".bootstrap"
+ entries.SubName = ".bootstrap"
}
}
}
-func (object *objectLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ret.Custom = func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
- out := ret.OutputFile.Path()
- varname := fmt.Sprintf("SOONG_%sOBJECT_%s%s", prefix, name, data.SubName)
+func (object *objectLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ entries.Class = "STATIC_LIBRARIES"
+ entries.ExtraFooters = append(entries.ExtraFooters,
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+ out := entries.OutputFile.Path()
+ varname := fmt.Sprintf("SOONG_%sOBJECT_%s%s", prefix, name, entries.SubName)
- fmt.Fprintf(w, "\n%s := %s\n", varname, out.String())
- fmt.Fprintln(w, ".KATI_READONLY: "+varname)
- }
+ fmt.Fprintf(w, "\n%s := %s\n", varname, out.String())
+ fmt.Fprintln(w, ".KATI_READONLY: "+varname)
+ })
}
-func (binary *binaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ctx.subAndroidMk(ret, binary.baseInstaller)
+func (binary *binaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ ctx.subAndroidMk(entries, binary.baseInstaller)
- ret.Class = "EXECUTABLES"
- ret.DistFile = binary.distFile
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", binary.unstrippedOutputFile.String())
+ entries.Class = "EXECUTABLES"
+ entries.DistFile = binary.distFile
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", binary.unstrippedOutputFile.String())
if len(binary.symlinks) > 0 {
- fmt.Fprintln(w, "LOCAL_MODULE_SYMLINKS := "+strings.Join(binary.symlinks, " "))
+ entries.AddStrings("LOCAL_MODULE_SYMLINKS", binary.symlinks...)
}
if binary.coverageOutputFile.Valid() {
- fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", binary.coverageOutputFile.String())
+ entries.SetString("LOCAL_PREBUILT_COVERAGE_ARCHIVE", binary.coverageOutputFile.String())
}
if len(binary.Properties.Overrides) > 0 {
- fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES := "+strings.Join(makeOverrideModuleNames(ctx, binary.Properties.Overrides), " "))
+ entries.SetString("LOCAL_OVERRIDES_MODULES", strings.Join(makeOverrideModuleNames(ctx, binary.Properties.Overrides), " "))
}
if len(binary.post_install_cmds) > 0 {
- fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD := "+strings.Join(binary.post_install_cmds, "&& "))
+ entries.SetString("LOCAL_POST_INSTALL_CMD", strings.Join(binary.post_install_cmds, "&& "))
}
})
}
-func (benchmark *benchmarkDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ctx.subAndroidMk(ret, benchmark.binaryDecorator)
- ret.Class = "NATIVE_TESTS"
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+func (benchmark *benchmarkDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ ctx.subAndroidMk(entries, benchmark.binaryDecorator)
+ entries.Class = "NATIVE_TESTS"
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
if len(benchmark.Properties.Test_suites) > 0 {
- fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
+ entries.SetString("LOCAL_COMPATIBILITY_SUITE",
strings.Join(benchmark.Properties.Test_suites, " "))
}
if benchmark.testConfig != nil {
- fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=", benchmark.testConfig.String())
+ entries.SetString("LOCAL_FULL_TEST_CONFIG", benchmark.testConfig.String())
}
- fmt.Fprintln(w, "LOCAL_NATIVE_BENCHMARK := true")
+ entries.SetBool("LOCAL_NATIVE_BENCHMARK", true)
if !BoolDefault(benchmark.Properties.Auto_gen_config, true) {
- fmt.Fprintln(w, "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG := true")
+ entries.SetBool("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", true)
}
})
- androidMkWriteTestData(benchmark.data, ctx, ret)
+ androidMkWriteTestData(benchmark.data, ctx, entries)
}
-func (test *testBinary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ctx.subAndroidMk(ret, test.binaryDecorator)
- ret.Class = "NATIVE_TESTS"
+func (test *testBinary) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ ctx.subAndroidMk(entries, test.binaryDecorator)
+ entries.Class = "NATIVE_TESTS"
if Bool(test.Properties.Test_per_src) {
- ret.SubName = "_" + String(test.binaryDecorator.Properties.Stem)
+ entries.SubName = "_" + String(test.binaryDecorator.Properties.Stem)
}
-
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
if len(test.Properties.Test_suites) > 0 {
- fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
+ entries.SetString("LOCAL_COMPATIBILITY_SUITE",
strings.Join(test.Properties.Test_suites, " "))
}
if test.testConfig != nil {
- fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=", test.testConfig.String())
+ entries.SetString("LOCAL_FULL_TEST_CONFIG", test.testConfig.String())
}
if !BoolDefault(test.Properties.Auto_gen_config, true) {
- fmt.Fprintln(w, "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG := true")
+ entries.SetBool("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", true)
}
})
- androidMkWriteTestData(test.data, ctx, ret)
+ androidMkWriteTestData(test.data, ctx, entries)
}
-func (fuzz *fuzzBinary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ctx.subAndroidMk(ret, fuzz.binaryDecorator)
+func (fuzz *fuzzBinary) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ ctx.subAndroidMk(entries, fuzz.binaryDecorator)
var fuzzFiles []string
for _, d := range fuzz.corpus {
@@ -344,142 +362,198 @@
filepath.Dir(fuzz.config.String())+":config.json")
}
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- fmt.Fprintln(w, "LOCAL_IS_FUZZ_TARGET := true")
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_IS_FUZZ_TARGET", true)
if len(fuzzFiles) > 0 {
- fmt.Fprintln(w, "LOCAL_TEST_DATA := "+strings.Join(fuzzFiles, " "))
+ entries.AddStrings("LOCAL_TEST_DATA", fuzzFiles...)
}
if fuzz.installedSharedDeps != nil {
- fmt.Fprintln(w, "LOCAL_FUZZ_INSTALLED_SHARED_DEPS :="+
- strings.Join(fuzz.installedSharedDeps, " "))
+ entries.AddStrings("LOCAL_FUZZ_INSTALLED_SHARED_DEPS", fuzz.installedSharedDeps...)
}
})
}
-func (test *testLibrary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ctx.subAndroidMk(ret, test.libraryDecorator)
+func (test *testLibrary) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ ctx.subAndroidMk(entries, test.libraryDecorator)
}
-func (library *toolchainLibraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ret.Class = "STATIC_LIBRARIES"
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- _, suffix, _ := android.SplitFileExt(outputFile.Base())
- fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
+func (library *toolchainLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ entries.Class = "STATIC_LIBRARIES"
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ _, suffix, _ := android.SplitFileExt(entries.OutputFile.Path().Base())
+ entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
})
}
-func (installer *baseInstaller) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+func (installer *baseInstaller) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
// Soong installation is only supported for host modules. Have Make
// installation trigger Soong installation.
if ctx.Target().Os.Class == android.Host {
- ret.OutputFile = android.OptionalPathForPath(installer.path)
+ entries.OutputFile = android.OptionalPathForPath(installer.path)
}
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
path, file := filepath.Split(installer.path.ToMakePath().String())
stem, suffix, _ := android.SplitFileExt(file)
- fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
- fmt.Fprintln(w, "LOCAL_MODULE_PATH := "+path)
- fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
+ entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
+ entries.SetString("LOCAL_MODULE_PATH", path)
+ entries.SetString("LOCAL_MODULE_STEM", stem)
})
}
-func (c *stubDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ret.SubName = ndkLibrarySuffix + "." + c.properties.ApiLevel
- ret.Class = "SHARED_LIBRARIES"
+func (c *stubDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ entries.SubName = ndkLibrarySuffix + "." + c.properties.ApiLevel
+ entries.Class = "SHARED_LIBRARIES"
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
path, file := filepath.Split(c.installPath.String())
stem, suffix, _ := android.SplitFileExt(file)
- fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
- fmt.Fprintln(w, "LOCAL_MODULE_PATH := "+path)
- fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
- fmt.Fprintln(w, "LOCAL_NO_NOTICE_FILE := true")
+ entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
+ entries.SetString("LOCAL_MODULE_PATH", path)
+ entries.SetString("LOCAL_MODULE_STEM", stem)
+ entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
})
}
-func (c *llndkStubDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ret.Class = "SHARED_LIBRARIES"
+func (c *llndkStubDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ entries.Class = "SHARED_LIBRARIES"
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- c.libraryDecorator.androidMkWriteExportedFlags(w)
- _, _, ext := android.SplitFileExt(outputFile.Base())
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ c.libraryDecorator.androidMkWriteExportedFlags(entries)
+ _, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base())
- fmt.Fprintln(w, "LOCAL_BUILT_MODULE_STEM := $(LOCAL_MODULE)"+ext)
- fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
- fmt.Fprintln(w, "LOCAL_NO_NOTICE_FILE := true")
- fmt.Fprintln(w, "LOCAL_SOONG_TOC :=", c.toc().String())
+ entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
+ entries.SetString("LOCAL_SOONG_TOC", c.toc().String())
})
}
-func (c *vndkPrebuiltLibraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ret.Class = "SHARED_LIBRARIES"
+func (c *vndkPrebuiltLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ entries.Class = "SHARED_LIBRARIES"
- ret.SubName = c.NameSuffix()
+ entries.SubName = c.androidMkSuffix
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- c.libraryDecorator.androidMkWriteExportedFlags(w)
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ c.libraryDecorator.androidMkWriteExportedFlags(entries)
path, file := filepath.Split(c.path.ToMakePath().String())
stem, suffix, ext := android.SplitFileExt(file)
- fmt.Fprintln(w, "LOCAL_BUILT_MODULE_STEM := $(LOCAL_MODULE)"+ext)
- fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
- fmt.Fprintln(w, "LOCAL_MODULE_PATH := "+path)
- fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
+ entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
+ entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
+ entries.SetString("LOCAL_MODULE_PATH", path)
+ entries.SetString("LOCAL_MODULE_STEM", stem)
+ if c.tocFile.Valid() {
+ entries.SetString("LOCAL_SOONG_TOC", c.tocFile.String())
+ }
})
}
-func (c *ndkPrebuiltStlLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ret.Class = "SHARED_LIBRARIES"
-}
+func (c *vendorSnapshotLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ // Each vendor snapshot is exported to androidMk only when BOARD_VNDK_VERSION != current
+ // and the version of the prebuilt is same as BOARD_VNDK_VERSION.
+ if c.shared() {
+ entries.Class = "SHARED_LIBRARIES"
+ } else if c.static() {
+ entries.Class = "STATIC_LIBRARIES"
+ } else if c.header() {
+ entries.Class = "HEADER_LIBRARIES"
+ }
-func (c *vendorPublicLibraryStubDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ret.Class = "SHARED_LIBRARIES"
- ret.SubName = vendorPublicLibrarySuffix
+ if c.androidMkVendorSuffix {
+ entries.SubName = vendorSuffix
+ } else {
+ entries.SubName = ""
+ }
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- c.libraryDecorator.androidMkWriteExportedFlags(w)
- _, _, ext := android.SplitFileExt(outputFile.Base())
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ c.libraryDecorator.androidMkWriteExportedFlags(entries)
- fmt.Fprintln(w, "LOCAL_BUILT_MODULE_STEM := $(LOCAL_MODULE)"+ext)
- fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
- fmt.Fprintln(w, "LOCAL_NO_NOTICE_FILE := true")
+ if c.shared() || c.static() {
+ path, file := filepath.Split(c.path.ToMakePath().String())
+ stem, suffix, ext := android.SplitFileExt(file)
+ entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
+ entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
+ entries.SetString("LOCAL_MODULE_STEM", stem)
+ if c.shared() {
+ entries.SetString("LOCAL_MODULE_PATH", path)
+ }
+ if c.tocFile.Valid() {
+ entries.SetString("LOCAL_SOONG_TOC", c.tocFile.String())
+ }
+ }
+
+ if !c.shared() { // static or header
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ }
})
}
-func (p *prebuiltLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+func (c *vendorSnapshotBinaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ entries.Class = "EXECUTABLES"
+
+ if c.androidMkVendorSuffix {
+ entries.SubName = vendorSuffix
+ } else {
+ entries.SubName = ""
+ }
+
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ entries.AddStrings("LOCAL_MODULE_SYMLINKS", c.Properties.Symlinks...)
+ })
+}
+
+func (c *ndkPrebuiltStlLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ entries.Class = "SHARED_LIBRARIES"
+}
+
+func (c *vendorPublicLibraryStubDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ entries.Class = "SHARED_LIBRARIES"
+ entries.SubName = vendorPublicLibrarySuffix
+
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ c.libraryDecorator.androidMkWriteExportedFlags(entries)
+ _, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base())
+
+ entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
+ })
+}
+
+func (p *prebuiltLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
if p.properties.Check_elf_files != nil {
- fmt.Fprintln(w, "LOCAL_CHECK_ELF_FILES :=", *p.properties.Check_elf_files)
+ entries.SetBool("LOCAL_CHECK_ELF_FILES", *p.properties.Check_elf_files)
} else {
// soong_cc_prebuilt.mk does not include check_elf_file.mk by default
// because cc_library_shared and cc_binary use soong_cc_prebuilt.mk as well.
// In order to turn on prebuilt ABI checker, set `LOCAL_CHECK_ELF_FILES` to
// true if `p.properties.Check_elf_files` is not specified.
- fmt.Fprintln(w, "LOCAL_CHECK_ELF_FILES := true")
+ entries.SetBool("LOCAL_CHECK_ELF_FILES", true)
}
})
}
-func (p *prebuiltLibraryLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ctx.subAndroidMk(ret, p.libraryDecorator)
+func (p *prebuiltLibraryLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ ctx.subAndroidMk(entries, p.libraryDecorator)
if p.shared() {
- ctx.subAndroidMk(ret, &p.prebuiltLinker)
- androidMkWriteAllowUndefinedSymbols(p.baseLinker, ret)
+ ctx.subAndroidMk(entries, &p.prebuiltLinker)
+ androidMkWriteAllowUndefinedSymbols(p.baseLinker, entries)
}
}
-func (p *prebuiltBinaryLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ctx.subAndroidMk(ret, p.binaryDecorator)
- ctx.subAndroidMk(ret, &p.prebuiltLinker)
- androidMkWriteAllowUndefinedSymbols(p.baseLinker, ret)
+func (p *prebuiltBinaryLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ ctx.subAndroidMk(entries, p.binaryDecorator)
+ ctx.subAndroidMk(entries, &p.prebuiltLinker)
+ androidMkWriteAllowUndefinedSymbols(p.baseLinker, entries)
}
-func androidMkWriteAllowUndefinedSymbols(linker *baseLinker, ret *android.AndroidMkData) {
- ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
- allow := linker.Properties.Allow_undefined_symbols
- if allow != nil {
- fmt.Fprintln(w, "LOCAL_ALLOW_UNDEFINED_SYMBOLS :=", *allow)
- }
- })
+func androidMkWriteAllowUndefinedSymbols(linker *baseLinker, entries *android.AndroidMkEntries) {
+ allow := linker.Properties.Allow_undefined_symbols
+ if allow != nil {
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_ALLOW_UNDEFINED_SYMBOLS", *allow)
+ })
+ }
}
diff --git a/cc/binary.go b/cc/binary.go
index 280d17b..661264e 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -200,6 +200,11 @@
module.compiler = NewBaseCompiler()
module.linker = binary
module.installer = binary
+
+ // Allow module to be added as member of an sdk/module_exports.
+ module.sdkMemberTypes = []android.SdkMemberType{
+ ccBinarySdkMemberType,
+ }
return module, binary
}
diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go
new file mode 100644
index 0000000..58d6ad0
--- /dev/null
+++ b/cc/binary_sdk_member.go
@@ -0,0 +1,160 @@
+// Copyright 2020 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 cc
+
+import (
+ "path/filepath"
+ "strings"
+
+ "android/soong/android"
+ "github.com/google/blueprint"
+)
+
+func init() {
+ android.RegisterSdkMemberType(ccBinarySdkMemberType)
+}
+
+var ccBinarySdkMemberType = &binarySdkMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "native_binaries",
+ },
+}
+
+type binarySdkMemberType struct {
+ android.SdkMemberTypeBase
+}
+
+func (mt *binarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
+ targets := mctx.MultiTargets()
+ for _, lib := range names {
+ for _, target := range targets {
+ name, version := StubsLibNameAndVersion(lib)
+ if version == "" {
+ version = LatestStubsVersionFor(mctx.Config(), name)
+ }
+ mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
+ {Mutator: "version", Variation: version},
+ }...), dependencyTag, name)
+ }
+ }
+}
+
+func (mt *binarySdkMemberType) IsInstance(module android.Module) bool {
+ // Check the module to see if it can be used with this module type.
+ if m, ok := module.(*Module); ok {
+ for _, allowableMemberType := range m.sdkMemberTypes {
+ if allowableMemberType == mt {
+ return true
+ }
+ }
+ }
+
+ return false
+}
+
+func (mt *binarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
+ info := mt.organizeVariants(member)
+ buildSharedNativeBinarySnapshot(info, builder, member)
+}
+
+// Organize the variants by architecture.
+func (mt *binarySdkMemberType) organizeVariants(member android.SdkMember) *nativeBinaryInfo {
+ memberName := member.Name()
+ info := &nativeBinaryInfo{
+ name: memberName,
+ memberType: mt,
+ }
+
+ for _, variant := range member.Variants() {
+ ccModule := variant.(*Module)
+
+ info.archVariantProperties = append(info.archVariantProperties, nativeBinaryInfoProperties{
+ name: memberName,
+ archType: ccModule.Target().Arch.ArchType.String(),
+ outputFile: ccModule.OutputFile().Path(),
+ })
+ }
+
+ // Initialize the unexported properties that will not be set during the
+ // extraction process.
+ info.commonProperties.name = memberName
+
+ // Extract common properties from the arch specific properties.
+ extractCommonProperties(&info.commonProperties, info.archVariantProperties)
+
+ return info
+}
+
+func buildSharedNativeBinarySnapshot(info *nativeBinaryInfo, builder android.SnapshotBuilder, member android.SdkMember) {
+ pbm := builder.AddPrebuiltModule(member, "cc_prebuilt_binary")
+ archVariantCount := len(info.archVariantProperties)
+
+ // Choose setting for compile_multilib that is appropriate for the arch variants supplied.
+ var multilib string
+ if archVariantCount == 2 {
+ multilib = "both"
+ } else if archVariantCount == 1 {
+ if strings.HasSuffix(info.archVariantProperties[0].archType, "64") {
+ multilib = "64"
+ } else {
+ multilib = "32"
+ }
+ }
+ if multilib != "" {
+ pbm.AddProperty("compile_multilib", multilib)
+ }
+
+ archProperties := pbm.AddPropertySet("arch")
+ for _, av := range info.archVariantProperties {
+ archTypeProperties := archProperties.AddPropertySet(av.archType)
+ archTypeProperties.AddProperty("srcs", []string{nativeBinaryPathFor(av)})
+
+ builder.CopyToSnapshot(av.outputFile, nativeBinaryPathFor(av))
+ }
+}
+
+const (
+ nativeBinaryDir = "bin"
+)
+
+// path to the native binary. Relative to <sdk_root>/<api_dir>
+func nativeBinaryPathFor(lib nativeBinaryInfoProperties) string {
+ return filepath.Join(lib.archType,
+ nativeBinaryDir, lib.outputFile.Base())
+}
+
+// nativeBinaryInfoProperties represents properties of a native binary
+//
+// The exported (capitalized) fields will be examined and may be changed during common value extraction.
+// The unexported fields will be left untouched.
+type nativeBinaryInfoProperties struct {
+ // The name of the library, is not exported as this must not be changed during optimization.
+ name string
+
+ // archType is not exported as if set (to a non default value) it is always arch specific.
+ // This is "" for common properties.
+ archType string
+
+ // outputFile is not exported as it is always arch specific.
+ outputFile android.Path
+}
+
+// nativeBinaryInfo represents a collection of arch-specific modules having the same name
+type nativeBinaryInfo struct {
+ name string
+ memberType *binarySdkMemberType
+ archVariantProperties []nativeBinaryInfoProperties
+ commonProperties nativeBinaryInfoProperties
+}
diff --git a/cc/builder.go b/cc/builder.go
index 3ecfe54..136263b 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -55,9 +55,9 @@
},
"ccCmd", "cFlags")
- ccNoDeps = pctx.AndroidRemoteStaticRule("ccNoDeps", android.RemoteRuleSupports{Goma: true},
+ ccNoDeps = pctx.AndroidStaticRule("ccNoDeps",
blueprint.RuleParams{
- Command: "$relPwd ${config.CcWrapper}$ccCmd -c $cFlags -o $out $in",
+ Command: "$relPwd $ccCmd -c $cFlags -o $out $in",
CommandDeps: []string{"$ccCmd"},
},
"ccCmd", "cFlags")
diff --git a/cc/cc.go b/cc/cc.go
index ce3a2ed..5af8459 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -49,6 +49,8 @@
ctx.BottomUp("version", VersionMutator).Parallel()
ctx.BottomUp("begin", BeginMutator).Parallel()
ctx.BottomUp("sysprop_cc", SyspropMutator).Parallel()
+ ctx.BottomUp("vendor_snapshot", VendorSnapshotMutator).Parallel()
+ ctx.BottomUp("vendor_snapshot_source", VendorSnapshotSourceMutator).Parallel()
})
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -93,6 +95,8 @@
HeaderLibs []string
RuntimeLibs []string
+ StaticUnwinderIfLegacy bool
+
ReexportSharedLibHeaders, ReexportStaticLibHeaders, ReexportHeaderLibHeaders []string
ObjFiles []string
@@ -242,6 +246,10 @@
// Even if DeviceConfig().VndkUseCoreVariant() is set, this module must use vendor variant.
// see soong/cc/config/vndk.go
MustUseVendorVariant bool `blueprint:"mutated"`
+
+ // Used by vendor snapshot to record dependencies from snapshot modules.
+ SnapshotSharedLibs []string `blueprint:"mutated"`
+ SnapshotRuntimeLibs []string `blueprint:"mutated"`
}
type VendorProperties struct {
@@ -379,6 +387,7 @@
lateSharedDepTag = DependencyTag{Name: "late shared", Library: true, Shared: true}
staticExportDepTag = DependencyTag{Name: "static", Library: true, ReexportFlags: true}
lateStaticDepTag = DependencyTag{Name: "late static", Library: true}
+ staticUnwinderDepTag = DependencyTag{Name: "static unwinder", Library: true}
wholeStaticDepTag = DependencyTag{Name: "whole static", Library: true, ReexportFlags: true}
headerDepTag = DependencyTag{Name: "header", Library: true}
headerExportDepTag = DependencyTag{Name: "header", Library: true, ReexportFlags: true}
@@ -403,13 +412,6 @@
return ok && ccDepTag.Shared
}
-func IsStaticDepTag(depTag blueprint.DependencyTag) bool {
- ccDepTag, ok := depTag.(DependencyTag)
- return ok && (ccDepTag == staticExportDepTag ||
- ccDepTag == lateStaticDepTag ||
- ccDepTag == wholeStaticDepTag)
-}
-
func IsRuntimeDepTag(depTag blueprint.DependencyTag) bool {
ccDepTag, ok := depTag.(DependencyTag)
return ok && ccDepTag == runtimeDepTag
@@ -451,9 +453,6 @@
vndkdep *vndkdep
lto *lto
pgo *pgo
- xom *xom
-
- androidMkSharedLibDeps []string
outputFile android.OptionalPath
@@ -475,9 +474,6 @@
makeLinkType string
// Kythe (source file indexer) paths for this compilation module
kytheFiles android.Paths
-
- // name of the modules that are direct or indirect static deps of this module
- allStaticDeps []string
}
func (c *Module) Toc() android.OptionalPath {
@@ -740,9 +736,6 @@
if c.pgo != nil {
c.AddProperties(c.pgo.props()...)
}
- if c.xom != nil {
- c.AddProperties(c.xom.props()...)
- }
for _, feature := range c.features {
c.AddProperties(feature.props()...)
}
@@ -930,6 +923,19 @@
return c.linker != nil && c.linker.nativeCoverage()
}
+func (c *Module) isSnapshotPrebuilt() bool {
+ if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
+ return true
+ }
+ if _, ok := c.linker.(*vendorSnapshotLibraryDecorator); ok {
+ return true
+ }
+ if _, ok := c.linker.(*vendorSnapshotBinaryDecorator); ok {
+ return true
+ }
+ return false
+}
+
func (c *Module) ExportedIncludeDirs() android.Paths {
if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
return flagsProducer.exportedDirs()
@@ -1199,7 +1205,6 @@
module.vndkdep = &vndkdep{}
module.lto = <o{}
module.pgo = &pgo{}
- module.xom = &xom{}
return module
}
@@ -1266,8 +1271,11 @@
allTransitiveDeps := make(map[android.Path][]android.Path, len(staticDeps))
staticDepFiles := []android.Path{}
for _, dep := range staticDeps {
- allTransitiveDeps[dep.OutputFile().Path()] = dep.GetDepsInLinkOrder()
- staticDepFiles = append(staticDepFiles, dep.OutputFile().Path())
+ // The OutputFile may not be valid for a variant not present, and the AllowMissingDependencies flag is set.
+ if dep.OutputFile().Valid() {
+ allTransitiveDeps[dep.OutputFile().Path()] = dep.GetDepsInLinkOrder()
+ staticDepFiles = append(staticDepFiles, dep.OutputFile().Path())
+ }
}
sharedDepFiles := []android.Path{}
for _, sharedDep := range sharedDeps {
@@ -1285,15 +1293,6 @@
return results
}
-func gatherTransitiveStaticDeps(staticDeps []LinkableInterface) []string {
- var ret []string
- for _, dep := range staticDeps {
- ret = append(ret, dep.Module().Name())
- ret = append(ret, dep.AllStaticDeps()...)
- }
- return android.FirstUniqueStrings(ret)
-}
-
func (c *Module) IsTestPerSrcAllTestsVariation() bool {
test, ok := c.linker.(testPerSrc)
return ok && test.isAllTestsVariation()
@@ -1400,9 +1399,6 @@
if c.pgo != nil {
flags = c.pgo.flags(ctx, flags)
}
- if c.xom != nil {
- flags = c.xom.flags(ctx, flags)
- }
for _, feature := range c.features {
flags = feature.flags(ctx, flags)
}
@@ -1621,6 +1617,10 @@
}
func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
+ if !c.Enabled() {
+ return
+ }
+
ctx := &depsContext{
BottomUpMutatorContext: actx,
moduleContextImpl: moduleContextImpl{
@@ -1636,7 +1636,7 @@
if ctx.Os() == android.Android {
version := ctx.sdkVersion()
- // rewriteNdkLibs takes a list of names of shared libraries and scans it for three types
+ // rewriteLibs takes a list of names of shared libraries and scans it for three types
// of names:
//
// 1. Name of an NDK library that refers to a prebuilt module.
@@ -1652,7 +1652,26 @@
// nonvariantLibs
vendorPublicLibraries := vendorPublicLibraries(actx.Config())
- rewriteNdkLibs := func(list []string) (nonvariantLibs []string, variantLibs []string) {
+ vendorSnapshotSharedLibs := vendorSnapshotSharedLibs(actx.Config())
+
+ rewriteVendorLibs := func(lib string) string {
+ if isLlndkLibrary(lib, ctx.Config()) {
+ return lib + llndkLibrarySuffix
+ }
+
+ // only modules with BOARD_VNDK_VERSION uses snapshot.
+ if c.VndkVersion() != actx.DeviceConfig().VndkVersion() {
+ return lib
+ }
+
+ if snapshot, ok := vendorSnapshotSharedLibs.get(lib, actx.Arch().ArchType); ok {
+ return snapshot
+ }
+
+ return lib
+ }
+
+ rewriteLibs := func(list []string) (nonvariantLibs []string, variantLibs []string) {
variantLibs = []string{}
nonvariantLibs = []string{}
for _, entry := range list {
@@ -1664,8 +1683,8 @@
} else {
variantLibs = append(variantLibs, name+ndkLibrarySuffix)
}
- } else if ctx.useVndk() && isLlndkLibrary(name, ctx.Config()) {
- nonvariantLibs = append(nonvariantLibs, name+llndkLibrarySuffix)
+ } else if ctx.useVndk() {
+ nonvariantLibs = append(nonvariantLibs, rewriteVendorLibs(entry))
} else if (ctx.Platform() || ctx.ProductSpecific()) && inList(name, *vendorPublicLibraries) {
vendorPublicLib := name + vendorPublicLibrarySuffix
if actx.OtherModuleExists(vendorPublicLib) {
@@ -1684,9 +1703,14 @@
return nonvariantLibs, variantLibs
}
- deps.SharedLibs, variantNdkLibs = rewriteNdkLibs(deps.SharedLibs)
- deps.LateSharedLibs, variantLateNdkLibs = rewriteNdkLibs(deps.LateSharedLibs)
- deps.ReexportSharedLibHeaders, _ = rewriteNdkLibs(deps.ReexportSharedLibHeaders)
+ deps.SharedLibs, variantNdkLibs = rewriteLibs(deps.SharedLibs)
+ deps.LateSharedLibs, variantLateNdkLibs = rewriteLibs(deps.LateSharedLibs)
+ deps.ReexportSharedLibHeaders, _ = rewriteLibs(deps.ReexportSharedLibHeaders)
+ if ctx.useVndk() {
+ for idx, lib := range deps.RuntimeLibs {
+ deps.RuntimeLibs[idx] = rewriteVendorLibs(lib)
+ }
+ }
}
buildStubs := false
@@ -1698,11 +1722,28 @@
}
}
+ rewriteSnapshotLibs := func(lib string, snapshotMap *snapshotMap) string {
+ // only modules with BOARD_VNDK_VERSION uses snapshot.
+ if c.VndkVersion() != actx.DeviceConfig().VndkVersion() {
+ return lib
+ }
+
+ if snapshot, ok := snapshotMap.get(lib, actx.Arch().ArchType); ok {
+ return snapshot
+ }
+
+ return lib
+ }
+
+ vendorSnapshotHeaderLibs := vendorSnapshotHeaderLibs(actx.Config())
for _, lib := range deps.HeaderLibs {
depTag := headerDepTag
if inList(lib, deps.ReexportHeaderLibHeaders) {
depTag = headerExportDepTag
}
+
+ lib = rewriteSnapshotLibs(lib, vendorSnapshotHeaderLibs)
+
if buildStubs {
actx.AddFarVariationDependencies(append(ctx.Target().Variations(), c.ImageVariation()),
depTag, lib)
@@ -1718,12 +1759,16 @@
}
syspropImplLibraries := syspropImplLibraries(actx.Config())
+ vendorSnapshotStaticLibs := vendorSnapshotStaticLibs(actx.Config())
for _, lib := range deps.WholeStaticLibs {
depTag := wholeStaticDepTag
if impl, ok := syspropImplLibraries[lib]; ok {
lib = impl
}
+
+ lib = rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs)
+
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, depTag, lib)
@@ -1739,14 +1784,24 @@
lib = impl
}
+ lib = rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs)
+
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, depTag, lib)
}
- actx.AddVariationDependencies([]blueprint.Variation{
- {Mutator: "link", Variation: "static"},
- }, lateStaticDepTag, deps.LateStaticLibs...)
+ if deps.StaticUnwinderIfLegacy && ctx.Config().UnbundledBuild() {
+ actx.AddVariationDependencies([]blueprint.Variation{
+ {Mutator: "link", Variation: "static"},
+ }, staticUnwinderDepTag, staticUnwinder(actx))
+ }
+
+ for _, lib := range deps.LateStaticLibs {
+ actx.AddVariationDependencies([]blueprint.Variation{
+ {Mutator: "link", Variation: "static"},
+ }, lateStaticDepTag, rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs))
+ }
addSharedLibDependencies := func(depTag DependencyTag, name string, version string) {
var variations []blueprint.Variation
@@ -1777,6 +1832,9 @@
for _, lib := range deps.SharedLibs {
depTag := SharedDepTag
+ if c.static() {
+ depTag = SharedFromStaticDepTag
+ }
if inList(lib, deps.ReexportSharedLibHeaders) {
depTag = sharedExportDepTag
}
@@ -2112,6 +2170,14 @@
}
}
+ if depTag == staticUnwinderDepTag {
+ if c.ApexProperties.Info.LegacyAndroid10Support {
+ depTag = StaticDepTag
+ } else {
+ return
+ }
+ }
+
// Extract ExplicitlyVersioned field from the depTag and reset it inside the struct.
// Otherwise, SharedDepTag and lateSharedDepTag with ExplicitlyVersioned set to true
// won't be matched to SharedDepTag and lateSharedDepTag.
@@ -2194,7 +2260,7 @@
depFile := android.OptionalPath{}
switch depTag {
- case ndkStubDepTag, SharedDepTag, sharedExportDepTag:
+ case ndkStubDepTag, SharedDepTag, SharedFromStaticDepTag, sharedExportDepTag:
ptr = &depPaths.SharedLibs
depPtr = &depPaths.SharedLibsDeps
depFile = ccDep.Toc()
@@ -2290,14 +2356,33 @@
*depPtr = append(*depPtr, dep.Path())
}
- makeLibName := func(depName string) string {
+ vendorSuffixModules := vendorSuffixModules(ctx.Config())
+
+ baseLibName := func(depName string) string {
libName := strings.TrimSuffix(depName, llndkLibrarySuffix)
libName = strings.TrimSuffix(libName, vendorPublicLibrarySuffix)
libName = strings.TrimPrefix(libName, "prebuilt_")
+ return libName
+ }
+
+ makeLibName := func(depName string) string {
+ libName := baseLibName(depName)
isLLndk := isLlndkLibrary(libName, ctx.Config())
isVendorPublicLib := inList(libName, *vendorPublicLibraries)
bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk
+ if c, ok := ccDep.(*Module); ok {
+ // Use base module name for snapshots when exporting to Makefile.
+ if c.isSnapshotPrebuilt() && !c.IsVndk() {
+ baseName := c.BaseModuleName()
+ if vendorSuffixModules[baseName] {
+ return baseName + ".vendor"
+ } else {
+ return baseName
+ }
+ }
+ }
+
if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() && !c.InRamdisk() && !c.InRecovery() {
// The vendor module is a no-vendor-variant VNDK library. Depend on the
// core module instead.
@@ -2337,6 +2422,8 @@
// they merely serve as Make dependencies and do not affect this lib itself.
c.Properties.AndroidMkSharedLibs = append(
c.Properties.AndroidMkSharedLibs, makeLibName(depName))
+ // Record baseLibName for snapshots.
+ c.Properties.SnapshotSharedLibs = append(c.Properties.SnapshotSharedLibs, baseLibName(depName))
case ndkStubDepTag, ndkLateStubDepTag:
c.Properties.AndroidMkSharedLibs = append(
c.Properties.AndroidMkSharedLibs,
@@ -2347,6 +2434,8 @@
case runtimeDepTag:
c.Properties.AndroidMkRuntimeLibs = append(
c.Properties.AndroidMkRuntimeLibs, makeLibName(depName))
+ // Record baseLibName for snapshots.
+ c.Properties.SnapshotRuntimeLibs = append(c.Properties.SnapshotRuntimeLibs, baseLibName(depName))
case wholeStaticDepTag:
c.Properties.AndroidMkWholeStaticLibs = append(
c.Properties.AndroidMkWholeStaticLibs, makeLibName(depName))
@@ -2372,8 +2461,6 @@
c.sabi.Properties.ReexportedIncludes = android.FirstUniqueStrings(c.sabi.Properties.ReexportedIncludes)
}
- c.allStaticDeps = gatherTransitiveStaticDeps(directStaticDeps)
-
return depPaths
}
@@ -2533,10 +2620,6 @@
return false
}
-func (c *Module) AllStaticDeps() []string {
- return c.allStaticDeps
-}
-
func (c *Module) AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
if c.linker != nil {
if library, ok := c.linker.(*libraryDecorator); ok {
@@ -2547,9 +2630,17 @@
func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
if depTag, ok := ctx.OtherModuleDependencyTag(dep).(DependencyTag); ok {
- if cc, ok := dep.(*Module); ok && cc.IsStubs() && depTag.Shared {
- // dynamic dep to a stubs lib crosses APEX boundary
- return false
+ if cc, ok := dep.(*Module); ok {
+ if cc.HasStubsVariants() && depTag.Shared && depTag.Library {
+ // dynamic dep to a stubs lib crosses APEX boundary
+ return false
+ }
+ if depTag.FromStatic {
+ // shared_lib dependency from a static lib is considered as crossing
+ // the APEX boundary because the dependency doesn't actually is
+ // linked; the dependency is used only during the compilation phase.
+ return false
+ }
}
}
return true
@@ -2601,7 +2692,6 @@
&VndkProperties{},
<OProperties{},
&PgoProperties{},
- &XomProperties{},
&android.ProtoProperties{},
)
@@ -2719,10 +2809,16 @@
platformVndkVersion,
productVndkVersion,
)
- } else if lib, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
+ } else if m.isSnapshotPrebuilt() {
// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
// PRODUCT_EXTRA_VNDK_VERSIONS.
- vendorVariants = append(vendorVariants, lib.version())
+ if snapshot, ok := m.linker.(interface {
+ version() string
+ }); ok {
+ vendorVariants = append(vendorVariants, snapshot.version())
+ } else {
+ mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
+ }
} else if m.HasVendorVariant() && !vendorSpecific {
// This will be available in /system, /vendor and /product
// or a /system directory that is available to vendor and product.
@@ -2819,6 +2915,14 @@
m.Properties.ImageVariationPrefix = VendorVariationPrefix
m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
squashVendorSrcs(m)
+
+ // Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION.
+ // Hide other vendor variants to avoid collision.
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion {
+ m.Properties.HideFromMake = true
+ m.SkipInstall()
+ }
} else if strings.HasPrefix(variant, ProductVariationPrefix) {
m.Properties.ImageVariationPrefix = ProductVariationPrefix
m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 332cc45..30ba733 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -258,8 +258,8 @@
}
}
-func checkVndkSnapshot(t *testing.T, ctx *android.TestContext, moduleName, snapshotFilename, subDir, variant string) {
- vndkSnapshot := ctx.SingletonForTests("vndk-snapshot")
+func checkSnapshot(t *testing.T, ctx *android.TestContext, singletonName, moduleName, snapshotFilename, subDir, variant string) {
+ snapshotSingleton := ctx.SingletonForTests(singletonName)
mod, ok := ctx.ModuleForTests(moduleName, variant).Module().(android.OutputFileProducer)
if !ok {
@@ -273,9 +273,9 @@
}
snapshotPath := filepath.Join(subDir, snapshotFilename)
- out := vndkSnapshot.Output(snapshotPath)
+ out := snapshotSingleton.Output(snapshotPath)
if out.Input.String() != outputFiles[0].String() {
- t.Errorf("The input of VNDK snapshot must be %q, but %q", out.Input.String(), outputFiles[0])
+ t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0])
}
}
@@ -398,16 +398,16 @@
variant := "android_vendor.VER_arm64_armv8-a_shared"
variant2nd := "android_vendor.VER_arm_armv7-a-neon_shared"
- checkVndkSnapshot(t, ctx, "libvndk", "libvndk.so", vndkCoreLibPath, variant)
- checkVndkSnapshot(t, ctx, "libvndk", "libvndk.so", vndkCoreLib2ndPath, variant2nd)
- checkVndkSnapshot(t, ctx, "libvndk_sp", "libvndk_sp-x.so", vndkSpLibPath, variant)
- checkVndkSnapshot(t, ctx, "libvndk_sp", "libvndk_sp-x.so", vndkSpLib2ndPath, variant2nd)
+ checkSnapshot(t, ctx, "vndk-snapshot", "libvndk", "libvndk.so", vndkCoreLibPath, variant)
+ checkSnapshot(t, ctx, "vndk-snapshot", "libvndk", "libvndk.so", vndkCoreLib2ndPath, variant2nd)
+ checkSnapshot(t, ctx, "vndk-snapshot", "libvndk_sp", "libvndk_sp-x.so", vndkSpLibPath, variant)
+ checkSnapshot(t, ctx, "vndk-snapshot", "libvndk_sp", "libvndk_sp-x.so", vndkSpLib2ndPath, variant2nd)
snapshotConfigsPath := filepath.Join(snapshotVariantPath, "configs")
- checkVndkSnapshot(t, ctx, "llndk.libraries.txt", "llndk.libraries.txt", snapshotConfigsPath, "")
- checkVndkSnapshot(t, ctx, "vndkcore.libraries.txt", "vndkcore.libraries.txt", snapshotConfigsPath, "")
- checkVndkSnapshot(t, ctx, "vndksp.libraries.txt", "vndksp.libraries.txt", snapshotConfigsPath, "")
- checkVndkSnapshot(t, ctx, "vndkprivate.libraries.txt", "vndkprivate.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, "vndk-snapshot", "llndk.libraries.txt", "llndk.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, "vndk-snapshot", "vndkcore.libraries.txt", "vndkcore.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, "vndk-snapshot", "vndksp.libraries.txt", "vndksp.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, "vndk-snapshot", "vndkprivate.libraries.txt", "vndkprivate.libraries.txt", snapshotConfigsPath, "")
checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
"LLNDK: libc.so",
@@ -799,6 +799,88 @@
`)
}
+func TestVendorSnapshot(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvendor",
+ vendor: true,
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvendor_available",
+ vendor_available: true,
+ nocrt: true,
+ }
+
+ cc_library_headers {
+ name: "libvendor_headers",
+ vendor_available: true,
+ nocrt: true,
+ }
+
+ cc_binary {
+ name: "vendor_bin",
+ vendor: true,
+ nocrt: true,
+ }
+
+ cc_binary {
+ name: "vendor_available_bin",
+ vendor_available: true,
+ nocrt: true,
+ }
+`
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ ctx := testCcWithConfig(t, config)
+
+ // Check Vendor snapshot output.
+
+ snapshotDir := "vendor-snapshot"
+ snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ []string{"arm", "armv7-a-neon"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ // For shared libraries, only non-VNDK vendor_available modules are captured
+ sharedVariant := fmt.Sprintf("android_vendor.VER_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+ checkSnapshot(t, ctx, "vendor-snapshot", "libvendor", "libvendor.so", sharedDir, sharedVariant)
+ checkSnapshot(t, ctx, "vendor-snapshot", "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
+
+ // For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
+ staticVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static", archType, archVariant)
+ staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
+ checkSnapshot(t, ctx, "vendor-snapshot", "libvndk", "libvndk.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, "vendor-snapshot", "libvendor", "libvendor.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, "vendor-snapshot", "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
+
+ // For binary libraries, all vendor:true and vendor_available modules are captured.
+ if archType == "arm64" {
+ binaryVariant := fmt.Sprintf("android_vendor.VER_%s_%s", archType, archVariant)
+ binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
+ checkSnapshot(t, ctx, "vendor-snapshot", "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
+ checkSnapshot(t, ctx, "vendor-snapshot", "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
+ }
+ }
+}
+
func TestDoubleLoadableDepError(t *testing.T) {
// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
@@ -2592,20 +2674,20 @@
cc_binary {
name: "mybin",
srcs: ["foo.c"],
- static_libs: ["libB"],
+ static_libs: ["libfooB"],
static_executable: true,
stl: "none",
}
cc_library {
- name: "libB",
+ name: "libfooB",
srcs: ["foo.c"],
- shared_libs: ["libC"],
+ shared_libs: ["libfooC"],
stl: "none",
}
cc_library {
- name: "libC",
+ name: "libfooC",
srcs: ["foo.c"],
stl: "none",
stubs: {
@@ -2615,7 +2697,7 @@
mybin := ctx.ModuleForTests("mybin", "android_arm64_armv8-a").Module().(*Module)
actual := mybin.depsInLinkOrder
- expected := getOutputPaths(ctx, "android_arm64_armv8-a_static", []string{"libB", "libC"})
+ expected := getOutputPaths(ctx, "android_arm64_armv8-a_static", []string{"libfooB", "libfooC"})
if !reflect.DeepEqual(actual, expected) {
t.Errorf("staticDeps orderings were not propagated correctly"+
@@ -2751,3 +2833,42 @@
t.Errorf("libboth ar rule wanted %q, got %q", w, g)
}
}
+
+func TestProductVariableDefaults(t *testing.T) {
+ bp := `
+ cc_defaults {
+ name: "libfoo_defaults",
+ srcs: ["foo.c"],
+ cppflags: ["-DFOO"],
+ product_variables: {
+ debuggable: {
+ cppflags: ["-DBAR"],
+ },
+ },
+ }
+
+ cc_library {
+ name: "libfoo",
+ defaults: ["libfoo_defaults"],
+ }
+ `
+
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.Debuggable = BoolPtr(true)
+
+ ctx := CreateTestContext()
+ ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("variable", android.VariableMutator).Parallel()
+ })
+ ctx.Register(config)
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module)
+ if !android.InList("-DBAR", libfoo.flags.Local.CppFlags) {
+ t.Errorf("expected -DBAR in cppflags, got %q", libfoo.flags.Local.CppFlags)
+ }
+}
diff --git a/cc/cflag_artifacts.go b/cc/cflag_artifacts.go
index b61f2a8..855ff25 100644
--- a/cc/cflag_artifacts.go
+++ b/cc/cflag_artifacts.go
@@ -41,12 +41,7 @@
// filter.
func allowedDir(subdir string) bool {
subdir += "/"
- for _, prefix := range TrackedCFlagsDir {
- if strings.HasPrefix(subdir, prefix) {
- return true
- }
- }
- return false
+ return android.HasAnyPrefix(subdir, TrackedCFlagsDir)
}
func (s *cflagArtifactsText) genFlagFilename(flag string) string {
diff --git a/cc/compiler.go b/cc/compiler.go
index 1ced451..c1a8d96 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -241,12 +241,7 @@
// Return true if the module is in the WarningAllowedProjects.
func warningsAreAllowed(subdir string) bool {
subdir += "/"
- for _, prefix := range config.WarningAllowedProjects {
- if strings.HasPrefix(subdir, prefix) {
- return true
- }
- }
- return false
+ return android.HasAnyPrefix(subdir, config.WarningAllowedProjects)
}
func addToModuleList(ctx ModuleContext, key android.OnceKey, module string) {
@@ -515,7 +510,7 @@
// Exclude directories from manual binder interface whitelisting.
//TODO(b/145621474): Move this check into IInterface.h when clang-tidy no longer uses absolute paths.
- if android.PrefixInList(ctx.ModuleDir(), allowedManualInterfacePaths) {
+ if android.HasAnyPrefix(ctx.ModuleDir(), allowedManualInterfacePaths) {
flags.Local.CFlags = append(flags.Local.CFlags, "-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES")
}
@@ -604,16 +599,12 @@
func isThirdParty(path string) bool {
thirdPartyDirPrefixes := []string{"external/", "vendor/", "hardware/"}
- for _, prefix := range thirdPartyDirPrefixes {
- if strings.HasPrefix(path, prefix) {
- for _, prefix := range thirdPartyDirPrefixExceptions {
- if prefix.MatchString(path) {
- return false
- }
+ if android.HasAnyPrefix(path, thirdPartyDirPrefixes) {
+ for _, prefix := range thirdPartyDirPrefixExceptions {
+ if prefix.MatchString(path) {
+ return false
}
- break
}
}
-
return true
}
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 8618d09..d849906 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -169,6 +169,10 @@
"-Wno-reorder-init-list",
// http://b/145211066
"-Wno-implicit-int-float-conversion",
+ // New warnings to be fixed after clang-r377782.
+ "-Wno-int-in-bool-context", // http://b/148287349
+ "-Wno-sizeof-array-div", // http://b/148815709
+ "-Wno-tautological-overlap-compare", // http://b/148815696
}, " "))
// Extra cflags for external third-party projects to disable warnings that
diff --git a/cc/config/global.go b/cc/config/global.go
index 333885f..d01dd84 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -127,8 +127,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r370808b"
- ClangDefaultShortVersion = "10.0.2"
+ ClangDefaultVersion = "clang-r377782b"
+ ClangDefaultShortVersion = "10.0.4"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index 52bd9f0..54f693e 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -18,48 +18,12 @@
// For these libraries, the vendor variants must be installed even if the device
// has VndkUseCoreVariant set.
var VndkMustUseVendorVariantList = []string{
- "android.hardware.automotive.evs@1.0",
- "android.hardware.automotive.vehicle@2.0",
- "android.hardware.broadcastradio@2.0",
- "android.hardware.camera.device@1.0",
- "android.hardware.camera.device@3.2",
- "android.hardware.camera.device@3.3",
- "android.hardware.camera.device@3.4",
- "android.hardware.camera.provider@2.4",
- "android.hardware.fastboot@1.0",
- "android.hardware.media.bufferpool@1.0",
- "android.hardware.neuralnetworks@1.0",
- "android.hardware.neuralnetworks@1.1",
- "android.hardware.neuralnetworks@1.2",
- "android.hardware.neuralnetworks@1.3",
+ "android.hardware.light-ndk_platform",
+ "android.hardware.identity-ndk_platform",
"android.hardware.nfc@1.2",
- "android.hardware.oemlock@1.0",
- "android.hardware.power.stats@1.0",
"android.hardware.power-ndk_platform",
- "android.hardware.power@1.0",
- "android.hardware.power@1.1",
- "android.hardware.radio@1.4",
- "android.hardware.secure_element@1.0",
- "android.hardware.sensors@1.0",
- "android.hardware.soundtrigger@2.0",
- "android.hardware.soundtrigger@2.0-core",
- "android.hardware.soundtrigger@2.1",
- "android.hardware.tetheroffload.config@1.0",
- "android.hardware.tetheroffload.control@1.0",
"android.hardware.vibrator-ndk_platform",
- "android.hardware.weaver@1.0",
- "android.hardware.wifi.hostapd@1.0",
- "android.hardware.wifi.offload@1.0",
- "android.hardware.wifi.supplicant@1.0",
- "android.hardware.wifi.supplicant@1.1",
- "android.hardware.wifi@1.1",
- "android.hardware.wifi@1.2",
- "android.hardwareundtrigger@2.0",
- "android.hardwareundtrigger@2.0-core",
- "android.hardwareundtrigger@2.1",
- "libaudioroute",
"libbinder",
- "libcamera_metadata",
"libcrypto",
"libexpat",
"libgatekeeper",
@@ -68,45 +32,17 @@
"libkeymaster_messages",
"libkeymaster_portable",
"libmedia_omx",
- "libprotobuf-cpp-full",
- "libprotobuf-cpp-lite",
"libpuresoftkeymasterdevice",
"libselinux",
"libsoftkeymasterdevice",
"libsqlite",
"libssl",
- "libstagefright_amrnb_common",
"libstagefright_bufferpool@2.0",
"libstagefright_bufferqueue_helper",
- "libstagefright_enc_common",
- "libstagefright_flacdec",
"libstagefright_foundation",
"libstagefright_omx",
"libstagefright_omx_utils",
- "libstagefright_soft_aacdec",
- "libstagefright_soft_aacenc",
- "libstagefright_soft_amrdec",
- "libstagefright_soft_amrnbenc",
- "libstagefright_soft_amrwbenc",
- "libstagefright_soft_avcdec",
- "libstagefright_soft_avcenc",
- "libstagefright_soft_flacdec",
- "libstagefright_soft_flacenc",
- "libstagefright_soft_g711dec",
- "libstagefright_soft_gsmdec",
- "libstagefright_soft_hevcdec",
- "libstagefright_soft_mp3dec",
- "libstagefright_soft_mpeg2dec",
- "libstagefright_soft_mpeg4dec",
- "libstagefright_soft_mpeg4enc",
- "libstagefright_soft_opusdec",
- "libstagefright_soft_rawdec",
- "libstagefright_soft_vorbisdec",
- "libstagefright_soft_vpxdec",
- "libstagefright_soft_vpxenc",
"libstagefright_xmlparser",
"libui",
- "libvorbisidec",
"libxml2",
- "libyuv",
}
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
index 63b9d48..25225b5 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/x86_darwin_host.go
@@ -100,7 +100,7 @@
pctx.VariableFunc("macSdkRoot", func(ctx android.PackageVarContext) string {
return xcrunSdk(ctx, "--show-sdk-path")
})
- pctx.StaticVariable("macMinVersion", "10.8")
+ pctx.StaticVariable("macMinVersion", "10.10")
pctx.VariableFunc("MacArPath", func(ctx android.PackageVarContext) string {
return xcrun(ctx, "--find", "ar")
})
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index f08a379..13b5511 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -234,7 +234,7 @@
}
func (toolchainLinuxX86) LibclangRuntimeLibraryArch() string {
- return "i686"
+ return "i386"
}
func (toolchainLinuxX8664) LibclangRuntimeLibraryArch() string {
diff --git a/cc/gen.go b/cc/gen.go
index 17ab45f..b0aadc6 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -162,17 +162,19 @@
})
}
-func genSysprop(ctx android.ModuleContext, syspropFile android.Path) (android.Path, android.Path) {
+func genSysprop(ctx android.ModuleContext, syspropFile android.Path) (android.Path, android.Paths) {
headerFile := android.PathForModuleGen(ctx, "sysprop", "include", syspropFile.Rel()+".h")
publicHeaderFile := android.PathForModuleGen(ctx, "sysprop/public", "include", syspropFile.Rel()+".h")
cppFile := android.PathForModuleGen(ctx, "sysprop", syspropFile.Rel()+".cpp")
+ headers := android.WritablePaths{headerFile, publicHeaderFile}
+
ctx.Build(pctx, android.BuildParams{
- Rule: sysprop,
- Description: "sysprop " + syspropFile.Rel(),
- Output: cppFile,
- ImplicitOutput: headerFile,
- Input: syspropFile,
+ Rule: sysprop,
+ Description: "sysprop " + syspropFile.Rel(),
+ Output: cppFile,
+ ImplicitOutputs: headers,
+ Input: syspropFile,
Args: map[string]string{
"headerOutDir": filepath.Dir(headerFile.String()),
"publicOutDir": filepath.Dir(publicHeaderFile.String()),
@@ -181,7 +183,7 @@
},
})
- return cppFile, headerFile
+ return cppFile, headers.Paths()
}
func genWinMsg(ctx android.ModuleContext, srcFile android.Path, flags builderFlags) (android.Path, android.Path) {
@@ -259,9 +261,9 @@
srcFiles[i] = rcFile
deps = append(deps, headerFile)
case ".sysprop":
- cppFile, headerFile := genSysprop(ctx, srcFile)
+ cppFile, headerFiles := genSysprop(ctx, srcFile)
srcFiles[i] = cppFile
- deps = append(deps, headerFile)
+ deps = append(deps, headerFiles...)
}
}
diff --git a/cc/library.go b/cc/library.go
index 0bddab5..6ffb7fc 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -183,7 +183,6 @@
ctx.RegisterModuleType("cc_library", LibraryFactory)
ctx.RegisterModuleType("cc_library_host_static", LibraryHostStaticFactory)
ctx.RegisterModuleType("cc_library_host_shared", LibraryHostSharedFactory)
- ctx.RegisterModuleType("cc_library_headers", LibraryHeaderFactory)
}
// cc_library creates both static and/or shared libraries for a device and/or
@@ -233,16 +232,6 @@
return module.Init()
}
-// cc_library_headers contains a set of c/c++ headers which are imported by
-// other soong cc modules using the header_libs property. For best practices,
-// use export_include_dirs property or LOCAL_EXPORT_C_INCLUDE_DIRS for
-// Make.
-func LibraryHeaderFactory() android.Module {
- module, library := NewLibrary(android.HostAndDeviceSupported)
- library.HeaderOnly()
- return module.Init()
-}
-
type flagExporter struct {
Properties FlagExporterProperties
@@ -281,11 +270,9 @@
}
func (f *flagExporter) reexportFlags(flags ...string) {
- for _, flag := range flags {
- if strings.HasPrefix(flag, "-I") || strings.HasPrefix(flag, "-isystem") {
- panic(fmt.Errorf("Exporting invalid flag %q: "+
- "use reexportDirs or reexportSystemDirs to export directories", flag))
- }
+ if android.PrefixInList(flags, "-I") || android.PrefixInList(flags, "-isystem") {
+ panic(fmt.Errorf("Exporting invalid flag %q: "+
+ "use reexportDirs or reexportSystemDirs to export directories", flag))
}
f.flags = append(f.flags, flags...)
}
@@ -1316,22 +1303,28 @@
if cc_prebuilt {
library := mctx.Module().(*Module).linker.(prebuiltLibraryInterface)
- // Always create both the static and shared variants for prebuilt libraries, and then disable the one
- // that is not being used. This allows them to share the name of a cc_library module, which requires that
- // all the variants of the cc_library also exist on the prebuilt.
- modules := mctx.CreateLocalVariations("static", "shared")
- static := modules[0].(*Module)
- shared := modules[1].(*Module)
+ // Differentiate between header only and building an actual static/shared library
+ if library.buildStatic() || library.buildShared() {
+ // Always create both the static and shared variants for prebuilt libraries, and then disable the one
+ // that is not being used. This allows them to share the name of a cc_library module, which requires that
+ // all the variants of the cc_library also exist on the prebuilt.
+ modules := mctx.CreateLocalVariations("static", "shared")
+ static := modules[0].(*Module)
+ shared := modules[1].(*Module)
- static.linker.(prebuiltLibraryInterface).setStatic()
- shared.linker.(prebuiltLibraryInterface).setShared()
+ static.linker.(prebuiltLibraryInterface).setStatic()
+ shared.linker.(prebuiltLibraryInterface).setShared()
- if !library.buildStatic() {
- static.linker.(prebuiltLibraryInterface).disablePrebuilt()
+ if !library.buildStatic() {
+ static.linker.(prebuiltLibraryInterface).disablePrebuilt()
+ }
+ if !library.buildShared() {
+ shared.linker.(prebuiltLibraryInterface).disablePrebuilt()
+ }
+ } else {
+ // Header only
}
- if !library.buildShared() {
- shared.linker.(prebuiltLibraryInterface).disablePrebuilt()
- }
+
} else if library, ok := mctx.Module().(LinkableInterface); ok && library.CcLibraryInterface() {
// Non-cc.Modules may need an empty variant for their mutators.
diff --git a/cc/library_headers.go b/cc/library_headers.go
new file mode 100644
index 0000000..88cf7af
--- /dev/null
+++ b/cc/library_headers.go
@@ -0,0 +1,56 @@
+// Copyright 2020 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 cc
+
+import "android/soong/android"
+
+func init() {
+ RegisterLibraryHeadersBuildComponents(android.InitRegistrationContext)
+
+ // Register sdk member types.
+ android.RegisterSdkMemberType(headersLibrarySdkMemberType)
+}
+
+var headersLibrarySdkMemberType = &librarySdkMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "native_header_libs",
+ SupportsSdk: true,
+ },
+ prebuiltModuleType: "cc_prebuilt_library_headers",
+ linkTypes: nil,
+}
+
+func RegisterLibraryHeadersBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("cc_library_headers", LibraryHeaderFactory)
+ ctx.RegisterModuleType("cc_prebuilt_library_headers", prebuiltLibraryHeaderFactory)
+}
+
+// cc_library_headers contains a set of c/c++ headers which are imported by
+// other soong cc modules using the header_libs property. For best practices,
+// use export_include_dirs property or LOCAL_EXPORT_C_INCLUDE_DIRS for
+// Make.
+func LibraryHeaderFactory() android.Module {
+ module, library := NewLibrary(android.HostAndDeviceSupported)
+ library.HeaderOnly()
+ module.sdkMemberTypes = []android.SdkMemberType{headersLibrarySdkMemberType}
+ return module.Init()
+}
+
+// cc_prebuilt_library_headers is a prebuilt version of cc_library_headers
+func prebuiltLibraryHeaderFactory() android.Module {
+ module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported)
+ library.HeaderOnly()
+ return module.Init()
+}
diff --git a/cc/library_headers_test.go b/cc/library_headers_test.go
new file mode 100644
index 0000000..564ef61
--- /dev/null
+++ b/cc/library_headers_test.go
@@ -0,0 +1,62 @@
+// Copyright 2020 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 cc
+
+import (
+ "strings"
+ "testing"
+)
+
+func TestLibraryHeaders(t *testing.T) {
+ ctx := testCc(t, `
+ cc_library_headers {
+ name: "headers",
+ export_include_dirs: ["my_include"],
+ }
+ cc_library_static {
+ name: "lib",
+ srcs: ["foo.c"],
+ header_libs: ["headers"],
+ }
+ `)
+
+ // test if header search paths are correctly added
+ cc := ctx.ModuleForTests("lib", "android_arm64_armv8-a_static").Rule("cc")
+ cflags := cc.Args["cFlags"]
+ if !strings.Contains(cflags, " -Imy_include ") {
+ t.Errorf("cflags for libsystem must contain -Imy_include, but was %#v.", cflags)
+ }
+}
+
+func TestPrebuiltLibraryHeaders(t *testing.T) {
+ ctx := testCc(t, `
+ cc_prebuilt_library_headers {
+ name: "headers",
+ export_include_dirs: ["my_include"],
+ }
+ cc_library_static {
+ name: "lib",
+ srcs: ["foo.c"],
+ header_libs: ["headers"],
+ }
+ `)
+
+ // test if header search paths are correctly added
+ cc := ctx.ModuleForTests("lib", "android_arm64_armv8-a_static").Rule("cc")
+ cflags := cc.Args["cFlags"]
+ if !strings.Contains(cflags, " -Imy_include ") {
+ t.Errorf("cflags for libsystem must contain -Imy_include, but was %#v.", cflags)
+ }
+}
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 165901d..a36917e 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -65,12 +65,19 @@
if version == "" {
version = LatestStubsVersionFor(mctx.Config(), name)
}
- for _, linkType := range mt.linkTypes {
+ if mt.linkTypes == nil {
mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
{Mutator: "image", Variation: android.CoreVariation},
- {Mutator: "link", Variation: linkType},
{Mutator: "version", Variation: version},
}...), dependencyTag, name)
+ } else {
+ for _, linkType := range mt.linkTypes {
+ mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
+ {Mutator: "image", Variation: android.CoreVariation},
+ {Mutator: "link", Variation: linkType},
+ {Mutator: "version", Variation: version},
+ }...), dependencyTag, name)
+ }
}
}
}
@@ -92,7 +99,7 @@
// copy exported header files and stub *.so files
func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
info := mt.organizeVariants(member)
- buildSharedNativeLibSnapshot(sdkModuleContext, info, builder, member)
+ info.generatePrebuiltLibrary(sdkModuleContext, builder, member)
}
// Organize the variants by architecture.
@@ -115,7 +122,7 @@
name: memberName,
archType: ccModule.Target().Arch.ArchType.String(),
ExportedIncludeDirs: exportedIncludeDirs,
- ExportedGeneratedIncludeDirs: exportedGeneratedIncludeDirs,
+ exportedGeneratedIncludeDirs: exportedGeneratedIncludeDirs,
ExportedSystemIncludeDirs: ccModule.ExportedSystemIncludeDirs(),
ExportedFlags: ccModule.ExportedFlags(),
exportedGeneratedHeaders: ccModule.ExportedGeneratedHeaders(),
@@ -197,85 +204,148 @@
}
}
-func buildSharedNativeLibSnapshot(sdkModuleContext android.ModuleContext, info *nativeLibInfo, builder android.SnapshotBuilder, member android.SdkMember) {
- // a function for emitting include dirs
- addExportedDirCopyCommandsForNativeLibs := func(lib nativeLibInfoProperties) {
- // Do not include ExportedGeneratedIncludeDirs in the list of directories whose
- // contents are copied as they are copied from exportedGeneratedHeaders below.
- includeDirs := lib.ExportedIncludeDirs
- includeDirs = append(includeDirs, lib.ExportedSystemIncludeDirs...)
- for _, dir := range includeDirs {
- // lib.ArchType is "" for common properties.
- targetDir := filepath.Join(lib.archType, nativeIncludeDir)
-
- // TODO(jiyong) copy headers having other suffixes
- headers, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.h", nil)
- for _, file := range headers {
- src := android.PathForSource(sdkModuleContext, file)
- dest := filepath.Join(targetDir, file)
- builder.CopyToSnapshot(src, dest)
- }
- }
-
- genHeaders := lib.exportedGeneratedHeaders
- for _, file := range genHeaders {
- // lib.ArchType is "" for common properties.
- targetDir := filepath.Join(lib.archType, nativeGeneratedIncludeDir)
-
- dest := filepath.Join(targetDir, lib.name, file.Rel())
- builder.CopyToSnapshot(file, dest)
- }
- }
-
- addExportedDirCopyCommandsForNativeLibs(info.commonProperties)
-
- // for each architecture
- for _, av := range info.archVariantProperties {
- builder.CopyToSnapshot(av.outputFile, nativeLibraryPathFor(av))
-
- addExportedDirCopyCommandsForNativeLibs(av)
- }
-
- info.generatePrebuiltLibrary(sdkModuleContext, builder, member)
-}
-
func (info *nativeLibInfo) generatePrebuiltLibrary(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
pbm := builder.AddPrebuiltModule(member, info.memberType.prebuiltModuleType)
- addPossiblyArchSpecificProperties(info.commonProperties, pbm)
+ addPossiblyArchSpecificProperties(sdkModuleContext, builder, info.commonProperties, pbm)
archProperties := pbm.AddPropertySet("arch")
for _, av := range info.archVariantProperties {
archTypeProperties := archProperties.AddPropertySet(av.archType)
- // Add any arch specific properties inside the appropriate arch: {<arch>: {...}} block
- archTypeProperties.AddProperty("srcs", []string{nativeLibraryPathFor(av)})
- addPossiblyArchSpecificProperties(av, archTypeProperties)
+ // If the library has some link types then it produces an output binary file, otherwise it
+ // is header only.
+ if info.memberType.linkTypes != nil {
+ // Copy the generated library to the snapshot and add a reference to it in the .bp module.
+ nativeLibraryPath := nativeLibraryPathFor(av)
+ builder.CopyToSnapshot(av.outputFile, nativeLibraryPath)
+ archTypeProperties.AddProperty("srcs", []string{nativeLibraryPath})
+ }
+
+ // Add any arch specific properties inside the appropriate arch: {<arch>: {...}} block
+ addPossiblyArchSpecificProperties(sdkModuleContext, builder, av, archTypeProperties)
}
pbm.AddProperty("stl", "none")
pbm.AddProperty("system_shared_libs", []string{})
}
-// Add properties that may, or may not, be arch specific.
-func addPossiblyArchSpecificProperties(libInfo nativeLibInfoProperties, outputProperties android.BpPropertySet) {
- addExportedDirsForNativeLibs(libInfo, outputProperties, false /*systemInclude*/)
- addExportedDirsForNativeLibs(libInfo, outputProperties, true /*systemInclude*/)
+type includeDirsProperty struct {
+ // Accessor to retrieve the paths
+ pathsGetter func(libInfo nativeLibInfoProperties) android.Paths
+
+ // The name of the property in the prebuilt library, "" means there is no property.
+ propertyName string
+
+ // The directory within the snapshot directory into which items should be copied.
+ snapshotDir string
+
+ // True if the items on the path should be copied.
+ copy bool
+
+ // True if the paths represent directories, files if they represent files.
+ dirs bool
}
-// a function for emitting include dirs
-func addExportedDirsForNativeLibs(lib nativeLibInfoProperties, properties android.BpPropertySet, systemInclude bool) {
- includeDirs := nativeIncludeDirPathsFor(lib, systemInclude)
- if len(includeDirs) == 0 {
- return
+var includeDirProperties = []includeDirsProperty{
+ {
+ // ExportedIncludeDirs lists directories that contains some header files to be
+ // copied into a directory in the snapshot. The snapshot directories must be added to
+ // the export_include_dirs property in the prebuilt module in the snapshot.
+ pathsGetter: func(libInfo nativeLibInfoProperties) android.Paths { return libInfo.ExportedIncludeDirs },
+ propertyName: "export_include_dirs",
+ snapshotDir: nativeIncludeDir,
+ copy: true,
+ dirs: true,
+ },
+ {
+ // ExportedSystemIncludeDirs lists directories that contains some system header files to
+ // be copied into a directory in the snapshot. The snapshot directories must be added to
+ // the export_system_include_dirs property in the prebuilt module in the snapshot.
+ pathsGetter: func(libInfo nativeLibInfoProperties) android.Paths { return libInfo.ExportedSystemIncludeDirs },
+ propertyName: "export_system_include_dirs",
+ snapshotDir: nativeIncludeDir,
+ copy: true,
+ dirs: true,
+ },
+ {
+ // exportedGeneratedIncludeDirs lists directories that contains some header files
+ // that are explicitly listed in the exportedGeneratedHeaders property. So, the contents
+ // of these directories do not need to be copied, but these directories do need adding to
+ // the export_include_dirs property in the prebuilt module in the snapshot.
+ pathsGetter: func(libInfo nativeLibInfoProperties) android.Paths { return libInfo.exportedGeneratedIncludeDirs },
+ propertyName: "export_include_dirs",
+ snapshotDir: nativeGeneratedIncludeDir,
+ copy: false,
+ dirs: true,
+ },
+ {
+ // exportedGeneratedHeaders lists header files that are in one of the directories
+ // specified in exportedGeneratedIncludeDirs must be copied into the snapshot.
+ // As they are in a directory in exportedGeneratedIncludeDirs they do not need adding to a
+ // property in the prebuilt module in the snapshot.
+ pathsGetter: func(libInfo nativeLibInfoProperties) android.Paths { return libInfo.exportedGeneratedHeaders },
+ propertyName: "",
+ snapshotDir: nativeGeneratedIncludeDir,
+ copy: true,
+ dirs: false,
+ },
+}
+
+// Add properties that may, or may not, be arch specific.
+func addPossiblyArchSpecificProperties(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, libInfo nativeLibInfoProperties, outputProperties android.BpPropertySet) {
+
+ // Map from property name to the include dirs to add to the prebuilt module in the snapshot.
+ includeDirs := make(map[string][]string)
+
+ // Iterate over each include directory property, copying files and collating property
+ // values where necessary.
+ for _, propertyInfo := range includeDirProperties {
+ // Calculate the base directory in the snapshot into which the files will be copied.
+ // lib.ArchType is "" for common properties.
+ targetDir := filepath.Join(libInfo.archType, propertyInfo.snapshotDir)
+
+ propertyName := propertyInfo.propertyName
+
+ // Iterate over each path in one of the include directory properties.
+ for _, path := range propertyInfo.pathsGetter(libInfo) {
+
+ // Copy the files/directories when necessary.
+ if propertyInfo.copy {
+ if propertyInfo.dirs {
+ // When copying a directory glob and copy all the headers within it.
+ // TODO(jiyong) copy headers having other suffixes
+ headers, _ := sdkModuleContext.GlobWithDeps(path.String()+"/**/*.h", nil)
+ for _, file := range headers {
+ src := android.PathForSource(sdkModuleContext, file)
+ dest := filepath.Join(targetDir, file)
+ builder.CopyToSnapshot(src, dest)
+ }
+ } else {
+ // Otherwise, just copy the files.
+ dest := filepath.Join(targetDir, libInfo.name, path.Rel())
+ builder.CopyToSnapshot(path, dest)
+ }
+ }
+
+ // Only directories are added to a property.
+ if propertyInfo.dirs {
+ var snapshotPath string
+ if isGeneratedHeaderDirectory(path) {
+ snapshotPath = filepath.Join(targetDir, libInfo.name)
+ } else {
+ snapshotPath = filepath.Join(targetDir, path.String())
+ }
+
+ includeDirs[propertyName] = append(includeDirs[propertyName], snapshotPath)
+ }
+ }
}
- var propertyName string
- if !systemInclude {
- propertyName = "export_include_dirs"
- } else {
- propertyName = "export_system_include_dirs"
+
+ // Add the collated include dir properties to the output.
+ for property, dirs := range includeDirs {
+ outputProperties.AddProperty(property, dirs)
}
- properties.AddProperty(propertyName, includeDirs)
}
const (
@@ -290,31 +360,6 @@
nativeStubDir, lib.outputFile.Base())
}
-// paths to the include dirs of a native shared library. Relative to <sdk_root>/<api_dir>
-func nativeIncludeDirPathsFor(lib nativeLibInfoProperties, systemInclude bool) []string {
- var result []string
- var includeDirs []android.Path
- if !systemInclude {
- // Include the generated include dirs in the exported include dirs.
- includeDirs = append(lib.ExportedIncludeDirs, lib.ExportedGeneratedIncludeDirs...)
- } else {
- includeDirs = lib.ExportedSystemIncludeDirs
- }
- for _, dir := range includeDirs {
- var path string
- if isGeneratedHeaderDirectory(dir) {
- path = filepath.Join(nativeGeneratedIncludeDir, lib.name)
- } else {
- path = filepath.Join(nativeIncludeDir, dir.String())
- }
-
- // lib.ArchType is "" for common properties.
- path = filepath.Join(lib.archType, path)
- result = append(result, path)
- }
- return result
-}
-
// nativeLibInfoProperties represents properties of a native lib
//
// The exported (capitalized) fields will be examined and may be changed during common value extraction.
@@ -327,14 +372,31 @@
// This is "" for common properties.
archType string
- ExportedIncludeDirs android.Paths
- ExportedGeneratedIncludeDirs android.Paths
- ExportedSystemIncludeDirs android.Paths
- ExportedFlags []string
+ // The list of possibly common exported include dirs.
+ //
+ // This field is exported as its contents may not be arch specific.
+ ExportedIncludeDirs android.Paths
- // exportedGeneratedHeaders is not exported as if set it is always arch specific.
+ // The list of arch specific exported generated include dirs.
+ //
+ // This field is not exported as its contents are always arch specific.
+ exportedGeneratedIncludeDirs android.Paths
+
+ // The list of arch specific exported generated header files.
+ //
+ // This field is not exported as its contents are is always arch specific.
exportedGeneratedHeaders android.Paths
+ // The list of possibly common exported system include dirs.
+ //
+ // This field is exported as its contents may not be arch specific.
+ ExportedSystemIncludeDirs android.Paths
+
+ // The list of possibly common exported flags.
+ //
+ // This field is exported as its contents may not be arch specific.
+ ExportedFlags []string
+
// outputFile is not exported as it is always arch specific.
outputFile android.Path
}
diff --git a/cc/linkable.go b/cc/linkable.go
index 3c46d9d..e4f034c 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -54,8 +54,6 @@
ToolchainLibrary() bool
NdkPrebuiltStl() bool
StubDecorator() bool
-
- AllStaticDeps() []string
}
type DependencyTag struct {
@@ -67,12 +65,17 @@
ReexportFlags bool
ExplicitlyVersioned bool
+
+ FromStatic bool
}
var (
SharedDepTag = DependencyTag{Name: "shared", Library: true, Shared: true}
StaticDepTag = DependencyTag{Name: "static", Library: true}
+ // Same as SharedDepTag, but from a static lib
+ SharedFromStaticDepTag = DependencyTag{Name: "shared from static", Library: true, Shared: true, FromStatic: true}
+
CrtBeginDepTag = DependencyTag{Name: "crtbegin"}
CrtEndDepTag = DependencyTag{Name: "crtend"}
)
diff --git a/cc/linker.go b/cc/linker.go
index 5a16cbd..a7b621a 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -101,6 +101,10 @@
// variant of the C/C++ module.
Shared_libs []string
+ // list of static libs that only should be used to build the vendor
+ // variant of the C/C++ module.
+ Static_libs []string
+
// list of shared libs that should not be used to build the vendor variant
// of the C/C++ module.
Exclude_shared_libs []string
@@ -222,6 +226,7 @@
deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Vendor.Shared_libs...)
deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor.Exclude_shared_libs)
deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Vendor.Exclude_shared_libs)
+ deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Target.Vendor.Static_libs...)
deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs)
deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Vendor.Exclude_header_libs)
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor.Exclude_static_libs)
@@ -496,19 +501,21 @@
var injectVersionSymbol = pctx.AndroidStaticRule("injectVersionSymbol",
blueprint.RuleParams{
Command: "$symbolInjectCmd -i $in -o $out -s soong_build_number " +
- "-from 'SOONG BUILD NUMBER PLACEHOLDER' -v $buildNumberFromFile",
+ "-from 'SOONG BUILD NUMBER PLACEHOLDER' -v $$(cat $buildNumberFile)",
CommandDeps: []string{"$symbolInjectCmd"},
},
- "buildNumberFromFile")
+ "buildNumberFile")
func (linker *baseLinker) injectVersionSymbol(ctx ModuleContext, in android.Path, out android.WritablePath) {
+ buildNumberFile := ctx.Config().BuildNumberFile(ctx)
ctx.Build(pctx, android.BuildParams{
Rule: injectVersionSymbol,
Description: "inject version symbol",
Input: in,
Output: out,
+ OrderOnly: android.Paths{buildNumberFile},
Args: map[string]string{
- "buildNumberFromFile": proptools.NinjaEscape(ctx.Config().BuildNumberFromFile()),
+ "buildNumberFile": buildNumberFile.String(),
},
})
}
diff --git a/cc/pgo.go b/cc/pgo.go
index 8eb3400..d5c4b87 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -256,6 +256,12 @@
}
}
+ // PGO profile use is not feasible for a Clang coverage build because
+ // -fprofile-use and -fprofile-instr-generate are incompatible.
+ if ctx.DeviceConfig().ClangCoverageEnabled() {
+ return
+ }
+
if !ctx.Config().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") &&
proptools.BoolDefault(pgo.Properties.Pgo.Enable_profile_use, true) {
if profileFile := pgo.Properties.getPgoProfileFile(ctx); profileFile.Valid() {
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index b0cf489..2c18ac3 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -87,15 +87,16 @@
func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
+
+ p.libraryDecorator.exportIncludes(ctx)
+ p.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
+ p.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
+ p.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
+ p.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
+ p.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
+
// TODO(ccross): verify shared library dependencies
if len(p.properties.Srcs) > 0 {
- p.libraryDecorator.exportIncludes(ctx)
- p.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
- p.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
- p.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
- p.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
- p.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
-
builderFlags := flagsToBuilderFlags(flags)
in := p.Prebuilt.SingleSourcePath(ctx)
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 93c4b41..6e809bf 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -179,6 +179,7 @@
SanitizerEnabled bool `blueprint:"mutated"`
SanitizeDep bool `blueprint:"mutated"`
MinimalRuntimeDep bool `blueprint:"mutated"`
+ BuiltinsDep bool `blueprint:"mutated"`
UbsanRuntimeDep bool `blueprint:"mutated"`
InSanitizerDir bool `blueprint:"mutated"`
Sanitizers []string `blueprint:"mutated"`
@@ -334,8 +335,8 @@
s.Diag.Cfi = nil
}
- // Disable sanitizers that depend on the UBSan runtime for host builds.
- if ctx.Host() {
+ // Disable sanitizers that depend on the UBSan runtime for windows/darwin builds.
+ if !ctx.Os().Linux() {
s.Cfi = nil
s.Diag.Cfi = nil
s.Misc_undefined = nil
@@ -350,6 +351,12 @@
s.Diag.Cfi = nil
}
+ // Also disable CFI if building against snapshot.
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ if ctx.useVndk() && vndkVersion != "current" && vndkVersion != "" {
+ s.Cfi = nil
+ }
+
// HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
// Keep libc instrumented so that ramdisk / recovery can run hwasan-instrumented code if necessary.
if (ctx.inRamdisk() || ctx.inRecovery()) && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
@@ -433,12 +440,19 @@
func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
minimalRuntimeLib := config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(ctx.toolchain()) + ".a"
minimalRuntimePath := "${config.ClangAsanLibDir}/" + minimalRuntimeLib
+ builtinsRuntimeLib := config.BuiltinsRuntimeLibrary(ctx.toolchain()) + ".a"
+ builtinsRuntimePath := "${config.ClangAsanLibDir}/" + builtinsRuntimeLib
- if ctx.Device() && sanitize.Properties.MinimalRuntimeDep {
+ if sanitize.Properties.MinimalRuntimeDep {
flags.Local.LdFlags = append(flags.Local.LdFlags,
minimalRuntimePath,
"-Wl,--exclude-libs,"+minimalRuntimeLib)
}
+
+ if sanitize.Properties.BuiltinsDep {
+ flags.libFlags = append([]string{builtinsRuntimePath}, flags.libFlags...)
+ }
+
if !sanitize.Properties.SanitizerEnabled && !sanitize.Properties.UbsanRuntimeDep {
return flags
}
@@ -541,11 +555,19 @@
// there will always be undefined symbols in intermediate libraries.
_, flags.Global.LdFlags = removeFromList("-Wl,--no-undefined", flags.Global.LdFlags)
flags.Local.LdFlags = append(flags.Local.LdFlags, sanitizeArg)
- } else {
- if enableMinimalRuntime(sanitize) {
- flags.Local.CFlags = append(flags.Local.CFlags, strings.Join(minimalRuntimeFlags, " "))
- flags.libFlags = append([]string{minimalRuntimePath}, flags.libFlags...)
- flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib)
+
+ // non-Bionic toolchain prebuilts are missing UBSan's vptr and function sanitizers
+ if !ctx.toolchain().Bionic() {
+ flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=vptr,function")
+ }
+ }
+
+ if enableMinimalRuntime(sanitize) {
+ flags.Local.CFlags = append(flags.Local.CFlags, strings.Join(minimalRuntimeFlags, " "))
+ flags.libFlags = append([]string{minimalRuntimePath}, flags.libFlags...)
+ flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib)
+ if !ctx.toolchain().Bionic() {
+ flags.libFlags = append([]string{builtinsRuntimePath}, flags.libFlags...)
}
}
@@ -587,18 +609,18 @@
return flags
}
-func (sanitize *sanitize) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+func (sanitize *sanitize) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
// Add a suffix for cfi/hwasan/scs-enabled static/header libraries to allow surfacing
// both the sanitized and non-sanitized variants to make without a name conflict.
- if ret.Class == "STATIC_LIBRARIES" || ret.Class == "HEADER_LIBRARIES" {
+ if entries.Class == "STATIC_LIBRARIES" || entries.Class == "HEADER_LIBRARIES" {
if Bool(sanitize.Properties.Sanitize.Cfi) {
- ret.SubName += ".cfi"
+ entries.SubName += ".cfi"
}
if Bool(sanitize.Properties.Sanitize.Hwaddress) {
- ret.SubName += ".hwasan"
+ entries.SubName += ".hwasan"
}
if Bool(sanitize.Properties.Sanitize.Scs) {
- ret.SubName += ".scs"
+ entries.SubName += ".scs"
}
}
}
@@ -739,13 +761,16 @@
return false
}
- if d, ok := child.(*Module); ok && d.static() && d.sanitize != nil {
+ d, ok := child.(*Module)
+ if !ok || !d.static() {
+ return false
+ }
+ if d.sanitize != nil {
if enableMinimalRuntime(d.sanitize) {
// If a static dependency is built with the minimal runtime,
// make sure we include the ubsan minimal runtime.
c.sanitize.Properties.MinimalRuntimeDep = true
- } else if Bool(d.sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
- len(d.sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0 {
+ } else if enableUbsanRuntime(d.sanitize) {
// If a static dependency runs with full ubsan diagnostics,
// make sure we include the ubsan runtime.
c.sanitize.Properties.UbsanRuntimeDep = true
@@ -757,10 +782,23 @@
return false
}
+ if c.Os() == android.Linux {
+ c.sanitize.Properties.BuiltinsDep = true
+ }
+
return true
- } else {
- return false
}
+
+ if p, ok := d.linker.(*vendorSnapshotLibraryDecorator); ok {
+ if Bool(p.properties.Sanitize_minimal_dep) {
+ c.sanitize.Properties.MinimalRuntimeDep = true
+ }
+ if Bool(p.properties.Sanitize_ubsan_dep) {
+ c.sanitize.Properties.UbsanRuntimeDep = true
+ }
+ }
+
+ return false
})
}
}
@@ -884,11 +922,14 @@
runtimeLibrary = config.ScudoRuntimeLibrary(toolchain)
}
} else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep ||
- Bool(c.sanitize.Properties.Sanitize.Fuzzer) {
+ Bool(c.sanitize.Properties.Sanitize.Fuzzer) ||
+ Bool(c.sanitize.Properties.Sanitize.Undefined) ||
+ Bool(c.sanitize.Properties.Sanitize.All_undefined) {
runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
}
- if mctx.Device() && runtimeLibrary != "" {
+ if runtimeLibrary != "" && (toolchain.Bionic() || c.sanitize.Properties.UbsanRuntimeDep) {
+ // UBSan is supported on non-bionic linux host builds as well
if isLlndkLibrary(runtimeLibrary, mctx.Config()) && !c.static() && c.UseVndk() {
runtimeLibrary = runtimeLibrary + llndkLibrarySuffix
}
@@ -901,12 +942,31 @@
// Note that by adding dependency with {static|shared}DepTag, the lib is
// added to libFlags and LOCAL_SHARED_LIBRARIES by cc.Module
if c.staticBinary() {
+ deps := append(extraStaticDeps, runtimeLibrary)
+ // If we're using snapshots and in vendor, redirect to snapshot whenever possible
+ if c.VndkVersion() == mctx.DeviceConfig().VndkVersion() {
+ snapshots := vendorSnapshotStaticLibs(mctx.Config())
+ for idx, dep := range deps {
+ if lib, ok := snapshots.get(dep, mctx.Arch().ArchType); ok {
+ deps[idx] = lib
+ }
+ }
+ }
+
// static executable gets static runtime libs
mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{
{Mutator: "link", Variation: "static"},
c.ImageVariation(),
- }...), StaticDepTag, append([]string{runtimeLibrary}, extraStaticDeps...)...)
+ }...), StaticDepTag, deps...)
} else if !c.static() && !c.header() {
+ // If we're using snapshots and in vendor, redirect to snapshot whenever possible
+ if c.VndkVersion() == mctx.DeviceConfig().VndkVersion() {
+ snapshots := vendorSnapshotSharedLibs(mctx.Config())
+ if lib, ok := snapshots.get(runtimeLibrary, mctx.Arch().ArchType); ok {
+ runtimeLibrary = lib
+ }
+ }
+
// dynamic executable and shared libs get shared runtime libs
mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{
{Mutator: "link", Variation: "shared"},
@@ -1042,16 +1102,28 @@
if !Bool(sanitize.Properties.Sanitize.Address) &&
!Bool(sanitize.Properties.Sanitize.Hwaddress) &&
!Bool(sanitize.Properties.Sanitize.Fuzzer) &&
+
(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
- len(sanitize.Properties.Sanitize.Misc_undefined) > 0) &&
+ len(sanitize.Properties.Sanitize.Misc_undefined) > 0 ||
+ Bool(sanitize.Properties.Sanitize.Undefined) ||
+ Bool(sanitize.Properties.Sanitize.All_undefined)) &&
+
!(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
Bool(sanitize.Properties.Sanitize.Diag.Cfi) ||
+ Bool(sanitize.Properties.Sanitize.Diag.Undefined) ||
len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0) {
+
return true
}
return false
}
+func enableUbsanRuntime(sanitize *sanitize) bool {
+ return Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
+ Bool(sanitize.Properties.Sanitize.Diag.Undefined) ||
+ len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0
+}
+
func cfiMakeVarsProvider(ctx android.MakeVarsContext) {
cfiStaticLibs := cfiStaticLibs(ctx.Config())
sort.Strings(*cfiStaticLibs)
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
new file mode 100644
index 0000000..73388ce
--- /dev/null
+++ b/cc/snapshot_utils.go
@@ -0,0 +1,142 @@
+// Copyright 2020 The Android Open Source Project
+//
+// 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 cc
+
+import (
+ "strings"
+
+ "android/soong/android"
+)
+
+var (
+ headerExts = []string{".h", ".hh", ".hpp", ".hxx", ".h++", ".inl", ".inc", ".ipp", ".h.generic"}
+)
+
+type snapshotLibraryInterface interface {
+ exportedFlagsProducer
+ libraryInterface
+}
+
+var _ snapshotLibraryInterface = (*prebuiltLibraryLinker)(nil)
+var _ snapshotLibraryInterface = (*libraryDecorator)(nil)
+
+type snapshotMap struct {
+ snapshots map[string]string
+}
+
+func newSnapshotMap() *snapshotMap {
+ return &snapshotMap{
+ snapshots: make(map[string]string),
+ }
+}
+
+func snapshotMapKey(name string, arch android.ArchType) string {
+ return name + ":" + arch.String()
+}
+
+// Adds a snapshot name for given module name and architecture.
+// e.g. add("libbase", X86, "libbase.vndk.29.x86")
+func (s *snapshotMap) add(name string, arch android.ArchType, snapshot string) {
+ s.snapshots[snapshotMapKey(name, arch)] = snapshot
+}
+
+// Returns snapshot name for given module name and architecture, if found.
+// e.g. get("libcutils", X86) => "libcutils.vndk.29.x86", true
+func (s *snapshotMap) get(name string, arch android.ArchType) (snapshot string, found bool) {
+ snapshot, found = s.snapshots[snapshotMapKey(name, arch)]
+ return snapshot, found
+}
+
+func exportedHeaders(ctx android.SingletonContext, l exportedFlagsProducer) android.Paths {
+ var ret android.Paths
+
+ // Headers in the source tree should be globbed. On the contrast, generated headers
+ // can't be globbed, and they should be manually collected.
+ // So, we first filter out intermediate directories (which contains generated headers)
+ // from exported directories, and then glob headers under remaining directories.
+ for _, path := range append(l.exportedDirs(), l.exportedSystemDirs()...) {
+ dir := path.String()
+ // Skip if dir is for generated headers
+ if strings.HasPrefix(dir, android.PathForOutput(ctx).String()) {
+ continue
+ }
+ exts := headerExts
+ // Glob all files under this special directory, because of C++ headers.
+ if strings.HasPrefix(dir, "external/libcxx/include") {
+ exts = []string{""}
+ }
+ for _, ext := range exts {
+ glob, err := ctx.GlobWithDeps(dir+"/**/*"+ext, nil)
+ if err != nil {
+ ctx.Errorf("%#v\n", err)
+ return nil
+ }
+ for _, header := range glob {
+ if strings.HasSuffix(header, "/") {
+ continue
+ }
+ ret = append(ret, android.PathForSource(ctx, header))
+ }
+ }
+ }
+
+ // Collect generated headers
+ for _, header := range append(l.exportedGeneratedHeaders(), l.exportedDeps()...) {
+ // TODO(b/148123511): remove exportedDeps after cleaning up genrule
+ if strings.HasSuffix(header.Base(), "-phony") {
+ continue
+ }
+ ret = append(ret, header)
+ }
+
+ return ret
+}
+
+func copyFile(ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
+ outPath := android.PathForOutput(ctx, out)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: path,
+ Output: outPath,
+ Description: "Cp " + out,
+ Args: map[string]string{
+ "cpFlags": "-f -L",
+ },
+ })
+ return outPath
+}
+
+func combineNotices(ctx android.SingletonContext, paths android.Paths, out string) android.OutputPath {
+ outPath := android.PathForOutput(ctx, out)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cat,
+ Inputs: paths,
+ Output: outPath,
+ Description: "combine notices for " + out,
+ })
+ return outPath
+}
+
+func writeStringToFile(ctx android.SingletonContext, content, out string) android.OutputPath {
+ outPath := android.PathForOutput(ctx, out)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.WriteFile,
+ Output: outPath,
+ Description: "WriteFile " + out,
+ Args: map[string]string{
+ "content": content,
+ },
+ })
+ return outPath
+}
diff --git a/cc/stl.go b/cc/stl.go
index af015f9..eda8a4f 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -151,6 +151,14 @@
return version < 21
}
+func staticUnwinder(ctx android.BaseModuleContext) string {
+ if ctx.Arch().ArchType == android.Arm {
+ return "libunwind_llvm"
+ } else {
+ return "libgcc_stripped"
+ }
+}
+
func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
switch stl.Properties.SelectedStl {
case "libstdc++":
@@ -172,16 +180,16 @@
}
if ctx.toolchain().Bionic() {
if ctx.staticBinary() {
- deps.StaticLibs = append(deps.StaticLibs, "libm", "libc")
- if ctx.Arch().ArchType == android.Arm {
- deps.StaticLibs = append(deps.StaticLibs, "libunwind_llvm")
- } else {
- deps.StaticLibs = append(deps.StaticLibs, "libgcc_stripped")
- }
+ deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", staticUnwinder(ctx))
+ } else {
+ deps.StaticUnwinderIfLegacy = true
}
}
case "":
// None or error.
+ if ctx.toolchain().Bionic() && ctx.Module().Name() == "libc++" {
+ deps.StaticUnwinderIfLegacy = true
+ }
case "ndk_system":
// TODO: Make a system STL prebuilt for the NDK.
// The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have
diff --git a/cc/test.go b/cc/test.go
index 05e6fe5..1085d3a 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -49,7 +49,7 @@
// list of files or filegroup modules that provide data that should be installed alongside
// the test
- Data []string `android:"path"`
+ Data []string `android:"path,arch_variant"`
// list of compatibility suites (for example "cts", "vts") that the module should be
// installed into.
diff --git a/cc/testing.go b/cc/testing.go
index ba8ed95..a22763a 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -25,10 +25,13 @@
RegisterCCBuildComponents(ctx)
RegisterBinaryBuildComponents(ctx)
RegisterLibraryBuildComponents(ctx)
+ RegisterLibraryHeadersBuildComponents(ctx)
ctx.RegisterModuleType("toolchain_library", ToolchainLibraryFactory)
ctx.RegisterModuleType("llndk_library", LlndkLibraryFactory)
ctx.RegisterModuleType("cc_object", ObjectFactory)
+ ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
+ ctx.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory)
}
func GatherRequiredDepsForTest(os android.OsType) string {
@@ -37,6 +40,7 @@
name: "libatomic",
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
src: "",
}
@@ -51,6 +55,7 @@
name: "libclang_rt.builtins-arm-android",
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
src: "",
}
@@ -58,6 +63,7 @@
name: "libclang_rt.builtins-aarch64-android",
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
src: "",
}
@@ -65,6 +71,7 @@
name: "libclang_rt.builtins-i686-android",
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
src: "",
}
@@ -72,6 +79,7 @@
name: "libclang_rt.builtins-x86_64-android",
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
src: "",
}
@@ -115,6 +123,7 @@
name: "libclang_rt.ubsan_standalone-aarch64-android",
vendor_available: true,
recovery_available: true,
+ system_shared_libs: [],
srcs: [""],
}
@@ -139,6 +148,9 @@
stl: "none",
system_shared_libs: [],
recovery_available: true,
+ stubs: {
+ versions: ["27", "28", "29"],
+ },
}
llndk_library {
name: "libc",
@@ -151,6 +163,13 @@
stl: "none",
system_shared_libs: [],
recovery_available: true,
+ stubs: {
+ versions: ["27", "28", "29"],
+ },
+ apex_available: [
+ "//apex_available:platform",
+ "myapex"
+ ],
}
llndk_library {
name: "libm",
@@ -163,6 +182,13 @@
stl: "none",
system_shared_libs: [],
recovery_available: true,
+ stubs: {
+ versions: ["27", "28", "29"],
+ },
+ apex_available: [
+ "//apex_available:platform",
+ "myapex"
+ ],
}
llndk_library {
name: "libdl",
@@ -188,6 +214,7 @@
stl: "none",
vendor_available: true,
recovery_available: true,
+ host_supported: true,
}
cc_library {
name: "libc++",
@@ -197,10 +224,15 @@
stl: "none",
vendor_available: true,
recovery_available: true,
+ host_supported: true,
vndk: {
enabled: true,
support_system_process: true,
},
+ apex_available: [
+ "//apex_available:platform",
+ "myapex"
+ ],
}
cc_library {
name: "libc++demangle",
@@ -226,6 +258,7 @@
name: "crtbegin_so",
recovery_available: true,
vendor_available: true,
+ native_bridge_supported: true,
stl: "none",
}
@@ -233,18 +266,23 @@
name: "crtbegin_dynamic",
recovery_available: true,
vendor_available: true,
+ native_bridge_supported: true,
+ stl: "none",
}
cc_object {
name: "crtbegin_static",
recovery_available: true,
vendor_available: true,
+ native_bridge_supported: true,
+ stl: "none",
}
cc_object {
name: "crtend_so",
recovery_available: true,
vendor_available: true,
+ native_bridge_supported: true,
stl: "none",
}
@@ -252,12 +290,57 @@
name: "crtend_android",
recovery_available: true,
vendor_available: true,
+ native_bridge_supported: true,
+ stl: "none",
}
cc_library {
name: "libprotobuf-cpp-lite",
}
- `
+
+ cc_library {
+ name: "ndk_libunwind",
+ sdk_version: "current",
+ stl: "none",
+ system_shared_libs: [],
+ }
+
+ cc_library {
+ name: "libc.ndk.current",
+ sdk_version: "current",
+ stl: "none",
+ system_shared_libs: [],
+ }
+
+ cc_library {
+ name: "libm.ndk.current",
+ sdk_version: "current",
+ stl: "none",
+ system_shared_libs: [],
+ }
+
+ cc_library {
+ name: "libdl.ndk.current",
+ sdk_version: "current",
+ stl: "none",
+ system_shared_libs: [],
+ }
+
+ ndk_prebuilt_object {
+ name: "ndk_crtbegin_so.27",
+ sdk_version: "27",
+ }
+
+ ndk_prebuilt_object {
+ name: "ndk_crtend_so.27",
+ sdk_version: "27",
+ }
+
+ ndk_prebuilt_shared_stl {
+ name: "ndk_libc++_shared",
+ }
+ `
+
if os == android.Fuchsia {
ret += `
cc_library {
@@ -273,6 +356,18 @@
return ret
}
+func GatherRequiredFilesForTest(fs map[string][]byte) {
+ fs["prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so"] = nil
+ fs["prebuilts/ndk/current/platforms/android-27/arch-arm/usr/lib/crtbegin_so.o"] = nil
+ fs["prebuilts/ndk/current/platforms/android-27/arch-arm/usr/lib/crtend_so.o"] = nil
+ fs["prebuilts/ndk/current/platforms/android-27/arch-arm64/usr/lib/crtbegin_so.o"] = nil
+ fs["prebuilts/ndk/current/platforms/android-27/arch-arm64/usr/lib/crtend_so.o"] = nil
+ fs["prebuilts/ndk/current/platforms/android-27/arch-x86/usr/lib/crtbegin_so.o"] = nil
+ fs["prebuilts/ndk/current/platforms/android-27/arch-x86/usr/lib/crtend_so.o"] = nil
+ fs["prebuilts/ndk/current/platforms/android-27/arch-x86_64/usr/lib64/crtbegin_so.o"] = nil
+ fs["prebuilts/ndk/current/platforms/android-27/arch-x86_64/usr/lib64/crtend_so.o"] = nil
+}
+
func TestConfig(buildDir string, os android.OsType, env map[string]string,
bp string, fs map[string][]byte) android.Config {
@@ -293,6 +388,8 @@
"liba.so": nil,
}
+ GatherRequiredFilesForTest(mockFS)
+
for k, v := range fs {
mockFS[k] = v
}
@@ -320,6 +417,7 @@
RegisterRequiredBuildComponentsForTest(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
+ ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
return ctx
}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
new file mode 100644
index 0000000..20762a8
--- /dev/null
+++ b/cc/vendor_snapshot.go
@@ -0,0 +1,842 @@
+// Copyright 2020 The Android Open Source Project
+//
+// 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 cc
+
+import (
+ "encoding/json"
+ "path/filepath"
+ "sort"
+ "strings"
+ "sync"
+
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+)
+
+const (
+ vendorSnapshotHeaderSuffix = ".vendor_header."
+ vendorSnapshotSharedSuffix = ".vendor_shared."
+ vendorSnapshotStaticSuffix = ".vendor_static."
+ vendorSnapshotBinarySuffix = ".vendor_binary."
+)
+
+var (
+ vendorSnapshotsLock sync.Mutex
+ vendorSuffixModulesKey = android.NewOnceKey("vendorSuffixModules")
+ vendorSnapshotHeaderLibsKey = android.NewOnceKey("vendorSnapshotHeaderLibs")
+ vendorSnapshotStaticLibsKey = android.NewOnceKey("vendorSnapshotStaticLibs")
+ vendorSnapshotSharedLibsKey = android.NewOnceKey("vendorSnapshotSharedLibs")
+ vendorSnapshotBinariesKey = android.NewOnceKey("vendorSnapshotBinaries")
+)
+
+// vendor snapshot maps hold names of vendor snapshot modules per arch
+func vendorSuffixModules(config android.Config) map[string]bool {
+ return config.Once(vendorSuffixModulesKey, func() interface{} {
+ return make(map[string]bool)
+ }).(map[string]bool)
+}
+
+func vendorSnapshotHeaderLibs(config android.Config) *snapshotMap {
+ return config.Once(vendorSnapshotHeaderLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func vendorSnapshotSharedLibs(config android.Config) *snapshotMap {
+ return config.Once(vendorSnapshotSharedLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func vendorSnapshotStaticLibs(config android.Config) *snapshotMap {
+ return config.Once(vendorSnapshotStaticLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func vendorSnapshotBinaries(config android.Config) *snapshotMap {
+ return config.Once(vendorSnapshotBinariesKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+type vendorSnapshotLibraryProperties struct {
+ // snapshot version.
+ Version string
+
+ // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
+ Target_arch string
+
+ // Prebuilt file for each arch.
+ Src *string `android:"arch_variant"`
+
+ // list of flags that will be used for any module that links against this module.
+ Export_flags []string `android:"arch_variant"`
+
+ // Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined symbols,
+ // etc).
+ Check_elf_files *bool
+
+ // Whether this prebuilt needs to depend on sanitize ubsan runtime or not.
+ Sanitize_ubsan_dep *bool `android:"arch_variant"`
+
+ // Whether this prebuilt needs to depend on sanitize minimal runtime or not.
+ Sanitize_minimal_dep *bool `android:"arch_variant"`
+}
+
+type vendorSnapshotLibraryDecorator struct {
+ *libraryDecorator
+ properties vendorSnapshotLibraryProperties
+ androidMkVendorSuffix bool
+}
+
+func (p *vendorSnapshotLibraryDecorator) Name(name string) string {
+ return name + p.NameSuffix()
+}
+
+func (p *vendorSnapshotLibraryDecorator) NameSuffix() string {
+ versionSuffix := p.version()
+ if p.arch() != "" {
+ versionSuffix += "." + p.arch()
+ }
+
+ var linkageSuffix string
+ if p.buildShared() {
+ linkageSuffix = vendorSnapshotSharedSuffix
+ } else if p.buildStatic() {
+ linkageSuffix = vendorSnapshotStaticSuffix
+ } else {
+ linkageSuffix = vendorSnapshotHeaderSuffix
+ }
+
+ return linkageSuffix + versionSuffix
+}
+
+func (p *vendorSnapshotLibraryDecorator) version() string {
+ return p.properties.Version
+}
+
+func (p *vendorSnapshotLibraryDecorator) arch() string {
+ return p.properties.Target_arch
+}
+
+func (p *vendorSnapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
+ p.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), p.NameSuffix())
+ return p.libraryDecorator.linkerFlags(ctx, flags)
+}
+
+func (p *vendorSnapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
+ arches := config.Arches()
+ if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
+ return false
+ }
+ if !p.header() && p.properties.Src == nil {
+ return false
+ }
+ return true
+}
+
+func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext,
+ flags Flags, deps PathDeps, objs Objects) android.Path {
+ m := ctx.Module().(*Module)
+ p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
+
+ if p.header() {
+ return p.libraryDecorator.link(ctx, flags, deps, objs)
+ }
+
+ if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ return nil
+ }
+
+ p.libraryDecorator.exportIncludes(ctx)
+ p.libraryDecorator.reexportFlags(p.properties.Export_flags...)
+
+ in := android.PathForModuleSrc(ctx, *p.properties.Src)
+ p.unstrippedOutputFile = in
+
+ if p.shared() {
+ libName := in.Base()
+ builderFlags := flagsToBuilderFlags(flags)
+
+ // Optimize out relinking against shared libraries whose interface hasn't changed by
+ // depending on a table of contents file instead of the library itself.
+ tocFile := android.PathForModuleOut(ctx, libName+".toc")
+ p.tocFile = android.OptionalPathForPath(tocFile)
+ TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
+ }
+
+ return in
+}
+
+func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool {
+ return false
+}
+
+func (p *vendorSnapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) {
+ if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
+ p.baseInstaller.install(ctx, file)
+ }
+}
+
+type vendorSnapshotInterface interface {
+ version() string
+}
+
+func vendorSnapshotLoadHook(ctx android.LoadHookContext, p vendorSnapshotInterface) {
+ if p.version() != ctx.DeviceConfig().VndkVersion() {
+ ctx.Module().Disable()
+ return
+ }
+}
+
+func vendorSnapshotLibrary() (*Module, *vendorSnapshotLibraryDecorator) {
+ module, library := NewLibrary(android.DeviceSupported)
+
+ module.stl = nil
+ module.sanitize = nil
+ library.StripProperties.Strip.None = BoolPtr(true)
+
+ prebuilt := &vendorSnapshotLibraryDecorator{
+ libraryDecorator: library,
+ }
+
+ prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true)
+ prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true)
+
+ // Prevent default system libs (libc, libm, and libdl) from being linked
+ if prebuilt.baseLinker.Properties.System_shared_libs == nil {
+ prebuilt.baseLinker.Properties.System_shared_libs = []string{}
+ }
+
+ module.compiler = nil
+ module.linker = prebuilt
+ module.installer = prebuilt
+
+ module.AddProperties(
+ &prebuilt.properties,
+ )
+
+ return module, prebuilt
+}
+
+func VendorSnapshotSharedFactory() android.Module {
+ module, prebuilt := vendorSnapshotLibrary()
+ prebuilt.libraryDecorator.BuildOnlyShared()
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ vendorSnapshotLoadHook(ctx, prebuilt)
+ })
+ return module.Init()
+}
+
+func VendorSnapshotStaticFactory() android.Module {
+ module, prebuilt := vendorSnapshotLibrary()
+ prebuilt.libraryDecorator.BuildOnlyStatic()
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ vendorSnapshotLoadHook(ctx, prebuilt)
+ })
+ return module.Init()
+}
+
+func VendorSnapshotHeaderFactory() android.Module {
+ module, prebuilt := vendorSnapshotLibrary()
+ prebuilt.libraryDecorator.HeaderOnly()
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ vendorSnapshotLoadHook(ctx, prebuilt)
+ })
+ return module.Init()
+}
+
+type vendorSnapshotBinaryProperties struct {
+ // snapshot version.
+ Version string
+
+ // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
+ Target_arch string
+
+ // Prebuilt file for each arch.
+ Src *string `android:"arch_variant"`
+}
+
+type vendorSnapshotBinaryDecorator struct {
+ *binaryDecorator
+ properties vendorSnapshotBinaryProperties
+ androidMkVendorSuffix bool
+}
+
+func (p *vendorSnapshotBinaryDecorator) Name(name string) string {
+ return name + p.NameSuffix()
+}
+
+func (p *vendorSnapshotBinaryDecorator) NameSuffix() string {
+ versionSuffix := p.version()
+ if p.arch() != "" {
+ versionSuffix += "." + p.arch()
+ }
+ return vendorSnapshotBinarySuffix + versionSuffix
+}
+
+func (p *vendorSnapshotBinaryDecorator) version() string {
+ return p.properties.Version
+}
+
+func (p *vendorSnapshotBinaryDecorator) arch() string {
+ return p.properties.Target_arch
+}
+
+func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
+ if config.DeviceArch() != p.arch() {
+ return false
+ }
+ if p.properties.Src == nil {
+ return false
+ }
+ return true
+}
+
+func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext,
+ flags Flags, deps PathDeps, objs Objects) android.Path {
+ if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ return nil
+ }
+
+ in := android.PathForModuleSrc(ctx, *p.properties.Src)
+ builderFlags := flagsToBuilderFlags(flags)
+ p.unstrippedOutputFile = in
+ binName := in.Base()
+ if p.needsStrip(ctx) {
+ stripped := android.PathForModuleOut(ctx, "stripped", binName)
+ p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags)
+ in = stripped
+ }
+
+ m := ctx.Module().(*Module)
+ p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
+
+ // use cpExecutable to make it executable
+ outputFile := android.PathForModuleOut(ctx, binName)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpExecutable,
+ Description: "prebuilt",
+ Output: outputFile,
+ Input: in,
+ })
+
+ return outputFile
+}
+
+func VendorSnapshotBinaryFactory() android.Module {
+ module, binary := NewBinary(android.DeviceSupported)
+ binary.baseLinker.Properties.No_libcrt = BoolPtr(true)
+ binary.baseLinker.Properties.Nocrt = BoolPtr(true)
+
+ // Prevent default system libs (libc, libm, and libdl) from being linked
+ if binary.baseLinker.Properties.System_shared_libs == nil {
+ binary.baseLinker.Properties.System_shared_libs = []string{}
+ }
+
+ prebuilt := &vendorSnapshotBinaryDecorator{
+ binaryDecorator: binary,
+ }
+
+ module.compiler = nil
+ module.sanitize = nil
+ module.stl = nil
+ module.linker = prebuilt
+
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ vendorSnapshotLoadHook(ctx, prebuilt)
+ })
+
+ module.AddProperties(&prebuilt.properties)
+ return module.Init()
+}
+
+func init() {
+ android.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
+ android.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
+ android.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
+ android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
+ android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
+}
+
+func VendorSnapshotSingleton() android.Singleton {
+ return &vendorSnapshotSingleton{}
+}
+
+type vendorSnapshotSingleton struct {
+ vendorSnapshotZipFile android.OptionalPath
+}
+
+var (
+ // Modules under following directories are ignored. They are OEM's and vendor's
+ // proprietary modules(device/, vendor/, and hardware/).
+ // TODO(b/65377115): Clean up these with more maintainable way
+ vendorProprietaryDirs = []string{
+ "device",
+ "vendor",
+ "hardware",
+ }
+
+ // Modules under following directories are included as they are in AOSP,
+ // although hardware/ is normally for vendor's own.
+ // TODO(b/65377115): Clean up these with more maintainable way
+ aospDirsUnderProprietary = []string{
+ "hardware/interfaces",
+ "hardware/libhardware",
+ "hardware/libhardware_legacy",
+ "hardware/ril",
+ }
+)
+
+// Determine if a dir under source tree is an SoC-owned proprietary directory, such as
+// device/, vendor/, etc.
+func isVendorProprietaryPath(dir string) bool {
+ for _, p := range vendorProprietaryDirs {
+ if strings.HasPrefix(dir, p) {
+ // filter out AOSP defined directories, e.g. hardware/interfaces/
+ aosp := false
+ for _, p := range aospDirsUnderProprietary {
+ if strings.HasPrefix(dir, p) {
+ aosp = true
+ break
+ }
+ }
+ if !aosp {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+// Determine if a module is going to be included in vendor snapshot or not.
+//
+// Targets of vendor snapshot are "vendor: true" or "vendor_available: true" modules in
+// AOSP. They are not guaranteed to be compatible with older vendor images. (e.g. might
+// depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
+// image and newer system image altogether.
+func isVendorSnapshotModule(ctx android.SingletonContext, m *Module) bool {
+ if !m.Enabled() {
+ return false
+ }
+ // skip proprietary modules, but include all VNDK (static)
+ if isVendorProprietaryPath(ctx.ModuleDir(m)) && !m.IsVndk() {
+ return false
+ }
+ if m.Target().Os.Class != android.Device {
+ return false
+ }
+ if m.Target().NativeBridge == android.NativeBridgeEnabled {
+ return false
+ }
+ // the module must be installed in /vendor
+ if !m.installable() || m.isSnapshotPrebuilt() || !m.inVendor() {
+ return false
+ }
+ // exclude test modules
+ if _, ok := m.linker.(interface{ gtest() bool }); ok {
+ return false
+ }
+ // TODO(b/65377115): add full support for sanitizer
+ if m.sanitize != nil && !m.sanitize.isUnsanitizedVariant() {
+ return false
+ }
+
+ // Libraries
+ if l, ok := m.linker.(snapshotLibraryInterface); ok {
+ if l.static() {
+ return proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
+ }
+ if l.shared() {
+ return !m.IsVndk()
+ }
+ return true
+ }
+
+ // Binaries
+ _, ok := m.linker.(*binaryDecorator)
+ if !ok {
+ if _, ok := m.linker.(*prebuiltBinaryLinker); !ok {
+ return false
+ }
+ }
+ return proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
+}
+
+func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ // BOARD_VNDK_VERSION must be set to 'current' in order to generate a vendor snapshot.
+ if ctx.DeviceConfig().VndkVersion() != "current" {
+ return
+ }
+
+ var snapshotOutputs android.Paths
+
+ /*
+ Vendor snapshot zipped artifacts directory structure:
+ {SNAPSHOT_ARCH}/
+ arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/
+ shared/
+ (.so shared libraries)
+ static/
+ (.a static libraries)
+ header/
+ (header only libraries)
+ binary/
+ (executable binaries)
+ arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
+ shared/
+ (.so shared libraries)
+ static/
+ (.a static libraries)
+ header/
+ (header only libraries)
+ binary/
+ (executable binaries)
+ NOTICE_FILES/
+ (notice files, e.g. libbase.txt)
+ configs/
+ (config files, e.g. init.rc files, vintf_fragments.xml files, etc.)
+ include/
+ (header files of same directory structure with source tree)
+ */
+
+ snapshotDir := "vendor-snapshot"
+ snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
+
+ includeDir := filepath.Join(snapshotArchDir, "include")
+ configsDir := filepath.Join(snapshotArchDir, "configs")
+ noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
+
+ installedNotices := make(map[string]bool)
+ installedConfigs := make(map[string]bool)
+
+ var headers android.Paths
+
+ type vendorSnapshotLibraryInterface interface {
+ exportedFlagsProducer
+ libraryInterface
+ }
+
+ var _ vendorSnapshotLibraryInterface = (*prebuiltLibraryLinker)(nil)
+ var _ vendorSnapshotLibraryInterface = (*libraryDecorator)(nil)
+
+ installSnapshot := func(m *Module) android.Paths {
+ targetArch := "arch-" + m.Target().Arch.ArchType.String()
+ if m.Target().Arch.ArchVariant != "" {
+ targetArch += "-" + m.Target().Arch.ArchVariant
+ }
+
+ var ret android.Paths
+
+ prop := struct {
+ ModuleName string `json:",omitempty"`
+ RelativeInstallPath string `json:",omitempty"`
+
+ // library flags
+ ExportedDirs []string `json:",omitempty"`
+ ExportedSystemDirs []string `json:",omitempty"`
+ ExportedFlags []string `json:",omitempty"`
+ SanitizeMinimalDep bool `json:",omitempty"`
+ SanitizeUbsanDep bool `json:",omitempty"`
+
+ // binary flags
+ Symlinks []string `json:",omitempty"`
+
+ // dependencies
+ SharedLibs []string `json:",omitempty"`
+ RuntimeLibs []string `json:",omitempty"`
+ Required []string `json:",omitempty"`
+
+ // extra config files
+ InitRc []string `json:",omitempty"`
+ VintfFragments []string `json:",omitempty"`
+ }{}
+
+ // Common properties among snapshots.
+ prop.ModuleName = ctx.ModuleName(m)
+ prop.RelativeInstallPath = m.RelativeInstallPath()
+ prop.RuntimeLibs = m.Properties.SnapshotRuntimeLibs
+ prop.Required = m.RequiredModuleNames()
+ for _, path := range m.InitRc() {
+ prop.InitRc = append(prop.InitRc, filepath.Join("configs", path.Base()))
+ }
+ for _, path := range m.VintfFragments() {
+ prop.VintfFragments = append(prop.VintfFragments, filepath.Join("configs", path.Base()))
+ }
+
+ // install config files. ignores any duplicates.
+ for _, path := range append(m.InitRc(), m.VintfFragments()...) {
+ out := filepath.Join(configsDir, path.Base())
+ if !installedConfigs[out] {
+ installedConfigs[out] = true
+ ret = append(ret, copyFile(ctx, path, out))
+ }
+ }
+
+ var propOut string
+
+ if l, ok := m.linker.(vendorSnapshotLibraryInterface); ok {
+ // library flags
+ prop.ExportedFlags = l.exportedFlags()
+ for _, dir := range l.exportedDirs() {
+ prop.ExportedDirs = append(prop.ExportedDirs, filepath.Join("include", dir.String()))
+ }
+ for _, dir := range l.exportedSystemDirs() {
+ prop.ExportedSystemDirs = append(prop.ExportedSystemDirs, filepath.Join("include", dir.String()))
+ }
+ // shared libs dependencies aren't meaningful on static or header libs
+ if l.shared() {
+ prop.SharedLibs = m.Properties.SnapshotSharedLibs
+ }
+ if l.static() && m.sanitize != nil {
+ prop.SanitizeMinimalDep = m.sanitize.Properties.MinimalRuntimeDep || enableMinimalRuntime(m.sanitize)
+ prop.SanitizeUbsanDep = m.sanitize.Properties.UbsanRuntimeDep || enableUbsanRuntime(m.sanitize)
+ }
+
+ var libType string
+ if l.static() {
+ libType = "static"
+ } else if l.shared() {
+ libType = "shared"
+ } else {
+ libType = "header"
+ }
+
+ var stem string
+
+ // install .a or .so
+ if libType != "header" {
+ libPath := m.outputFile.Path()
+ stem = libPath.Base()
+ snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem)
+ ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
+ } else {
+ stem = ctx.ModuleName(m)
+ }
+
+ propOut = filepath.Join(snapshotArchDir, targetArch, libType, stem+".json")
+ } else {
+ // binary flags
+ prop.Symlinks = m.Symlinks()
+ prop.SharedLibs = m.Properties.SnapshotSharedLibs
+
+ // install bin
+ binPath := m.outputFile.Path()
+ snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
+ ret = append(ret, copyFile(ctx, binPath, snapshotBinOut))
+ propOut = snapshotBinOut + ".json"
+ }
+
+ j, err := json.Marshal(prop)
+ if err != nil {
+ ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
+ return nil
+ }
+ ret = append(ret, writeStringToFile(ctx, string(j), propOut))
+
+ return ret
+ }
+
+ ctx.VisitAllModules(func(module android.Module) {
+ m, ok := module.(*Module)
+ if !ok || !isVendorSnapshotModule(ctx, m) {
+ return
+ }
+
+ snapshotOutputs = append(snapshotOutputs, installSnapshot(m)...)
+ if l, ok := m.linker.(vendorSnapshotLibraryInterface); ok {
+ headers = append(headers, exportedHeaders(ctx, l)...)
+ }
+
+ if len(m.NoticeFiles()) > 0 {
+ noticeName := ctx.ModuleName(m) + ".txt"
+ noticeOut := filepath.Join(noticeDir, noticeName)
+ // skip already copied notice file
+ if !installedNotices[noticeOut] {
+ installedNotices[noticeOut] = true
+ snapshotOutputs = append(snapshotOutputs, combineNotices(
+ ctx, m.NoticeFiles(), noticeOut))
+ }
+ }
+ })
+
+ // install all headers after removing duplicates
+ for _, header := range android.FirstUniquePaths(headers) {
+ snapshotOutputs = append(snapshotOutputs, copyFile(
+ ctx, header, filepath.Join(includeDir, header.String())))
+ }
+
+ // All artifacts are ready. Sort them to normalize ninja and then zip.
+ sort.Slice(snapshotOutputs, func(i, j int) bool {
+ return snapshotOutputs[i].String() < snapshotOutputs[j].String()
+ })
+
+ zipPath := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+".zip")
+ zipRule := android.NewRuleBuilder()
+
+ // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr
+ snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+"_list")
+ zipRule.Command().
+ Text("tr").
+ FlagWithArg("-d ", "\\'").
+ FlagWithRspFileInputList("< ", snapshotOutputs).
+ FlagWithOutput("> ", snapshotOutputList)
+
+ zipRule.Temporary(snapshotOutputList)
+
+ zipRule.Command().
+ BuiltTool(ctx, "soong_zip").
+ FlagWithOutput("-o ", zipPath).
+ FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
+ FlagWithInput("-l ", snapshotOutputList)
+
+ zipRule.Build(pctx, ctx, zipPath.String(), "vendor snapshot "+zipPath.String())
+ zipRule.DeleteTemporaryFiles()
+ c.vendorSnapshotZipFile = android.OptionalPathForPath(zipPath)
+}
+
+func (c *vendorSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.Strict("SOONG_VENDOR_SNAPSHOT_ZIP", c.vendorSnapshotZipFile.String())
+}
+
+type snapshotInterface interface {
+ matchesWithDevice(config android.DeviceConfig) bool
+}
+
+var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
+var _ snapshotInterface = (*vendorSnapshotLibraryDecorator)(nil)
+var _ snapshotInterface = (*vendorSnapshotBinaryDecorator)(nil)
+
+// gathers all snapshot modules for vendor, and disable unnecessary snapshots
+// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules
+func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) {
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ // don't need snapshot if current
+ if vndkVersion == "current" || vndkVersion == "" {
+ return
+ }
+
+ module, ok := ctx.Module().(*Module)
+ if !ok || !module.Enabled() || module.VndkVersion() != vndkVersion {
+ return
+ }
+
+ snapshot, ok := module.linker.(snapshotInterface)
+ if !ok {
+ return
+ }
+
+ if !snapshot.matchesWithDevice(ctx.DeviceConfig()) {
+ // Disable unnecessary snapshot module, but do not disable
+ // vndk_prebuilt_shared because they might be packed into vndk APEX
+ if !module.IsVndk() {
+ module.Disable()
+ }
+ return
+ }
+
+ var snapshotMap *snapshotMap
+
+ if lib, ok := module.linker.(libraryInterface); ok {
+ if lib.static() {
+ snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
+ } else if lib.shared() {
+ snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
+ } else {
+ // header
+ snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
+ }
+ } else if _, ok := module.linker.(*vendorSnapshotBinaryDecorator); ok {
+ snapshotMap = vendorSnapshotBinaries(ctx.Config())
+ } else {
+ return
+ }
+
+ vendorSnapshotsLock.Lock()
+ defer vendorSnapshotsLock.Unlock()
+ snapshotMap.add(module.BaseModuleName(), ctx.Arch().ArchType, ctx.ModuleName())
+}
+
+// Disables source modules which have snapshots
+func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
+ if !ctx.Device() {
+ return
+ }
+
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ // don't need snapshot if current
+ if vndkVersion == "current" || vndkVersion == "" {
+ return
+ }
+
+ module, ok := ctx.Module().(*Module)
+ if !ok {
+ return
+ }
+
+ // vendor suffix should be added to snapshots if the source module isn't vendor: true.
+ if !module.SocSpecific() {
+ // But we can't just check SocSpecific() since we already passed the image mutator.
+ // Check ramdisk and recovery to see if we are real "vendor: true" module.
+ ramdisk_available := module.InRamdisk() && !module.OnlyInRamdisk()
+ recovery_available := module.InRecovery() && !module.OnlyInRecovery()
+
+ if !ramdisk_available && !recovery_available {
+ vendorSnapshotsLock.Lock()
+ defer vendorSnapshotsLock.Unlock()
+
+ vendorSuffixModules(ctx.Config())[ctx.ModuleName()] = true
+ }
+ }
+
+ if module.isSnapshotPrebuilt() || module.VndkVersion() != ctx.DeviceConfig().VndkVersion() {
+ // only non-snapshot modules with BOARD_VNDK_VERSION
+ return
+ }
+
+ var snapshotMap *snapshotMap
+
+ if lib, ok := module.linker.(libraryInterface); ok {
+ if lib.static() {
+ snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
+ } else if lib.shared() {
+ snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
+ } else {
+ // header
+ snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
+ }
+ } else if _, ok := module.linker.(*binaryDecorator); ok {
+ snapshotMap = vendorSnapshotBinaries(ctx.Config())
+ } else if _, ok := module.linker.(*prebuiltBinaryLinker); ok {
+ snapshotMap = vendorSnapshotBinaries(ctx.Config())
+ } else {
+ return
+ }
+
+ if _, ok := snapshotMap.get(ctx.ModuleName(), ctx.Arch().ArchType); !ok {
+ // Corresponding snapshot doesn't exist
+ return
+ }
+
+ // Disables source modules if corresponding snapshot exists.
+ if lib, ok := module.linker.(libraryInterface); ok && lib.buildStatic() && lib.buildShared() {
+ // But do not disable because the shared variant depends on the static variant.
+ module.SkipInstall()
+ module.Properties.HideFromMake = true
+ } else {
+ module.Disable()
+ }
+}
diff --git a/cc/vndk.go b/cc/vndk.go
index ab73035..d0492fc 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -229,8 +229,6 @@
vndkUsingCoreVariantLibrariesKey = android.NewOnceKey("vndkUsingCoreVariantLibraries")
vndkMustUseVendorVariantListKey = android.NewOnceKey("vndkMustUseVendorVariantListKey")
vndkLibrariesLock sync.Mutex
-
- headerExts = []string{".h", ".hh", ".hpp", ".hxx", ".h++", ".inl", ".inc", ".ipp", ".h.generic"}
)
func vndkCoreLibraries(config android.Config) map[string]string {
@@ -548,29 +546,10 @@
snapshotDir := "vndk-snapshot"
snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
- targetArchDirMap := make(map[android.ArchType]string)
- for _, target := range ctx.Config().Targets[android.Android] {
- dir := snapshotArchDir
- if ctx.DeviceConfig().BinderBitness() == "32" {
- dir = filepath.Join(dir, "binder32")
- }
- arch := "arch-" + target.Arch.ArchType.String()
- if target.Arch.ArchVariant != "" {
- arch += "-" + target.Arch.ArchVariant
- }
- dir = filepath.Join(dir, arch)
- targetArchDirMap[target.Arch.ArchType] = dir
- }
configsDir := filepath.Join(snapshotArchDir, "configs")
noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
includeDir := filepath.Join(snapshotArchDir, "include")
- // set of include paths exported by VNDK libraries
- exportedIncludes := make(map[string]bool)
-
- // generated header files among exported headers.
- var generatedHeaders android.Paths
-
// set of notice files copied.
noticeBuilt := make(map[string]bool)
@@ -581,67 +560,20 @@
// e.g. moduleNames["libprotobuf-cpp-full-3.9.1.so"] = "libprotobuf-cpp-full"
moduleNames := make(map[string]string)
- installSnapshotFileFromPath := func(path android.Path, out string) android.OutputPath {
- outPath := android.PathForOutput(ctx, out)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Input: path,
- Output: outPath,
- Description: "vndk snapshot " + out,
- Args: map[string]string{
- "cpFlags": "-f -L",
- },
- })
- return outPath
- }
+ var headers android.Paths
- installSnapshotFileFromContent := func(content, out string) android.OutputPath {
- outPath := android.PathForOutput(ctx, out)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Output: outPath,
- Description: "vndk snapshot " + out,
- Args: map[string]string{
- "content": content,
- },
- })
- return outPath
- }
-
- type vndkSnapshotLibraryInterface interface {
- exportedFlagsProducer
- libraryInterface
- }
-
- var _ vndkSnapshotLibraryInterface = (*prebuiltLibraryLinker)(nil)
- var _ vndkSnapshotLibraryInterface = (*libraryDecorator)(nil)
-
- installVndkSnapshotLib := func(m *Module, l vndkSnapshotLibraryInterface, vndkType string) (android.Paths, bool) {
- targetArchDir, ok := targetArchDirMap[m.Target().Arch.ArchType]
- if !ok {
- return nil, false
- }
-
+ installVndkSnapshotLib := func(m *Module, l snapshotLibraryInterface, vndkType string) (android.Paths, bool) {
var ret android.Paths
- libPath := m.outputFile.Path()
- stem := libPath.Base()
- snapshotLibOut := filepath.Join(targetArchDir, "shared", vndkType, stem)
- ret = append(ret, installSnapshotFileFromPath(libPath, snapshotLibOut))
-
- moduleNames[stem] = ctx.ModuleName(m)
- modulePaths[stem] = ctx.ModuleDir(m)
-
- if m.NoticeFile().Valid() {
- noticeName := stem + ".txt"
- // skip already copied notice file
- if _, ok := noticeBuilt[noticeName]; !ok {
- noticeBuilt[noticeName] = true
- ret = append(ret, installSnapshotFileFromPath(
- m.NoticeFile().Path(), filepath.Join(noticeDir, noticeName)))
- }
+ targetArch := "arch-" + m.Target().Arch.ArchType.String()
+ if m.Target().Arch.ArchVariant != "" {
+ targetArch += "-" + m.Target().Arch.ArchVariant
}
+ libPath := m.outputFile.Path()
+ snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "shared", vndkType, libPath.Base())
+ ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
+
if ctx.Config().VndkSnapshotBuildArtifacts() {
prop := struct {
ExportedDirs []string `json:",omitempty"`
@@ -661,19 +593,19 @@
ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
return nil, false
}
- ret = append(ret, installSnapshotFileFromContent(string(j), propOut))
+ ret = append(ret, writeStringToFile(ctx, string(j), propOut))
}
return ret, true
}
- isVndkSnapshotLibrary := func(m *Module) (i vndkSnapshotLibraryInterface, vndkType string, isVndkSnapshotLib bool) {
+ isVndkSnapshotLibrary := func(m *Module) (i snapshotLibraryInterface, vndkType string, isVndkSnapshotLib bool) {
if m.Target().NativeBridge == android.NativeBridgeEnabled {
return nil, "", false
}
- if !m.UseVndk() || !m.installable() || !m.inVendor() {
+ if !m.inVendor() || !m.installable() || m.isSnapshotPrebuilt() {
return nil, "", false
}
- l, ok := m.linker.(vndkSnapshotLibraryInterface)
+ l, ok := m.linker.(snapshotLibraryInterface)
if !ok || !l.shared() {
return nil, "", false
}
@@ -699,75 +631,38 @@
return
}
+ // install .so files for appropriate modules.
+ // Also install .json files if VNDK_SNAPSHOT_BUILD_ARTIFACTS
libs, ok := installVndkSnapshotLib(m, l, vndkType)
if !ok {
return
}
-
snapshotOutputs = append(snapshotOutputs, libs...)
- // We glob headers from include directories inside source tree. So we first gather
- // all include directories inside our source tree. On the contrast, we manually
- // collect generated headers from dependencies as they can't globbed.
- generatedHeaders = append(generatedHeaders, l.exportedGeneratedHeaders()...)
- for _, dir := range append(l.exportedDirs(), l.exportedSystemDirs()...) {
- exportedIncludes[dir.String()] = true
+ // These are for generating module_names.txt and module_paths.txt
+ stem := m.outputFile.Path().Base()
+ moduleNames[stem] = ctx.ModuleName(m)
+ modulePaths[stem] = ctx.ModuleDir(m)
+
+ if len(m.NoticeFiles()) > 0 {
+ noticeName := stem + ".txt"
+ // skip already copied notice file
+ if _, ok := noticeBuilt[noticeName]; !ok {
+ noticeBuilt[noticeName] = true
+ snapshotOutputs = append(snapshotOutputs, combineNotices(
+ ctx, m.NoticeFiles(), filepath.Join(noticeDir, noticeName)))
+ }
+ }
+
+ if ctx.Config().VndkSnapshotBuildArtifacts() {
+ headers = append(headers, exportedHeaders(ctx, l)...)
}
})
- if ctx.Config().VndkSnapshotBuildArtifacts() {
- globbedHeaders := make(map[string]bool)
-
- for _, dir := range android.SortedStringKeys(exportedIncludes) {
- // Skip if dir is for generated headers
- if strings.HasPrefix(dir, android.PathForOutput(ctx).String()) {
- continue
- }
- exts := headerExts
- // Glob all files under this special directory, because of C++ headers.
- if strings.HasPrefix(dir, "external/libcxx/include") {
- exts = []string{""}
- }
- for _, ext := range exts {
- glob, err := ctx.GlobWithDeps(dir+"/**/*"+ext, nil)
- if err != nil {
- ctx.Errorf("%#v\n", err)
- return
- }
- for _, header := range glob {
- if strings.HasSuffix(header, "/") {
- continue
- }
- globbedHeaders[header] = true
- }
- }
- }
-
- for _, header := range android.SortedStringKeys(globbedHeaders) {
- snapshotOutputs = append(snapshotOutputs, installSnapshotFileFromPath(
- android.PathForSource(ctx, header), filepath.Join(includeDir, header)))
- }
-
- isHeader := func(path string) bool {
- for _, ext := range headerExts {
- if strings.HasSuffix(path, ext) {
- return true
- }
- }
- return false
- }
-
- // For generated headers, manually install one by one, rather than glob
- for _, path := range android.PathsToDirectorySortedPaths(android.FirstUniquePaths(generatedHeaders)) {
- header := path.String()
-
- if !isHeader(header) {
- continue
- }
-
- snapshotOutputs = append(snapshotOutputs, installSnapshotFileFromPath(
- path, filepath.Join(includeDir, header)))
- }
+ // install all headers after removing duplicates
+ for _, header := range android.FirstUniquePaths(headers) {
+ snapshotOutputs = append(snapshotOutputs, copyFile(
+ ctx, header, filepath.Join(includeDir, header.String())))
}
// install *.libraries.txt except vndkcorevariant.libraries.txt
@@ -776,7 +671,8 @@
if !ok || !m.Enabled() || m.Name() == vndkUsingCoreVariantLibrariesTxt {
return
}
- snapshotOutputs = append(snapshotOutputs, installSnapshotFileFromPath(m.OutputFile(), filepath.Join(configsDir, m.Name())))
+ snapshotOutputs = append(snapshotOutputs, copyFile(
+ ctx, m.OutputFile(), filepath.Join(configsDir, m.Name())))
})
/*
@@ -796,7 +692,7 @@
txtBuilder.WriteString(" ")
txtBuilder.WriteString(m[k])
}
- return installSnapshotFileFromContent(txtBuilder.String(), path)
+ return writeStringToFile(ctx, txtBuilder.String(), path)
}
/*
@@ -827,14 +723,13 @@
zipPath := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+".zip")
zipRule := android.NewRuleBuilder()
- // If output files are too many, soong_zip command can exceed ARG_MAX.
- // So first dump file lists into a single list file, and then feed it to Soong
+ // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with xargs
snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+"_list")
zipRule.Command().
- Text("( xargs").
- FlagWithRspFileInputList("-n1 echo < ", snapshotOutputs).
- FlagWithOutput("| tr -d \\' > ", snapshotOutputList).
- Text(")")
+ Text("tr").
+ FlagWithArg("-d ", "\\'").
+ FlagWithRspFileInputList("< ", snapshotOutputs).
+ FlagWithOutput("> ", snapshotOutputList)
zipRule.Temporary(snapshotOutputList)
@@ -845,6 +740,7 @@
FlagWithInput("-l ", snapshotOutputList)
zipRule.Build(pctx, ctx, zipPath.String(), "vndk snapshot "+zipPath.String())
+ zipRule.DeleteTemporaryFiles()
c.vndkSnapshotZipFile = android.OptionalPathForPath(zipPath)
}
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index c941c46..53b5181 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -31,7 +31,8 @@
//
// vndk_prebuilt_shared {
// name: "libfoo",
-// version: "27.1.0",
+// version: "27",
+// target_arch: "arm64",
// vendor_available: true,
// vndk: {
// enabled: true,
@@ -61,10 +62,6 @@
// Prebuilt files for each arch.
Srcs []string `android:"arch_variant"`
- // list of directories relative to the Blueprints file that will be added to the include
- // path (using -isystem) for any module that links against this module.
- Export_system_include_dirs []string `android:"arch_variant"`
-
// list of flags that will be used for any module that links against this module.
Export_flags []string `android:"arch_variant"`
@@ -75,7 +72,8 @@
type vndkPrebuiltLibraryDecorator struct {
*libraryDecorator
- properties vndkPrebuiltProperties
+ properties vndkPrebuiltProperties
+ androidMkSuffix string
}
func (p *vndkPrebuiltLibraryDecorator) Name(name string) string {
@@ -137,11 +135,33 @@
if len(p.properties.Srcs) > 0 && p.shared() {
p.libraryDecorator.exportIncludes(ctx)
- p.libraryDecorator.reexportSystemDirs(
- android.PathsForModuleSrc(ctx, p.properties.Export_system_include_dirs)...)
p.libraryDecorator.reexportFlags(p.properties.Export_flags...)
// current VNDK prebuilts are only shared libs.
- return p.singleSourcePath(ctx)
+
+ in := p.singleSourcePath(ctx)
+ builderFlags := flagsToBuilderFlags(flags)
+ p.unstrippedOutputFile = in
+ libName := in.Base()
+ if p.needsStrip(ctx) {
+ stripped := android.PathForModuleOut(ctx, "stripped", libName)
+ p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags)
+ in = stripped
+ }
+
+ // Optimize out relinking against shared libraries whose interface hasn't changed by
+ // depending on a table of contents file instead of the library itself.
+ tocFile := android.PathForModuleOut(ctx, libName+".toc")
+ p.tocFile = android.OptionalPathForPath(tocFile)
+ TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
+
+ p.androidMkSuffix = p.NameSuffix()
+
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ if vndkVersion == p.version() {
+ p.androidMkSuffix = ""
+ }
+
+ return in
}
ctx.Module().SkipInstall()
@@ -220,7 +240,8 @@
//
// vndk_prebuilt_shared {
// name: "libfoo",
-// version: "27.1.0",
+// version: "27",
+// target_arch: "arm64",
// vendor_available: true,
// vndk: {
// enabled: true,
diff --git a/cc/xom.go b/cc/xom.go
deleted file mode 100644
index ce817aa..0000000
--- a/cc/xom.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2018 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 cc
-
-import (
- "android/soong/android"
-)
-
-type XomProperties struct {
- Xom *bool
-}
-
-type xom struct {
- Properties XomProperties
-}
-
-func (xom *xom) props() []interface{} {
- return []interface{}{&xom.Properties}
-}
-
-func (xom *xom) begin(ctx BaseModuleContext) {}
-
-func (xom *xom) deps(ctx BaseModuleContext, deps Deps) Deps {
- return deps
-}
-
-func (xom *xom) flags(ctx ModuleContext, flags Flags) Flags {
- disableXom := false
-
- if !ctx.Config().EnableXOM() || ctx.Config().XOMDisabledForPath(ctx.ModuleDir()) {
- disableXom = true
- }
-
- if xom.Properties.Xom != nil && !*xom.Properties.Xom {
- return flags
- }
-
- // If any static dependencies have XOM disabled, we should disable XOM in this module,
- // the assumption being if it's been explicitly disabled then there's probably incompatible
- // code in the library which may get pulled in.
- if !disableXom {
- ctx.VisitDirectDeps(func(m android.Module) {
- cc, ok := m.(*Module)
- if !ok || cc.xom == nil || !cc.static() {
- return
- }
- if cc.xom.Properties.Xom != nil && !*cc.xom.Properties.Xom {
- disableXom = true
- return
- }
- })
- }
-
- // Enable execute-only if none of the dependencies disable it,
- // also if it's explicitly set true (allows overriding dependencies disabling it).
- if !disableXom || (xom.Properties.Xom != nil && *xom.Properties.Xom) {
- // XOM is only supported on AArch64 when using lld.
- if ctx.Arch().ArchType == android.Arm64 && ctx.useClangLld(ctx) {
- flags.Local.LdFlags = append(flags.Local.LdFlags,
- "-Wl,--execute-only",
- "-Wl,-z,separate-code",
- )
- }
- }
-
- return flags
-}
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index 7057b33..65a34fd 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -36,6 +36,7 @@
outputRoot string
keepOutDir bool
depfileOut string
+ inputHash string
)
func init() {
@@ -51,6 +52,8 @@
flag.StringVar(&depfileOut, "depfile-out", "",
"file path of the depfile to generate. This value will replace '__SBOX_DEPFILE__' in the command and will be treated as an output but won't be added to __SBOX_OUT_FILES__")
+ flag.StringVar(&inputHash, "input-hash", "",
+ "This option is ignored. Typical usage is to supply a hash of the list of input names so that the module will be rebuilt if the list (and thus the hash) changes.")
}
func usageViolation(violation string) {
@@ -59,7 +62,7 @@
}
fmt.Fprintf(os.Stderr,
- "Usage: sbox -c <commandToRun> --sandbox-path <sandboxPath> --output-root <outputRoot> [--depfile-out depFile] <outputFile> [<outputFile>...]\n"+
+ "Usage: sbox -c <commandToRun> --sandbox-path <sandboxPath> --output-root <outputRoot> [--depfile-out depFile] [--input-hash hash] <outputFile> [<outputFile>...]\n"+
"\n"+
"Deletes <outputRoot>,"+
"runs <commandToRun>,"+
diff --git a/dexpreopt/Android.bp b/dexpreopt/Android.bp
index c5f24e2..b8f7ea6 100644
--- a/dexpreopt/Android.bp
+++ b/dexpreopt/Android.bp
@@ -4,6 +4,7 @@
srcs: [
"config.go",
"dexpreopt.go",
+ "testing.go",
],
testSrcs: [
"dexpreopt_test.go",
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 2a929c5..98850e5 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -16,22 +16,23 @@
import (
"encoding/json"
+ "fmt"
"strings"
+ "github.com/google/blueprint"
+
"android/soong/android"
)
// GlobalConfig stores the configuration for dex preopting. The fields are set
-// from product variables via dex_preopt_config.mk, except for SoongConfig
-// which come from CreateGlobalSoongConfig.
+// from product variables via dex_preopt_config.mk.
type GlobalConfig struct {
DisablePreopt bool // disable preopt for all modules
DisablePreoptModules []string // modules with preopt disabled by product-specific config
OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server
- GenerateApexImage bool // generate an extra boot image only containing jars from the runtime apex
- UseApexImage bool // use the apex image by default
+ UseArtImage bool // use the art image (use other boot class path dex files without image)
HasSystemOther bool // store odex files that match PatternsOnSystemOther on the system_other partition
PatternsOnSystemOther []string // patterns (using '%' to denote a prefix match) to put odex on the system_other partition
@@ -82,8 +83,6 @@
BootFlags string // extra flags to pass to dex2oat for the boot image
Dex2oatImageXmx string // max heap size for dex2oat for the boot image
Dex2oatImageXms string // initial heap size for dex2oat for the boot image
-
- SoongConfig GlobalSoongConfig // settings read from dexpreopt_soong.config
}
// GlobalSoongConfig contains the global config that is generated from Soong,
@@ -179,14 +178,11 @@
return constructPath(ctx, path).(android.WritablePath)
}
-// LoadGlobalConfig reads the global dexpreopt.config file into a GlobalConfig
-// struct, except the SoongConfig field which is set from the provided
-// soongConfig argument. LoadGlobalConfig is used directly in Soong and in
-// dexpreopt_gen called from Make to read the $OUT/dexpreopt.config written by
-// Make.
-func LoadGlobalConfig(ctx android.PathContext, data []byte, soongConfig GlobalSoongConfig) (GlobalConfig, error) {
+// ParseGlobalConfig parses the given data assumed to be read from the global
+// dexpreopt.config file into a GlobalConfig struct.
+func ParseGlobalConfig(ctx android.PathContext, data []byte) (*GlobalConfig, error) {
type GlobalJSONConfig struct {
- GlobalConfig
+ *GlobalConfig
// Copies of entries in GlobalConfig that are not constructable without extra parameters. They will be
// used to construct the real value manually below.
@@ -204,19 +200,70 @@
config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects))
config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles)
- // Set this here to force the caller to provide a value for this struct (from
- // either CreateGlobalSoongConfig or LoadGlobalSoongConfig).
- config.GlobalConfig.SoongConfig = soongConfig
-
return config.GlobalConfig, nil
}
-// LoadModuleConfig reads a per-module dexpreopt.config file into a ModuleConfig struct. It is not used in Soong, which
-// receives a ModuleConfig struct directly from java/dexpreopt.go. It is used in dexpreopt_gen called from oMake to
-// read the module dexpreopt.config written by Make.
-func LoadModuleConfig(ctx android.PathContext, data []byte) (ModuleConfig, error) {
+type globalConfigAndRaw struct {
+ global *GlobalConfig
+ data []byte
+}
+
+// GetGlobalConfig returns the global dexpreopt.config that's created in the
+// make config phase. It is loaded once the first time it is called for any
+// ctx.Config(), and returns the same data for all future calls with the same
+// ctx.Config(). A value can be inserted for tests using
+// setDexpreoptTestGlobalConfig.
+func GetGlobalConfig(ctx android.PathContext) *GlobalConfig {
+ return getGlobalConfigRaw(ctx).global
+}
+
+// GetGlobalConfigRawData is the same as GetGlobalConfig, except that it returns
+// the literal content of dexpreopt.config.
+func GetGlobalConfigRawData(ctx android.PathContext) []byte {
+ return getGlobalConfigRaw(ctx).data
+}
+
+var globalConfigOnceKey = android.NewOnceKey("DexpreoptGlobalConfig")
+var testGlobalConfigOnceKey = android.NewOnceKey("TestDexpreoptGlobalConfig")
+
+func getGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw {
+ return ctx.Config().Once(globalConfigOnceKey, func() interface{} {
+ if data, err := ctx.Config().DexpreoptGlobalConfig(ctx); err != nil {
+ panic(err)
+ } else if data != nil {
+ globalConfig, err := ParseGlobalConfig(ctx, data)
+ if err != nil {
+ panic(err)
+ }
+ return globalConfigAndRaw{globalConfig, data}
+ }
+
+ // No global config filename set, see if there is a test config set
+ return ctx.Config().Once(testGlobalConfigOnceKey, func() interface{} {
+ // Nope, return a config with preopting disabled
+ return globalConfigAndRaw{&GlobalConfig{
+ DisablePreopt: true,
+ DisableGenerateProfile: true,
+ }, nil}
+ })
+ }).(globalConfigAndRaw)
+}
+
+// SetTestGlobalConfig sets a GlobalConfig that future calls to GetGlobalConfig
+// will return. It must be called before the first call to GetGlobalConfig for
+// the config.
+func SetTestGlobalConfig(config android.Config, globalConfig *GlobalConfig) {
+ config.Once(testGlobalConfigOnceKey, func() interface{} { return globalConfigAndRaw{globalConfig, nil} })
+}
+
+// ParseModuleConfig parses a per-module dexpreopt.config file into a
+// ModuleConfig struct. It is not used in Soong, which receives a ModuleConfig
+// struct directly from java/dexpreopt.go. It is used in dexpreopt_gen called
+// from Make to read the module dexpreopt.config written in the Make config
+// stage.
+func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, error) {
type ModuleJSONConfig struct {
- ModuleConfig
+ *ModuleConfig
// Copies of entries in ModuleConfig that are not constructable without extra parameters. They will be
// used to construct the real value manually below.
@@ -253,21 +300,63 @@
return config.ModuleConfig, nil
}
-// CreateGlobalSoongConfig creates a GlobalSoongConfig from the current context.
-// Should not be used in dexpreopt_gen.
-func CreateGlobalSoongConfig(ctx android.PathContext) GlobalSoongConfig {
- // Default to debug version to help find bugs.
+// dex2oatModuleName returns the name of the module to use for the dex2oat host
+// tool. It should be a binary module with public visibility that is compiled
+// and installed for host.
+func dex2oatModuleName(config android.Config) string {
+ // Default to the debug variant of dex2oat to help find bugs.
// Set USE_DEX2OAT_DEBUG to false for only building non-debug versions.
- var dex2oatBinary string
- if ctx.Config().Getenv("USE_DEX2OAT_DEBUG") == "false" {
- dex2oatBinary = "dex2oat"
+ if config.Getenv("USE_DEX2OAT_DEBUG") == "false" {
+ return "dex2oat"
} else {
- dex2oatBinary = "dex2oatd"
+ return "dex2oatd"
+ }
+}
+
+var dex2oatDepTag = struct {
+ blueprint.BaseDependencyTag
+}{}
+
+// RegisterToolDeps adds the necessary dependencies to binary modules for tools
+// that are required later when Get(Cached)GlobalSoongConfig is called. It
+// should be called from a mutator that's registered with
+// android.RegistrationContext.FinalDepsMutators.
+func RegisterToolDeps(ctx android.BottomUpMutatorContext) {
+ dex2oatBin := dex2oatModuleName(ctx.Config())
+ v := ctx.Config().BuildOSTarget.Variations()
+ ctx.AddFarVariationDependencies(v, dex2oatDepTag, dex2oatBin)
+}
+
+func dex2oatPathFromDep(ctx android.ModuleContext) android.Path {
+ dex2oatBin := dex2oatModuleName(ctx.Config())
+
+ dex2oatModule := ctx.GetDirectDepWithTag(dex2oatBin, dex2oatDepTag)
+ if dex2oatModule == nil {
+ // If this happens there's probably a missing call to AddToolDeps in DepsMutator.
+ panic(fmt.Sprintf("Failed to lookup %s dependency", dex2oatBin))
}
- return GlobalSoongConfig{
+ dex2oatPath := dex2oatModule.(android.HostToolProvider).HostToolPath()
+ if !dex2oatPath.Valid() {
+ panic(fmt.Sprintf("Failed to find host tool path in %s", dex2oatModule))
+ }
+
+ return dex2oatPath.Path()
+}
+
+// createGlobalSoongConfig creates a GlobalSoongConfig from the current context.
+// Should not be used in dexpreopt_gen.
+func createGlobalSoongConfig(ctx android.ModuleContext) *GlobalSoongConfig {
+ if ctx.Config().TestProductVariables != nil {
+ // If we're called in a test there'll be a confusing error from the path
+ // functions below that gets reported without a stack trace, so let's panic
+ // properly with a more helpful message.
+ panic("This should not be called from tests. Please call GlobalSoongConfigForTests somewhere in the test setup.")
+ }
+
+ return &GlobalSoongConfig{
Profman: ctx.Config().HostToolPath(ctx, "profman"),
- Dex2oat: ctx.Config().HostToolPath(ctx, dex2oatBinary),
+ Dex2oat: dex2oatPathFromDep(ctx),
Aapt: ctx.Config().HostToolPath(ctx, "aapt"),
SoongZip: ctx.Config().HostToolPath(ctx, "soong_zip"),
Zip2zip: ctx.Config().HostToolPath(ctx, "zip2zip"),
@@ -276,6 +365,47 @@
}
}
+// The main reason for this Once cache for GlobalSoongConfig is to make the
+// dex2oat path available to singletons. In ordinary modules we get it through a
+// dex2oatDepTag dependency, but in singletons there's no simple way to do the
+// same thing and ensure the right variant is selected, hence this cache to make
+// the resolved path available to singletons. This means we depend on there
+// being at least one ordinary module with a dex2oatDepTag dependency.
+//
+// TODO(b/147613152): Implement a way to deal with dependencies from singletons,
+// and then possibly remove this cache altogether (but the use in
+// GlobalSoongConfigForTests also needs to be rethought).
+var globalSoongConfigOnceKey = android.NewOnceKey("DexpreoptGlobalSoongConfig")
+
+// GetGlobalSoongConfig creates a GlobalSoongConfig the first time it's called,
+// and later returns the same cached instance.
+func GetGlobalSoongConfig(ctx android.ModuleContext) *GlobalSoongConfig {
+ globalSoong := ctx.Config().Once(globalSoongConfigOnceKey, func() interface{} {
+ return createGlobalSoongConfig(ctx)
+ }).(*GlobalSoongConfig)
+
+ // Always resolve the tool path from the dependency, to ensure that every
+ // module has the dependency added properly.
+ myDex2oat := dex2oatPathFromDep(ctx)
+ if myDex2oat != globalSoong.Dex2oat {
+ panic(fmt.Sprintf("Inconsistent dex2oat path in cached config: expected %s, got %s", globalSoong.Dex2oat, myDex2oat))
+ }
+
+ return globalSoong
+}
+
+// GetCachedGlobalSoongConfig returns a cached GlobalSoongConfig created by an
+// earlier GetGlobalSoongConfig call. This function works with any context
+// compatible with a basic PathContext, since it doesn't try to create a
+// GlobalSoongConfig with the proper paths (which requires a full
+// ModuleContext). If there has been no prior call to GetGlobalSoongConfig, nil
+// is returned.
+func GetCachedGlobalSoongConfig(ctx android.PathContext) *GlobalSoongConfig {
+ return ctx.Config().Once(globalSoongConfigOnceKey, func() interface{} {
+ return (*GlobalSoongConfig)(nil)
+ }).(*GlobalSoongConfig)
+}
+
type globalJsonSoongConfig struct {
Profman string
Dex2oat string
@@ -286,17 +416,18 @@
ConstructContext string
}
-// LoadGlobalSoongConfig reads the dexpreopt_soong.config file into a
-// GlobalSoongConfig struct. It is only used in dexpreopt_gen.
-func LoadGlobalSoongConfig(ctx android.PathContext, data []byte) (GlobalSoongConfig, error) {
+// ParseGlobalSoongConfig parses the given data assumed to be read from the
+// global dexpreopt_soong.config file into a GlobalSoongConfig struct. It is
+// only used in dexpreopt_gen.
+func ParseGlobalSoongConfig(ctx android.PathContext, data []byte) (*GlobalSoongConfig, error) {
var jc globalJsonSoongConfig
err := json.Unmarshal(data, &jc)
if err != nil {
- return GlobalSoongConfig{}, err
+ return &GlobalSoongConfig{}, err
}
- config := GlobalSoongConfig{
+ config := &GlobalSoongConfig{
Profman: constructPath(ctx, jc.Profman),
Dex2oat: constructPath(ctx, jc.Dex2oat),
Aapt: constructPath(ctx, jc.Aapt),
@@ -310,7 +441,17 @@
}
func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- config := CreateGlobalSoongConfig(ctx)
+ if GetGlobalConfig(ctx).DisablePreopt {
+ return
+ }
+
+ config := GetCachedGlobalSoongConfig(ctx)
+ if config == nil {
+ // No module has enabled dexpreopting, so we assume there will be no calls
+ // to dexpreopt_gen.
+ return
+ }
+
jc := globalJsonSoongConfig{
Profman: config.Profman.String(),
Dex2oat: config.Dex2oat.String(),
@@ -337,7 +478,14 @@
}
func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
- config := CreateGlobalSoongConfig(ctx)
+ if GetGlobalConfig(ctx).DisablePreopt {
+ return
+ }
+
+ config := GetCachedGlobalSoongConfig(ctx)
+ if config == nil {
+ return
+ }
ctx.Strict("DEX2OAT", config.Dex2oat.String())
ctx.Strict("DEXPREOPT_GEN_DEPS", strings.Join([]string{
@@ -351,8 +499,8 @@
}, " "))
}
-func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
- return GlobalConfig{
+func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig {
+ return &GlobalConfig{
DisablePreopt: false,
DisablePreoptModules: nil,
OnlyPreoptBootImageAndSystemServer: false,
@@ -390,7 +538,14 @@
BootFlags: "",
Dex2oatImageXmx: "",
Dex2oatImageXms: "",
- SoongConfig: GlobalSoongConfig{
+ }
+}
+
+func GlobalSoongConfigForTests(config android.Config) *GlobalSoongConfig {
+ // Install the test GlobalSoongConfig in the Once cache so that later calls to
+ // Get(Cached)GlobalSoongConfig returns it without trying to create a real one.
+ return config.Once(globalSoongConfigOnceKey, func() interface{} {
+ return &GlobalSoongConfig{
Profman: android.PathForTesting("profman"),
Dex2oat: android.PathForTesting("dex2oat"),
Aapt: android.PathForTesting("aapt"),
@@ -398,6 +553,6 @@
Zip2zip: android.PathForTesting("zip2zip"),
ManifestCheck: android.PathForTesting("manifest_check"),
ConstructContext: android.PathForTesting("construct_context.sh"),
- },
- }
+ }
+ }).(*GlobalSoongConfig)
}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index ac5b691..6cb9873 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -41,16 +41,25 @@
"android/soong/android"
+ "github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
)
const SystemPartition = "/system/"
const SystemOtherPartition = "/system_other/"
+type dependencyTag struct {
+ blueprint.BaseDependencyTag
+ name string
+}
+
+var SystemServerDepTag = dependencyTag{name: "system-server-dep"}
+var SystemServerForcedDepTag = dependencyTag{name: "system-server-forced-dep"}
+
// GenerateDexpreoptRule generates a set of commands that will preopt a module based on a GlobalConfig and a
// ModuleConfig. The produced files and their install locations will be available through rule.Installs().
-func GenerateDexpreoptRule(ctx android.PathContext,
- global GlobalConfig, module ModuleConfig) (rule *android.RuleBuilder, err error) {
+func GenerateDexpreoptRule(ctx android.PathContext, globalSoong *GlobalSoongConfig,
+ global *GlobalConfig, module *ModuleConfig) (rule *android.RuleBuilder, err error) {
defer func() {
if r := recover(); r != nil {
@@ -72,13 +81,13 @@
var profile android.WritablePath
if generateProfile {
- profile = profileCommand(ctx, global, module, rule)
+ profile = profileCommand(ctx, globalSoong, global, module, rule)
}
if generateBootProfile {
- bootProfileCommand(ctx, global, module, rule)
+ bootProfileCommand(ctx, globalSoong, global, module, rule)
}
- if !dexpreoptDisabled(global, module) {
+ if !dexpreoptDisabled(ctx, global, module) {
// Don't preopt individual boot jars, they will be preopted together.
if !contains(global.BootJars, module.Name) {
appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) &&
@@ -87,7 +96,7 @@
generateDM := shouldGenerateDM(module, global)
for archIdx, _ := range module.Archs {
- dexpreoptCommand(ctx, global, module, rule, archIdx, profile, appImage, generateDM)
+ dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, profile, appImage, generateDM)
}
}
}
@@ -95,14 +104,21 @@
return rule, nil
}
-func dexpreoptDisabled(global GlobalConfig, module ModuleConfig) bool {
+func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *ModuleConfig) bool {
if contains(global.DisablePreoptModules, module.Name) {
return true
}
// Don't preopt system server jars that are updatable.
for _, p := range global.UpdatableSystemServerJars {
- if _, jar := SplitApexJarPair(p); jar == module.Name {
+ if _, jar := android.SplitApexJarPair(p); jar == module.Name {
+ return true
+ }
+ }
+
+ // Don't preopt system server jars that are not Soong modules.
+ if android.InList(module.Name, NonUpdatableSystemServerJars(ctx, global)) {
+ if _, ok := ctx.(android.ModuleContext); !ok {
return true
}
}
@@ -119,8 +135,8 @@
return false
}
-func profileCommand(ctx android.PathContext, global GlobalConfig, module ModuleConfig,
- rule *android.RuleBuilder) android.WritablePath {
+func profileCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
+ module *ModuleConfig, rule *android.RuleBuilder) android.WritablePath {
profilePath := module.BuildPath.InSameDir(ctx, "profile.prof")
profileInstalledPath := module.DexLocation + ".prof"
@@ -131,7 +147,7 @@
cmd := rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
- Tool(global.SoongConfig.Profman)
+ Tool(globalSoong.Profman)
if module.ProfileIsTextListing {
// The profile is a test listing of classes (used for framework jars).
@@ -158,8 +174,8 @@
return profilePath
}
-func bootProfileCommand(ctx android.PathContext, global GlobalConfig, module ModuleConfig,
- rule *android.RuleBuilder) android.WritablePath {
+func bootProfileCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
+ module *ModuleConfig, rule *android.RuleBuilder) android.WritablePath {
profilePath := module.BuildPath.InSameDir(ctx, "profile.bprof")
profileInstalledPath := module.DexLocation + ".bprof"
@@ -170,7 +186,7 @@
cmd := rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
- Tool(global.SoongConfig.Profman)
+ Tool(globalSoong.Profman)
// The profile is a test listing of methods.
// We need to generate the actual binary profile.
@@ -190,8 +206,9 @@
return profilePath
}
-func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder,
- archIdx int, profile android.WritablePath, appImage bool, generateDM bool) {
+func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
+ module *ModuleConfig, rule *android.RuleBuilder, archIdx int, profile android.WritablePath,
+ appImage bool, generateDM bool) {
arch := module.Archs[archIdx]
@@ -236,7 +253,8 @@
var conditionalClassLoaderContextHost29 android.Paths
var conditionalClassLoaderContextTarget29 []string
- var classLoaderContextHostString string
+ var classLoaderContextHostString, classLoaderContextDeviceString string
+ var classLoaderDeps android.Paths
if module.EnforceUsesLibraries {
usesLibs := append(copyOf(module.UsesLibraries), module.PresentOptionalUsesLibraries...)
@@ -282,6 +300,30 @@
filepath.Join("/system/framework", hidlBase+".jar"))
classLoaderContextHostString = strings.Join(classLoaderContextHost.Strings(), ":")
+ } else if android.InList(module.Name, NonUpdatableSystemServerJars(ctx, global)) {
+ // We expect that all dexpreopted system server jars are Soong modules.
+ mctx, isModule := ctx.(android.ModuleContext)
+ if !isModule {
+ panic("Cannot dexpreopt system server jar that is not a soong module.")
+ }
+
+ // System server jars should be dexpreopted together: class loader context of each jar
+ // should include preceding jars (which can be found as dependencies of the current jar
+ // with a special tag).
+ var jarsOnHost android.Paths
+ var jarsOnDevice []string
+ mctx.VisitDirectDepsWithTag(SystemServerDepTag, func(dep android.Module) {
+ depName := mctx.OtherModuleName(dep)
+ if jar, ok := dep.(interface{ DexJar() android.Path }); ok {
+ jarsOnHost = append(jarsOnHost, jar.DexJar())
+ jarsOnDevice = append(jarsOnDevice, "/system/framework/"+depName+".jar")
+ } else {
+ mctx.ModuleErrorf("module \"%s\" is not a jar", depName)
+ }
+ })
+ classLoaderContextHostString = strings.Join(jarsOnHost.Strings(), ":")
+ classLoaderContextDeviceString = strings.Join(jarsOnDevice, ":")
+ classLoaderDeps = jarsOnHost
} else {
// Pass special class loader context to skip the classpath and collision check.
// This will get removed once LOCAL_USES_LIBRARIES is enforced.
@@ -293,20 +335,25 @@
rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String()))
rule.Command().FlagWithOutput("rm -f ", odexPath)
// Set values in the environment of the rule. These may be modified by construct_context.sh.
- rule.Command().FlagWithArg("class_loader_context_arg=--class-loader-context=", classLoaderContextHostString)
- rule.Command().Text(`stored_class_loader_context_arg=""`)
+ if classLoaderContextHostString == `\&` {
+ rule.Command().Text(`class_loader_context_arg=--class-loader-context=\&`)
+ rule.Command().Text(`stored_class_loader_context_arg=""`)
+ } else {
+ rule.Command().Text("class_loader_context_arg=--class-loader-context=PCL[" + classLoaderContextHostString + "]")
+ rule.Command().Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + classLoaderContextDeviceString + "]")
+ }
if module.EnforceUsesLibraries {
if module.ManifestPath != nil {
rule.Command().Text(`target_sdk_version="$(`).
- Tool(global.SoongConfig.ManifestCheck).
+ Tool(globalSoong.ManifestCheck).
Flag("--extract-target-sdk-version").
Input(module.ManifestPath).
Text(`)"`)
} else {
// No manifest to extract targetSdkVersion from, hope that DexJar is an APK
rule.Command().Text(`target_sdk_version="$(`).
- Tool(global.SoongConfig.Aapt).
+ Tool(globalSoong.Aapt).
Flag("dump badging").
Input(module.DexPath).
Text(`| grep "targetSdkVersion" | sed -n "s/targetSdkVersion:'\(.*\)'/\1/p"`).
@@ -327,7 +374,7 @@
Implicits(conditionalClassLoaderContextHost29)
rule.Command().Textf(`conditional_target_libs_29="%s"`,
strings.Join(conditionalClassLoaderContextTarget29, " "))
- rule.Command().Text("source").Tool(global.SoongConfig.ConstructContext).Input(module.DexPath)
+ rule.Command().Text("source").Tool(globalSoong.ConstructContext).Input(module.DexPath)
}
// Devices that do not have a product partition use a symlink from /product to /system/product.
@@ -340,7 +387,7 @@
cmd := rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
- Tool(global.SoongConfig.Dex2oat).
+ Tool(globalSoong.Dex2oat).
Flag("--avoid-storing-invocation").
FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatXms).
@@ -348,7 +395,7 @@
Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", module.PreoptBootClassPathDexFiles, ":").
Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", module.PreoptBootClassPathDexLocations, ":").
Flag("${class_loader_context_arg}").
- Flag("${stored_class_loader_context_arg}").
+ Flag("${stored_class_loader_context_arg}").Implicits(classLoaderDeps).
FlagWithArg("--boot-image=", strings.Join(module.DexPreoptImageLocations, ":")).Implicits(module.DexPreoptImagesDeps[archIdx].Paths()).
FlagWithInput("--dex-file=", module.DexPath).
FlagWithArg("--dex-location=", dexLocationArg).
@@ -379,7 +426,7 @@
cmd.FlagWithArg("--copy-dex-files=", "false")
}
- if !anyHavePrefix(preoptFlags, "--compiler-filter=") {
+ if !android.PrefixInList(preoptFlags, "--compiler-filter=") {
var compilerFilter string
if contains(global.SystemServerJars, module.Name) {
// Jars of system server, use the product option if it is set, speed otherwise.
@@ -409,7 +456,7 @@
dmInstalledPath := pathtools.ReplaceExtension(module.DexLocation, "dm")
tmpPath := module.BuildPath.InSameDir(ctx, "primary.vdex")
rule.Command().Text("cp -f").Input(vdexPath).Output(tmpPath)
- rule.Command().Tool(global.SoongConfig.SoongZip).
+ rule.Command().Tool(globalSoong.SoongZip).
FlagWithArg("-L", "9").
FlagWithOutput("-o", dmPath).
Flag("-j").
@@ -474,14 +521,14 @@
rule.Install(vdexPath, vdexInstallPath)
}
-func shouldGenerateDM(module ModuleConfig, global GlobalConfig) bool {
+func shouldGenerateDM(module *ModuleConfig, global *GlobalConfig) bool {
// Generating DM files only makes sense for verify, avoid doing for non verify compiler filter APKs.
// No reason to use a dm file if the dex is already uncompressed.
return global.GenerateDMFiles && !module.UncompressedDex &&
contains(module.PreoptFlags, "--compiler-filter=verify")
}
-func OdexOnSystemOtherByName(name string, dexLocation string, global GlobalConfig) bool {
+func OdexOnSystemOtherByName(name string, dexLocation string, global *GlobalConfig) bool {
if !global.HasSystemOther {
return false
}
@@ -503,7 +550,7 @@
return false
}
-func odexOnSystemOther(module ModuleConfig, global GlobalConfig) bool {
+func odexOnSystemOther(module *ModuleConfig, global *GlobalConfig) bool {
return OdexOnSystemOtherByName(module.Name, module.DexLocation, global)
}
@@ -516,7 +563,7 @@
return filepath.Join(filepath.Dir(filepath.Dir(path.String())), filepath.Base(path.String()))
}
-func pathForLibrary(module ModuleConfig, lib string) android.Path {
+func pathForLibrary(module *ModuleConfig, lib string) android.Path {
path, ok := module.LibraryPaths[lib]
if !ok {
panic(fmt.Errorf("unknown library path for %q", lib))
@@ -537,19 +584,29 @@
}
// Expected format for apexJarValue = <apex name>:<jar name>
-func SplitApexJarPair(apexJarValue string) (string, string) {
- var apexJarPair []string = strings.SplitN(apexJarValue, ":", 2)
- if apexJarPair == nil || len(apexJarPair) != 2 {
- panic(fmt.Errorf("malformed apexJarValue: %q, expected format: <apex>:<jar>",
- apexJarValue))
- }
- return apexJarPair[0], apexJarPair[1]
+func GetJarLocationFromApexJarPair(apexJarValue string) string {
+ apex, jar := android.SplitApexJarPair(apexJarValue)
+ return filepath.Join("/apex", apex, "javalib", jar+".jar")
}
-// Expected format for apexJarValue = <apex name>:<jar name>
-func GetJarLocationFromApexJarPair(apexJarValue string) string {
- apex, jar := SplitApexJarPair(apexJarValue)
- return filepath.Join("/apex", apex, "javalib", jar+".jar")
+func GetJarsFromApexJarPairs(apexJarPairs []string) []string {
+ modules := make([]string, len(apexJarPairs))
+ for i, p := range apexJarPairs {
+ _, jar := android.SplitApexJarPair(p)
+ modules[i] = jar
+ }
+ return modules
+}
+
+var nonUpdatableSystemServerJarsKey = android.NewOnceKey("nonUpdatableSystemServerJars")
+
+// TODO: eliminate the superficial global config parameter by moving global config definition
+// from java subpackage to dexpreopt.
+func NonUpdatableSystemServerJars(ctx android.PathContext, global *GlobalConfig) []string {
+ return ctx.Config().Once(nonUpdatableSystemServerJarsKey, func() interface{} {
+ return android.RemoveListFromList(global.SystemServerJars,
+ GetJarsFromApexJarPairs(global.UpdatableSystemServerJars))
+ }).([]string)
}
func contains(l []string, s string) bool {
@@ -561,32 +618,4 @@
return false
}
-// remove all elements in a from b, returning a new slice
-func filterOut(a []string, b []string) []string {
- var ret []string
- for _, x := range b {
- if !contains(a, x) {
- ret = append(ret, x)
- }
- }
- return ret
-}
-
-func replace(l []string, from, to string) {
- for i := range l {
- if l[i] == from {
- l[i] = to
- }
- }
-}
-
var copyOf = android.CopyOf
-
-func anyHavePrefix(l []string, prefix string) bool {
- for _, x := range l {
- if strings.HasPrefix(x, prefix) {
- return true
- }
- }
- return false
-}
diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
index e2818bb..e89f045 100644
--- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
+++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
@@ -80,13 +80,13 @@
globalSoongConfigData, err := ioutil.ReadFile(*globalSoongConfigPath)
if err != nil {
- fmt.Fprintf(os.Stderr, "error reading global config %q: %s\n", *globalSoongConfigPath, err)
+ fmt.Fprintf(os.Stderr, "error reading global Soong config %q: %s\n", *globalSoongConfigPath, err)
os.Exit(2)
}
- globalSoongConfig, err := dexpreopt.LoadGlobalSoongConfig(ctx, globalSoongConfigData)
+ globalSoongConfig, err := dexpreopt.ParseGlobalSoongConfig(ctx, globalSoongConfigData)
if err != nil {
- fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalSoongConfigPath, err)
+ fmt.Fprintf(os.Stderr, "error parsing global Soong config %q: %s\n", *globalSoongConfigPath, err)
os.Exit(2)
}
@@ -96,9 +96,9 @@
os.Exit(2)
}
- globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, globalConfigData, globalSoongConfig)
+ globalConfig, err := dexpreopt.ParseGlobalConfig(ctx, globalConfigData)
if err != nil {
- fmt.Fprintf(os.Stderr, "error parse global config %q: %s\n", *globalConfigPath, err)
+ fmt.Fprintf(os.Stderr, "error parsing global config %q: %s\n", *globalConfigPath, err)
os.Exit(2)
}
@@ -108,9 +108,9 @@
os.Exit(2)
}
- moduleConfig, err := dexpreopt.LoadModuleConfig(ctx, moduleConfigData)
+ moduleConfig, err := dexpreopt.ParseModuleConfig(ctx, moduleConfigData)
if err != nil {
- fmt.Fprintf(os.Stderr, "error loading module config %q: %s\n", *moduleConfigPath, err)
+ fmt.Fprintf(os.Stderr, "error parsing module config %q: %s\n", *moduleConfigPath, err)
os.Exit(2)
}
@@ -130,12 +130,12 @@
}
}()
- writeScripts(ctx, globalConfig, moduleConfig, *dexpreoptScriptPath)
+ writeScripts(ctx, globalSoongConfig, globalConfig, moduleConfig, *dexpreoptScriptPath)
}
-func writeScripts(ctx android.PathContext, global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig,
- dexpreoptScriptPath string) {
- dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, global, module)
+func writeScripts(ctx android.PathContext, globalSoong *dexpreopt.GlobalSoongConfig,
+ global *dexpreopt.GlobalConfig, module *dexpreopt.ModuleConfig, dexpreoptScriptPath string) {
+ dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, module)
if err != nil {
panic(err)
}
@@ -150,7 +150,7 @@
dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath.String()))
dexpreoptRule.Command().Text("cp -f").Input(install.From).Output(installPath)
}
- dexpreoptRule.Command().Tool(global.SoongConfig.SoongZip).
+ dexpreoptRule.Command().Tool(globalSoong.SoongZip).
FlagWithArg("-o ", "$2").
FlagWithArg("-C ", installDir.String()).
FlagWithArg("-D ", installDir.String())
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index a128dc0..d239993 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -20,20 +20,20 @@
"testing"
)
-func testSystemModuleConfig(ctx android.PathContext, name string) ModuleConfig {
+func testSystemModuleConfig(ctx android.PathContext, name string) *ModuleConfig {
return testModuleConfig(ctx, name, "system")
}
-func testSystemProductModuleConfig(ctx android.PathContext, name string) ModuleConfig {
+func testSystemProductModuleConfig(ctx android.PathContext, name string) *ModuleConfig {
return testModuleConfig(ctx, name, "system/product")
}
-func testProductModuleConfig(ctx android.PathContext, name string) ModuleConfig {
+func testProductModuleConfig(ctx android.PathContext, name string) *ModuleConfig {
return testModuleConfig(ctx, name, "product")
}
-func testModuleConfig(ctx android.PathContext, name, partition string) ModuleConfig {
- return ModuleConfig{
+func testModuleConfig(ctx android.PathContext, name, partition string) *ModuleConfig {
+ return &ModuleConfig{
Name: name,
DexLocation: fmt.Sprintf("/%s/app/test/%s.apk", partition, name),
BuildPath: android.PathForOutput(ctx, fmt.Sprintf("%s/%s.apk", name, name)),
@@ -61,10 +61,13 @@
}
func TestDexPreopt(t *testing.T) {
- ctx := android.PathContextForTesting(android.TestConfig("out", nil, "", nil))
- global, module := GlobalConfigForTests(ctx), testSystemModuleConfig(ctx, "test")
+ config := android.TestConfig("out", nil, "", nil)
+ ctx := android.PathContextForTesting(config)
+ globalSoong := GlobalSoongConfigForTests(config)
+ global := GlobalConfigForTests(ctx)
+ module := testSystemModuleConfig(ctx, "test")
- rule, err := GenerateDexpreoptRule(ctx, global, module)
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module)
if err != nil {
t.Fatal(err)
}
@@ -80,7 +83,9 @@
}
func TestDexPreoptSystemOther(t *testing.T) {
- ctx := android.PathContextForTesting(android.TestConfig("out", nil, "", nil))
+ config := android.TestConfig("out", nil, "", nil)
+ ctx := android.PathContextForTesting(config)
+ globalSoong := GlobalSoongConfigForTests(config)
global := GlobalConfigForTests(ctx)
systemModule := testSystemModuleConfig(ctx, "Stest")
systemProductModule := testSystemProductModuleConfig(ctx, "SPtest")
@@ -89,7 +94,7 @@
global.HasSystemOther = true
type moduleTest struct {
- module ModuleConfig
+ module *ModuleConfig
expectedPartition string
}
tests := []struct {
@@ -118,7 +123,7 @@
for _, test := range tests {
global.PatternsOnSystemOther = test.patterns
for _, mt := range test.moduleTests {
- rule, err := GenerateDexpreoptRule(ctx, global, mt.module)
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, mt.module)
if err != nil {
t.Fatal(err)
}
@@ -138,12 +143,15 @@
}
func TestDexPreoptProfile(t *testing.T) {
- ctx := android.PathContextForTesting(android.TestConfig("out", nil, "", nil))
- global, module := GlobalConfigForTests(ctx), testSystemModuleConfig(ctx, "test")
+ config := android.TestConfig("out", nil, "", nil)
+ ctx := android.PathContextForTesting(config)
+ globalSoong := GlobalSoongConfigForTests(config)
+ global := GlobalConfigForTests(ctx)
+ module := testSystemModuleConfig(ctx, "test")
module.ProfileClassListing = android.OptionalPathForPath(android.PathForTesting("profile"))
- rule, err := GenerateDexpreoptRule(ctx, global, module)
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module)
if err != nil {
t.Fatal(err)
}
diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go
new file mode 100644
index 0000000..b572eb3
--- /dev/null
+++ b/dexpreopt/testing.go
@@ -0,0 +1,47 @@
+// Copyright 2020 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 dexpreopt
+
+import (
+ "android/soong/android"
+)
+
+type dummyToolBinary struct {
+ android.ModuleBase
+}
+
+func (m *dummyToolBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
+
+func (m *dummyToolBinary) HostToolPath() android.OptionalPath {
+ return android.OptionalPathForPath(android.PathForTesting("dex2oat"))
+}
+
+func dummyToolBinaryFactory() android.Module {
+ module := &dummyToolBinary{}
+ android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
+ return module
+}
+
+func RegisterToolModulesForTest(ctx *android.TestContext) {
+ ctx.RegisterModuleType("dummy_tool_binary", dummyToolBinaryFactory)
+}
+
+func BpToolModulesForTest() string {
+ return `
+ dummy_tool_binary {
+ name: "dex2oatd",
+ }
+ `
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index a0008d3..fe877fe 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -26,6 +26,7 @@
"android/soong/android"
"android/soong/shared"
+ "crypto/sha256"
"path/filepath"
)
@@ -309,6 +310,7 @@
addLocationLabel(out.Rel(), []string{filepath.Join("__SBOX_OUT_DIR__", out.Rel())})
}
+ referencedIn := false
referencedDepfile := false
rawCommand, err := android.ExpandNinjaEscaped(task.cmd, func(name string) (string, bool, error) {
@@ -333,6 +335,7 @@
}
return locationLabels[firstLabel][0], false, nil
case "in":
+ referencedIn = true
return "${in}", true, nil
case "out":
return "__SBOX_OUT_FILES__", false, nil
@@ -398,8 +401,16 @@
// Escape the command for the shell
rawCommand = "'" + strings.Replace(rawCommand, "'", `'\''`, -1) + "'"
g.rawCommands = append(g.rawCommands, rawCommand)
- sandboxCommand := fmt.Sprintf("rm -rf %s && $sboxCmd --sandbox-path %s --output-root %s -c %s %s $allouts",
- task.genDir, sandboxPath, task.genDir, rawCommand, depfilePlaceholder)
+
+ sandboxCommand := fmt.Sprintf("rm -rf %s && $sboxCmd --sandbox-path %s --output-root %s",
+ task.genDir, sandboxPath, task.genDir)
+
+ if !referencedIn {
+ sandboxCommand = sandboxCommand + hashSrcFiles(srcFiles)
+ }
+
+ sandboxCommand = sandboxCommand + fmt.Sprintf(" -c %s %s $allouts",
+ rawCommand, depfilePlaceholder)
ruleParams := blueprint.RuleParams{
Command: sandboxCommand,
@@ -463,6 +474,14 @@
}
+func hashSrcFiles(srcFiles android.Paths) string {
+ h := sha256.New()
+ for _, src := range srcFiles {
+ h.Write([]byte(src.String()))
+ }
+ return fmt.Sprintf(" --input-hash %x", h.Sum(nil))
+}
+
func (g *Module) generateSourceFile(ctx android.ModuleContext, task generateTask, rule blueprint.Rule) {
desc := "generate"
if len(task.out) == 0 {
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 7eb43ac..4b36600 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -502,6 +502,93 @@
}
}
+func TestGenruleHashInputs(t *testing.T) {
+
+ // The basic idea here is to verify that the sbox command (which is
+ // in the Command field of the generate rule) contains a hash of the
+ // inputs, but only if $(in) is not referenced in the genrule cmd
+ // property.
+
+ // By including a hash of the inputs, we cause the rule to re-run if
+ // the list of inputs changes (because the sbox command changes).
+
+ // However, if the genrule cmd property already contains $(in), then
+ // the dependency is already expressed, so we don't need to include the
+ // hash in that case.
+
+ bp := `
+ genrule {
+ name: "hash0",
+ srcs: ["in1.txt", "in2.txt"],
+ out: ["out"],
+ cmd: "echo foo > $(out)",
+ }
+ genrule {
+ name: "hash1",
+ srcs: ["*.txt"],
+ out: ["out"],
+ cmd: "echo bar > $(out)",
+ }
+ genrule {
+ name: "hash2",
+ srcs: ["*.txt"],
+ out: ["out"],
+ cmd: "echo $(in) > $(out)",
+ }
+ `
+ testcases := []struct {
+ name string
+ expectedHash string
+ }{
+ {
+ name: "hash0",
+ // sha256 value obtained from: echo -n 'in1.txtin2.txt' | sha256sum
+ expectedHash: "031097e11e0a8c822c960eb9742474f46336360a515744000d086d94335a9cb9",
+ },
+ {
+ name: "hash1",
+ // sha256 value obtained from: echo -n 'in1.txtin2.txtin3.txt' | sha256sum
+ expectedHash: "de5d22a4a7ab50d250cc59fcdf7a7e0775790d270bfca3a7a9e1f18a70dd996c",
+ },
+ {
+ name: "hash2",
+ // $(in) is present, option should not appear
+ expectedHash: "",
+ },
+ }
+
+ config := testConfig(bp, nil)
+ ctx := testContext(config)
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ if errs == nil {
+ _, errs = ctx.PrepareBuildActions(config)
+ }
+ if errs != nil {
+ t.Fatal(errs)
+ }
+
+ for _, test := range testcases {
+ t.Run(test.name, func(t *testing.T) {
+ gen := ctx.ModuleForTests(test.name, "")
+ command := gen.Rule("generator").RuleParams.Command
+
+ if len(test.expectedHash) > 0 {
+ // We add spaces before and after to make sure that
+ // this option doesn't abutt another sbox option.
+ expectedInputHashOption := " --input-hash " + test.expectedHash + " "
+
+ if !strings.Contains(command, expectedInputHashOption) {
+ t.Errorf("Expected command \"%s\" to contain \"%s\"", command, expectedInputHashOption)
+ }
+ } else {
+ if strings.Contains(command, "--input-hash") {
+ t.Errorf("Unexpected \"--input-hash\" found in command: \"%s\"", command)
+ }
+ }
+ })
+ }
+}
+
func TestGenSrcs(t *testing.T) {
testcases := []struct {
name string
diff --git a/java/aar.go b/java/aar.go
index 24c5e7d..6e3b9e6 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -101,6 +101,7 @@
usesNonSdkApis bool
sdkLibraries []string
hasNoCode bool
+ LoggingParent string
splitNames []string
splits []split
@@ -134,15 +135,8 @@
manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
- hasVersionCode := false
- hasVersionName := false
- for _, f := range a.aaptProperties.Aaptflags {
- if strings.HasPrefix(f, "--version-code") {
- hasVersionCode = true
- } else if strings.HasPrefix(f, "--version-name") {
- hasVersionName = true
- }
- }
+ hasVersionCode := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-code")
+ hasVersionName := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-name")
// Flags specified in Android.bp
linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...)
@@ -241,7 +235,8 @@
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, sdkLibraries,
- a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex, a.hasNoCode)
+ a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex, a.hasNoCode,
+ a.LoggingParent)
// Add additional manifest files to transitive manifests.
additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests)
@@ -337,7 +332,7 @@
// Extract assets from the resource package output so that they can be used later in aapt2link
// for modules that depend on this one.
- if android.PrefixedStringInList(linkFlags, "-A ") || len(assetPackages) > 0 {
+ if android.PrefixInList(linkFlags, "-A ") || len(assetPackages) > 0 {
assets := android.PathForModuleOut(ctx, "assets.zip")
ctx.Build(pctx, android.BuildParams{
Rule: extractAssetsRule,
diff --git a/java/android_manifest.go b/java/android_manifest.go
index e3646f5..9a71be2 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -53,7 +53,7 @@
// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries []string,
- isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool) android.Path {
+ isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
var args []string
if isLibrary {
@@ -91,6 +91,9 @@
args = append(args, "--has-no-code")
}
+ if loggingParent != "" {
+ args = append(args, "--logging-parent", loggingParent)
+ }
var deps android.Paths
targetSdkVersion, err := sdkContext.targetSdkVersion().effectiveVersionString(ctx)
if err != nil {
diff --git a/java/app.go b/java/app.go
index 6e0ffeb..ed4462c 100755
--- a/java/app.go
+++ b/java/app.go
@@ -79,6 +79,10 @@
// list of native libraries that will be provided in or alongside the resulting jar
Jni_libs []string `android:"arch_variant"`
+ // if true, allow JNI libraries that link against platform APIs even if this module sets
+ // sdk_version.
+ Jni_uses_platform_apis *bool
+
// STL library to use for JNI libraries.
Stl *string `android:"arch_variant"`
@@ -111,6 +115,9 @@
// the package name of this app. The package name in the manifest file is used if one was not given.
Package_name *string
+
+ // the logging parent of this app.
+ Logging_parent *string
}
type AndroidApp struct {
@@ -142,6 +149,10 @@
noticeOutputs android.NoticeOutputs
}
+func (a *AndroidApp) IsInstallable() bool {
+ return Bool(a.properties.Installable)
+}
+
func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
return nil
}
@@ -269,13 +280,7 @@
aaptLinkFlags := []string{}
// Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided.
- hasProduct := false
- for _, f := range a.aaptProperties.Aaptflags {
- if strings.HasPrefix(f, "--product") {
- hasProduct = true
- break
- }
- }
+ hasProduct := android.PrefixInList(a.aaptProperties.Aaptflags, "--product")
if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
aaptLinkFlags = append(aaptLinkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
}
@@ -305,7 +310,7 @@
a.aapt.splitNames = a.appProperties.Package_splits
a.aapt.sdkLibraries = a.exportedSdkLibs
-
+ a.aapt.LoggingParent = String(a.overridableAppProperties.Logging_parent)
a.aapt.buildActions(ctx, sdkContext(a), aaptLinkFlags...)
// apps manifests are handled by aapt, don't let Module see them
@@ -338,7 +343,6 @@
installDir = filepath.Join("app", a.installApkName)
}
a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
- a.dexpreopter.isInstallable = Bool(a.properties.Installable)
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
@@ -386,16 +390,20 @@
return false
}
- path := child.(android.Module).NoticeFile()
- if path.Valid() {
- noticePathSet[path.Path()] = true
+ paths := child.(android.Module).NoticeFiles()
+ if len(paths) > 0 {
+ for _, path := range paths {
+ noticePathSet[path] = true
+ }
}
return true
})
// If the app has one, add it too.
- if a.NoticeFile().Valid() {
- noticePathSet[a.NoticeFile().Path()] = true
+ if len(a.NoticeFiles()) > 0 {
+ for _, path := range a.NoticeFiles() {
+ noticePathSet[path] = true
+ }
}
if len(noticePathSet) == 0 {
@@ -487,7 +495,7 @@
dexJarFile := a.dexBuildActions(ctx)
- jniLibs, certificateDeps := collectAppDeps(ctx, a.shouldEmbedJnis(ctx))
+ jniLibs, certificateDeps := collectAppDeps(ctx, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
jniJarFile := a.jniBuildActions(jniLibs, ctx)
if ctx.Failed() {
@@ -523,7 +531,8 @@
}
}
-func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps bool) ([]jniLib, []Certificate) {
+func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps bool,
+ checkNativeSdkVersion bool) ([]jniLib, []Certificate) {
var jniLibs []jniLib
var certificates []Certificate
seenModulePaths := make(map[string]bool)
@@ -545,6 +554,18 @@
}
seenModulePaths[path.String()] = true
+ if checkNativeSdkVersion {
+ if app, ok := ctx.Module().(interface{ sdkVersion() sdkSpec }); ok {
+ if app.sdkVersion().specified() &&
+ app.sdkVersion().kind != sdkCorePlatform &&
+ dep.SdkVersion() == "" {
+ ctx.PropertyErrorf("jni_libs",
+ "JNI dependency %q uses platform APIs, but this module does not",
+ otherName)
+ }
+ }
+ }
+
if lib.Valid() {
jniLibs = append(jniLibs, jniLib{
name: ctx.OtherModuleName(module),
@@ -583,6 +604,13 @@
return String(a.overridableAppProperties.Certificate)
}
+func (a *AndroidApp) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+ if IsJniDepTag(ctx.OtherModuleDependencyTag(dep)) {
+ return true
+ }
+ return a.Library.DepIsInSameApex(ctx, dep)
+}
+
// For OutputFileProducer interface
func (a *AndroidApp) OutputFiles(tag string) (android.Paths, error) {
switch tag {
@@ -915,6 +943,10 @@
Filename *string
}
+func (a *AndroidAppImport) IsInstallable() bool {
+ return true
+}
+
// Updates properties with variant-specific values.
func (a *AndroidAppImport) processVariants(ctx android.LoadHookContext) {
config := ctx.Config()
@@ -1030,7 +1062,7 @@
ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set")
}
- _, certificates := collectAppDeps(ctx, false)
+ _, certificates := collectAppDeps(ctx, false, false)
// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
// TODO: LOCAL_PACKAGE_SPLITS
@@ -1057,7 +1089,6 @@
}
a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
- a.dexpreopter.isInstallable = true
a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
@@ -1286,7 +1317,7 @@
r.aapt.buildActions(ctx, r, "--no-resource-deduping", "--no-resource-removal")
// Sign the built package
- _, certificates := collectAppDeps(ctx, false)
+ _, certificates := collectAppDeps(ctx, false, false)
certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx)
signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk")
SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates)
diff --git a/java/app_test.go b/java/app_test.go
index c86b038..0c6da7a 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -903,6 +903,7 @@
name: "libjni",
system_shared_libs: [],
stl: "none",
+ sdk_version: "current",
}
android_app {
@@ -1181,6 +1182,7 @@
name: "bar",
base: "foo",
certificate: ":new_certificate",
+ logging_parent: "bah",
}
android_app_certificate {
@@ -1196,37 +1198,41 @@
`)
expectedVariants := []struct {
- moduleName string
- variantName string
- apkName string
- apkPath string
- signFlag string
- overrides []string
- aaptFlag string
+ moduleName string
+ variantName string
+ apkName string
+ apkPath string
+ signFlag string
+ overrides []string
+ aaptFlag string
+ logging_parent string
}{
{
- moduleName: "foo",
- variantName: "android_common",
- apkPath: "/target/product/test_device/system/app/foo/foo.apk",
- signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
- overrides: []string{"qux"},
- aaptFlag: "",
+ moduleName: "foo",
+ variantName: "android_common",
+ apkPath: "/target/product/test_device/system/app/foo/foo.apk",
+ signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
+ overrides: []string{"qux"},
+ aaptFlag: "",
+ logging_parent: "",
},
{
- moduleName: "bar",
- variantName: "android_common_bar",
- apkPath: "/target/product/test_device/system/app/bar/bar.apk",
- signFlag: "cert/new_cert.x509.pem cert/new_cert.pk8",
- overrides: []string{"qux", "foo"},
- aaptFlag: "",
+ moduleName: "bar",
+ variantName: "android_common_bar",
+ apkPath: "/target/product/test_device/system/app/bar/bar.apk",
+ signFlag: "cert/new_cert.x509.pem cert/new_cert.pk8",
+ overrides: []string{"qux", "foo"},
+ aaptFlag: "",
+ logging_parent: "bah",
},
{
- moduleName: "baz",
- variantName: "android_common_baz",
- apkPath: "/target/product/test_device/system/app/baz/baz.apk",
- signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
- overrides: []string{"qux", "foo"},
- aaptFlag: "--rename-manifest-package org.dandroid.bp",
+ moduleName: "baz",
+ variantName: "android_common_baz",
+ apkPath: "/target/product/test_device/system/app/baz/baz.apk",
+ signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
+ overrides: []string{"qux", "foo"},
+ aaptFlag: "--rename-manifest-package org.dandroid.bp",
+ logging_parent: "",
},
}
for _, expected := range expectedVariants {
@@ -1260,6 +1266,13 @@
expected.overrides, mod.appProperties.Overrides)
}
+ // Test Overridable property: Logging_parent
+ logging_parent := mod.aapt.LoggingParent
+ if expected.logging_parent != logging_parent {
+ t.Errorf("Incorrect overrides property value for logging parent, expected: %q, got: %q",
+ expected.logging_parent, logging_parent)
+ }
+
// Check the package renaming flag, if exists.
res := variant.Output("package-res.apk")
aapt2Flags := res.Args["flags"]
@@ -1847,42 +1860,6 @@
func TestStl(t *testing.T) {
ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
cc_library {
- name: "ndk_libunwind",
- sdk_version: "current",
- stl: "none",
- system_shared_libs: [],
- }
-
- cc_library {
- name: "libc.ndk.current",
- sdk_version: "current",
- stl: "none",
- system_shared_libs: [],
- }
-
- cc_library {
- name: "libm.ndk.current",
- sdk_version: "current",
- stl: "none",
- system_shared_libs: [],
- }
-
- cc_library {
- name: "libdl.ndk.current",
- sdk_version: "current",
- stl: "none",
- system_shared_libs: [],
- }
-
- cc_object {
- name: "ndk_crtbegin_so.27",
- }
-
- cc_object {
- name: "ndk_crtend_so.27",
- }
-
- cc_library {
name: "libjni",
sdk_version: "current",
stl: "c++_shared",
@@ -1902,10 +1879,6 @@
compile_multilib: "both",
sdk_version: "current",
}
-
- ndk_prebuilt_shared_stl {
- name: "ndk_libc++_shared",
- }
`)
testCases := []struct {
@@ -2140,6 +2113,7 @@
system_shared_libs: [],
stl: "none",
notice: "LIB_NOTICE",
+ sdk_version: "current",
}
java_library {
diff --git a/java/config/config.go b/java/config/config.go
index 7f446e5..54c89cd 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -48,7 +48,7 @@
// TODO: Could this be all updatable bootclasspath jars?
"updatable-media",
"framework-sdkextensions",
- "ike",
+ "android.net.ipsec.ike",
}
)
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index da68660..40cfe4f 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -19,6 +19,11 @@
"android/soong/dexpreopt"
)
+type dexpreopterInterface interface {
+ IsInstallable() bool // Structs that embed dexpreopter must implement this.
+ dexpreoptDisabled(ctx android.BaseModuleContext) bool
+}
+
type dexpreopter struct {
dexpreoptProperties DexpreoptProperties
@@ -26,7 +31,6 @@
uncompressedDex bool
isSDKLibrary bool
isTest bool
- isInstallable bool
isPresignedPrebuilt bool
manifestFile android.Path
@@ -58,8 +62,8 @@
}
}
-func (d *dexpreopter) dexpreoptDisabled(ctx android.ModuleContext) bool {
- global := dexpreoptGlobalConfig(ctx)
+func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
+ global := dexpreopt.GetGlobalConfig(ctx)
if global.DisablePreopt {
return true
@@ -81,7 +85,11 @@
return true
}
- if !d.isInstallable {
+ if !ctx.Module().(dexpreopterInterface).IsInstallable() {
+ return true
+ }
+
+ if ctx.Host() {
return true
}
@@ -95,43 +103,57 @@
return false
}
+func dexpreoptToolDepsMutator(ctx android.BottomUpMutatorContext) {
+ if d, ok := ctx.Module().(dexpreopterInterface); !ok || d.dexpreoptDisabled(ctx) {
+ return
+ }
+ dexpreopt.RegisterToolDeps(ctx)
+}
+
func odexOnSystemOther(ctx android.ModuleContext, installPath android.InstallPath) bool {
- return dexpreopt.OdexOnSystemOtherByName(ctx.ModuleName(), android.InstallPathToOnDevicePath(ctx, installPath), dexpreoptGlobalConfig(ctx))
+ return dexpreopt.OdexOnSystemOtherByName(ctx.ModuleName(), android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx))
}
func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.ModuleOutPath) android.ModuleOutPath {
- if d.dexpreoptDisabled(ctx) {
+ // TODO(b/148690468): The check on d.installPath is to bail out in cases where
+ // the dexpreopter struct hasn't been fully initialized before we're called,
+ // e.g. in aar.go. This keeps the behaviour that dexpreopting is effectively
+ // disabled, even if installable is true.
+ if d.dexpreoptDisabled(ctx) || d.installPath.Base() == "." {
return dexJarFile
}
- global := dexpreoptGlobalConfig(ctx)
+ globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
+ global := dexpreopt.GetGlobalConfig(ctx)
bootImage := defaultBootImageConfig(ctx)
- if global.UseApexImage {
- bootImage = frameworkJZBootImageConfig(ctx)
+ dexFiles := bootImage.dexPathsDeps.Paths()
+ dexLocations := bootImage.dexLocationsDeps
+ if global.UseArtImage {
+ bootImage = artBootImageConfig(ctx)
}
- var archs []android.ArchType
- for _, a := range ctx.MultiTargets() {
- archs = append(archs, a.Arch.ArchType)
- }
- if len(archs) == 0 {
+ targets := ctx.MultiTargets()
+ if len(targets) == 0 {
// assume this is a java library, dexpreopt for all arches for now
for _, target := range ctx.Config().Targets[android.Android] {
if target.NativeBridge == android.NativeBridgeDisabled {
- archs = append(archs, target.Arch.ArchType)
+ targets = append(targets, target)
}
}
if inList(ctx.ModuleName(), global.SystemServerJars) && !d.isSDKLibrary {
// If the module is not an SDK library and it's a system server jar, only preopt the primary arch.
- archs = archs[:1]
+ targets = targets[:1]
}
}
+ var archs []android.ArchType
var images android.Paths
var imagesDeps []android.OutputPaths
- for _, arch := range archs {
- images = append(images, bootImage.images[arch])
- imagesDeps = append(imagesDeps, bootImage.imagesDeps[arch])
+ for _, target := range targets {
+ archs = append(archs, target.Arch.ArchType)
+ variant := bootImage.getVariant(target)
+ images = append(images, variant.images)
+ imagesDeps = append(imagesDeps, variant.imagesDeps)
}
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
@@ -154,7 +176,7 @@
}
}
- dexpreoptConfig := dexpreopt.ModuleConfig{
+ dexpreoptConfig := &dexpreopt.ModuleConfig{
Name: ctx.ModuleName(),
DexLocation: dexLocation,
BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
@@ -178,8 +200,8 @@
DexPreoptImagesDeps: imagesDeps,
DexPreoptImageLocations: bootImage.imageLocations,
- PreoptBootClassPathDexFiles: bootImage.dexPathsDeps.Paths(),
- PreoptBootClassPathDexLocations: bootImage.dexLocationsDeps,
+ PreoptBootClassPathDexFiles: dexFiles,
+ PreoptBootClassPathDexLocations: dexLocations,
PreoptExtractedApk: false,
@@ -189,7 +211,7 @@
PresignedPrebuilt: d.isPresignedPrebuilt,
}
- dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, global, dexpreoptConfig)
+ dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, dexpreoptConfig)
if err != nil {
ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
return dexJarFile
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 87f6d5e..d7adb40 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -16,7 +16,6 @@
import (
"path/filepath"
- "sort"
"strings"
"android/soong/android"
@@ -48,6 +47,7 @@
// The location is passed as an argument to the ART tools like dex2oat instead of the real path. The ART tools
// will then reconstruct the real path, so the rules must have a dependency on the real path.
+// Target-independent description of pre-compiled boot image.
type bootImageConfig struct {
// Whether this image is an extension.
extension bool
@@ -67,9 +67,6 @@
// Subdirectory where the image files are installed.
installSubdir string
- // Targets for which the image is generated.
- targets []android.Target
-
// The names of jars that constitute this image.
modules []string
@@ -84,15 +81,43 @@
// The "locations" of the dependency images and in this image.
imageLocations []string
- // Paths to image files (grouped by target).
- images map[android.ArchType]android.OutputPath // first image file
- imagesDeps map[android.ArchType]android.OutputPaths // all files
-
- // Only for extensions, paths to the primary boot images (grouped by target).
- primaryImages map[android.ArchType]android.OutputPath
-
// File path to a zip archive with all image files (or nil, if not needed).
zip android.WritablePath
+
+ // Rules which should be used in make to install the outputs.
+ profileInstalls android.RuleBuilderInstalls
+
+ // Target-dependent fields.
+ variants []*bootImageVariant
+}
+
+// Target-dependent description of pre-compiled boot image.
+type bootImageVariant struct {
+ *bootImageConfig
+
+ // Target for which the image is generated.
+ target android.Target
+
+ // Paths to image files.
+ images android.OutputPath // first image file
+ imagesDeps android.OutputPaths // all files
+
+ // Only for extensions, paths to the primary boot images.
+ primaryImages android.OutputPath
+
+ // Rules which should be used in make to install the outputs.
+ installs android.RuleBuilderInstalls
+ vdexInstalls android.RuleBuilderInstalls
+ unstrippedInstalls android.RuleBuilderInstalls
+}
+
+func (image bootImageConfig) getVariant(target android.Target) *bootImageVariant {
+ for _, variant := range image.variants {
+ if variant.target.Os == target.Os && variant.target.Arch.ArchType == target.Arch.ArchType {
+ return variant
+ }
+ }
+ return nil
}
func (image bootImageConfig) moduleName(idx int) string {
@@ -126,28 +151,6 @@
return ret
}
-type bootImage struct {
- bootImageConfig
-
- installs map[android.ArchType]android.RuleBuilderInstalls
- vdexInstalls map[android.ArchType]android.RuleBuilderInstalls
- unstrippedInstalls map[android.ArchType]android.RuleBuilderInstalls
-
- profileInstalls android.RuleBuilderInstalls
-}
-
-func newBootImage(ctx android.PathContext, config bootImageConfig) *bootImage {
- image := &bootImage{
- bootImageConfig: config,
-
- installs: make(map[android.ArchType]android.RuleBuilderInstalls),
- vdexInstalls: make(map[android.ArchType]android.RuleBuilderInstalls),
- unstrippedInstalls: make(map[android.ArchType]android.RuleBuilderInstalls),
- }
-
- return image
-}
-
func concat(lists ...[]string) []string {
var size int
for _, l := range lists {
@@ -165,7 +168,7 @@
}
func skipDexpreoptBootJars(ctx android.PathContext) bool {
- if dexpreoptGlobalConfig(ctx).DisablePreopt {
+ if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
return true
}
@@ -182,8 +185,8 @@
}
type dexpreoptBootJars struct {
- defaultBootImage *bootImage
- otherImages []*bootImage
+ defaultBootImage *bootImageConfig
+ otherImages []*bootImageConfig
dexpreoptConfigForMake android.WritablePath
}
@@ -193,17 +196,11 @@
if skipDexpreoptBootJars(ctx) {
return nil
}
-
// Include dexpreopt files for the primary boot image.
- files := artBootImageConfig(ctx).imagesDeps
-
- // For JIT-zygote config, also include dexpreopt files for the primary JIT-zygote image.
- if dexpreoptGlobalConfig(ctx).UseApexImage {
- for arch, paths := range artJZBootImageConfig(ctx).imagesDeps {
- files[arch] = append(files[arch], paths...)
- }
+ files := map[android.ArchType]android.OutputPaths{}
+ for _, variant := range artBootImageConfig(ctx).variants {
+ files[variant.target.Arch.ArchType] = variant.imagesDeps
}
-
return files
}
@@ -212,11 +209,15 @@
if skipDexpreoptBootJars(ctx) {
return
}
+ if dexpreopt.GetCachedGlobalSoongConfig(ctx) == nil {
+ // No module has enabled dexpreopting, so we assume there will be no boot image to make.
+ return
+ }
d.dexpreoptConfigForMake = android.PathForOutput(ctx, ctx.Config().DeviceName(), "dexpreopt.config")
writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
- global := dexpreoptGlobalConfig(ctx)
+ global := dexpreopt.GetGlobalConfig(ctx)
// Skip recompiling the boot image for the second sanitization phase. We'll get separate paths
// and invalidate first-stage artifacts which are crucial to SANITIZE_LITE builds.
@@ -232,19 +233,12 @@
d.defaultBootImage = buildBootImage(ctx, defaultBootImageConfig(ctx))
// Create boot image for the ART apex (build artifacts are accessed via the global boot image config).
d.otherImages = append(d.otherImages, buildBootImage(ctx, artBootImageConfig(ctx)))
- if global.GenerateApexImage {
- // Create boot images for the JIT-zygote experiment.
- d.otherImages = append(d.otherImages, buildBootImage(ctx, artJZBootImageConfig(ctx)))
- d.otherImages = append(d.otherImages, buildBootImage(ctx, frameworkJZBootImageConfig(ctx)))
- }
dumpOatRules(ctx, d.defaultBootImage)
}
-// buildBootImage takes a bootImageConfig, creates rules to build it, and returns a *bootImage.
-func buildBootImage(ctx android.SingletonContext, config bootImageConfig) *bootImage {
- image := newBootImage(ctx, config)
-
+// buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
+func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig {
bootDexJars := make(android.Paths, len(image.modules))
ctx.VisitAllModules(func(module android.Module) {
// Collect dex jar paths for the modules listed above.
@@ -285,8 +279,8 @@
bootFrameworkProfileRule(ctx, image, missingDeps)
var allFiles android.Paths
- for _, target := range image.targets {
- files := buildBootImageRuleForArch(ctx, image, target.Arch.ArchType, profile, missingDeps)
+ for _, variant := range image.variants {
+ files := buildBootImageVariant(ctx, variant, profile, missingDeps)
allFiles = append(allFiles, files.Paths()...)
}
@@ -304,11 +298,13 @@
return image
}
-func buildBootImageRuleForArch(ctx android.SingletonContext, image *bootImage,
- arch android.ArchType, profile android.Path, missingDeps []string) android.WritablePaths {
+func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant,
+ profile android.Path, missingDeps []string) android.WritablePaths {
- global := dexpreoptGlobalConfig(ctx)
+ globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
+ global := dexpreopt.GetGlobalConfig(ctx)
+ arch := image.target.Arch.ArchType
symbolsDir := image.symbolsDir.Join(ctx, image.installSubdir, arch.String())
symbolsFile := symbolsDir.Join(ctx, image.stem+".oat")
outputDir := image.dir.Join(ctx, image.installSubdir, arch.String())
@@ -342,7 +338,7 @@
invocationPath := outputPath.ReplaceExtension(ctx, "invocation")
- cmd.Tool(global.SoongConfig.Dex2oat).
+ cmd.Tool(globalSoong.Dex2oat).
Flag("--avoid-storing-invocation").
FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatImageXms).
@@ -358,7 +354,7 @@
}
if image.extension {
- artImage := image.primaryImages[arch]
+ artImage := image.primaryImages
cmd.
Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", image.dexLocationsDeps, ":").
@@ -433,9 +429,9 @@
rule.Build(pctx, ctx, image.name+"JarsDexpreopt_"+arch.String(), "dexpreopt "+image.name+" jars "+arch.String())
// save output and installed files for makevars
- image.installs[arch] = rule.Installs()
- image.vdexInstalls[arch] = vdexInstalls
- image.unstrippedInstalls[arch] = unstrippedInstalls
+ image.installs = rule.Installs()
+ image.vdexInstalls = vdexInstalls
+ image.unstrippedInstalls = unstrippedInstalls
return zipFiles
}
@@ -444,8 +440,9 @@
It is likely that the boot classpath is inconsistent.
Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.`
-func bootImageProfileRule(ctx android.SingletonContext, image *bootImage, missingDeps []string) android.WritablePath {
- global := dexpreoptGlobalConfig(ctx)
+func bootImageProfileRule(ctx android.SingletonContext, image *bootImageConfig, missingDeps []string) android.WritablePath {
+ globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
+ global := dexpreopt.GetGlobalConfig(ctx)
if global.DisableGenerateProfile || ctx.Config().IsPdkBuild() || ctx.Config().UnbundledBuild() {
return nil
@@ -476,7 +473,7 @@
rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
- Tool(global.SoongConfig.Profman).
+ Tool(globalSoong.Profman).
FlagWithInput("--create-profile-from=", bootImageProfile).
FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
FlagForEachArg("--dex-location=", image.dexLocationsDeps).
@@ -498,8 +495,9 @@
var bootImageProfileRuleKey = android.NewOnceKey("bootImageProfileRule")
-func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImage, missingDeps []string) android.WritablePath {
- global := dexpreoptGlobalConfig(ctx)
+func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImageConfig, missingDeps []string) android.WritablePath {
+ globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
+ global := dexpreopt.GetGlobalConfig(ctx)
if global.DisableGenerateProfile || ctx.Config().IsPdkBuild() || ctx.Config().UnbundledBuild() {
return nil
@@ -525,7 +523,7 @@
rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
- Tool(global.SoongConfig.Profman).
+ Tool(globalSoong.Profman).
Flag("--generate-boot-profile").
FlagWithInput("--create-profile-from=", bootFrameworkProfile).
FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
@@ -542,15 +540,10 @@
var bootFrameworkProfileRuleKey = android.NewOnceKey("bootFrameworkProfileRule")
-func dumpOatRules(ctx android.SingletonContext, image *bootImage) {
- var archs []android.ArchType
- for arch := range image.images {
- archs = append(archs, arch)
- }
- sort.Slice(archs, func(i, j int) bool { return archs[i].String() < archs[j].String() })
-
+func dumpOatRules(ctx android.SingletonContext, image *bootImageConfig) {
var allPhonies android.Paths
- for _, arch := range archs {
+ for _, image := range image.variants {
+ arch := image.target.Arch.ArchType
// Create a rule to call oatdump.
output := android.PathForOutput(ctx, "boot."+arch.String()+".oatdump.txt")
rule := android.NewRuleBuilder()
@@ -559,7 +552,7 @@
BuiltTool(ctx, "oatdumpd").
FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":").
- FlagWithArg("--image=", strings.Join(image.imageLocations, ":")).Implicits(image.imagesDeps[arch].Paths()).
+ FlagWithArg("--image=", strings.Join(image.imageLocations, ":")).Implicits(image.imagesDeps.Paths()).
FlagWithOutput("--output=", output).
FlagWithArg("--instruction-set=", arch.String())
rule.Build(pctx, ctx, "dump-oat-boot-"+arch.String(), "dump oat boot "+arch.String())
@@ -587,7 +580,7 @@
}
func writeGlobalConfigForMake(ctx android.SingletonContext, path android.WritablePath) {
- data := dexpreoptGlobalConfigRaw(ctx).data
+ data := dexpreopt.GetGlobalConfigRawData(ctx)
ctx.Build(pctx, android.BuildParams{
Rule: android.WriteFile,
@@ -614,20 +607,13 @@
var imageNames []string
for _, current := range append(d.otherImages, image) {
imageNames = append(imageNames, current.name)
- var arches []android.ArchType
- for arch, _ := range current.images {
- arches = append(arches, arch)
- }
-
- sort.Slice(arches, func(i, j int) bool { return arches[i].String() < arches[j].String() })
-
- for _, arch := range arches {
- sfx := current.name + "_" + arch.String()
- ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, current.vdexInstalls[arch].String())
- ctx.Strict("DEXPREOPT_IMAGE_"+sfx, current.images[arch].String())
- ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(current.imagesDeps[arch].Strings(), " "))
- ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, current.installs[arch].String())
- ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, current.unstrippedInstalls[arch].String())
+ for _, current := range current.variants {
+ sfx := current.name + "_" + current.target.Arch.ArchType.String()
+ ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, current.vdexInstalls.String())
+ ctx.Strict("DEXPREOPT_IMAGE_"+sfx, current.images.String())
+ ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(current.imagesDeps.Strings(), " "))
+ ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, current.installs.String())
+ ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, current.unstrippedInstalls.String())
}
ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(current.imageLocations, ":"))
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 4ce30f6..c3b2133 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -49,7 +49,7 @@
pathCtx := android.PathContextForTesting(config)
dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
dexpreoptConfig.BootJars = []string{"foo", "bar", "baz"}
- setDexpreoptTestGlobalConfig(config, dexpreoptConfig)
+ dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
ctx := testContext()
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 637a32f..a06aec4 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -15,6 +15,7 @@
package java
import (
+ "fmt"
"path/filepath"
"strings"
@@ -22,67 +23,36 @@
"android/soong/dexpreopt"
)
-// dexpreoptGlobalConfig returns the global dexpreopt.config. It is loaded once the first time it is called for any
-// ctx.Config(), and returns the same data for all future calls with the same ctx.Config(). A value can be inserted
-// for tests using setDexpreoptTestGlobalConfig.
-func dexpreoptGlobalConfig(ctx android.PathContext) dexpreopt.GlobalConfig {
- return dexpreoptGlobalConfigRaw(ctx).global
-}
-
-type globalConfigAndRaw struct {
- global dexpreopt.GlobalConfig
- data []byte
-}
-
-func dexpreoptGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw {
- return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} {
- if data, err := ctx.Config().DexpreoptGlobalConfig(ctx); err != nil {
- panic(err)
- } else if data != nil {
- soongConfig := dexpreopt.CreateGlobalSoongConfig(ctx)
- globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, data, soongConfig)
- if err != nil {
- panic(err)
- }
- return globalConfigAndRaw{globalConfig, data}
- }
-
- // No global config filename set, see if there is a test config set
- return ctx.Config().Once(dexpreoptTestGlobalConfigKey, func() interface{} {
- // Nope, return a config with preopting disabled
- return globalConfigAndRaw{dexpreopt.GlobalConfig{
- DisablePreopt: true,
- DisableGenerateProfile: true,
- }, nil}
- })
- }).(globalConfigAndRaw)
-}
-
-// setDexpreoptTestGlobalConfig sets a GlobalConfig that future calls to dexpreoptGlobalConfig will return. It must
-// be called before the first call to dexpreoptGlobalConfig for the config.
-func setDexpreoptTestGlobalConfig(config android.Config, globalConfig dexpreopt.GlobalConfig) {
- config.Once(dexpreoptTestGlobalConfigKey, func() interface{} { return globalConfigAndRaw{globalConfig, nil} })
-}
-
-var dexpreoptGlobalConfigKey = android.NewOnceKey("DexpreoptGlobalConfig")
-var dexpreoptTestGlobalConfigKey = android.NewOnceKey("TestDexpreoptGlobalConfig")
-
// systemServerClasspath returns the on-device locations of the modules in the system server classpath. It is computed
// once the first time it is called for any ctx.Config(), and returns the same slice for all future calls with the same
// ctx.Config().
-func systemServerClasspath(ctx android.PathContext) []string {
+func systemServerClasspath(ctx android.MakeVarsContext) []string {
return ctx.Config().OnceStringSlice(systemServerClasspathKey, func() []string {
- global := dexpreoptGlobalConfig(ctx)
-
+ global := dexpreopt.GetGlobalConfig(ctx)
var systemServerClasspathLocations []string
- for _, m := range global.SystemServerJars {
+ var dexpreoptJars = *DexpreoptedSystemServerJars(ctx.Config())
+ // 1) The jars that are dexpreopted.
+ for _, m := range dexpreoptJars {
systemServerClasspathLocations = append(systemServerClasspathLocations,
filepath.Join("/system/framework", m+".jar"))
}
+ // 2) The jars that are from an updatable apex.
for _, m := range global.UpdatableSystemServerJars {
systemServerClasspathLocations = append(systemServerClasspathLocations,
dexpreopt.GetJarLocationFromApexJarPair(m))
}
+ // 3) The jars from make (which are not updatable, not preopted).
+ for _, m := range dexpreopt.NonUpdatableSystemServerJars(ctx, global) {
+ if !android.InList(m, dexpreoptJars) {
+ systemServerClasspathLocations = append(systemServerClasspathLocations,
+ filepath.Join("/system/framework", m+".jar"))
+ }
+ }
+ if len(systemServerClasspathLocations) != len(global.SystemServerJars)+len(global.UpdatableSystemServerJars) {
+ panic(fmt.Errorf("Wrong number of system server jars, got %d, expected %d",
+ len(systemServerClasspathLocations),
+ len(global.SystemServerJars)+len(global.UpdatableSystemServerJars)))
+ }
return systemServerClasspathLocations
})
}
@@ -112,28 +82,17 @@
return moduleName
}
-func getJarsFromApexJarPairs(apexJarPairs []string) []string {
- modules := make([]string, len(apexJarPairs))
- for i, p := range apexJarPairs {
- _, jar := dexpreopt.SplitApexJarPair(p)
- modules[i] = jar
- }
- return modules
-}
-
var (
- bootImageConfigKey = android.NewOnceKey("bootImageConfig")
- artBootImageName = "art"
- frameworkBootImageName = "boot"
- artJZBootImageName = "jitzygote-art"
- frameworkJZBootImageName = "jitzygote-boot"
+ bootImageConfigKey = android.NewOnceKey("bootImageConfig")
+ artBootImageName = "art"
+ frameworkBootImageName = "boot"
)
// Construct the global boot image configs.
func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
return ctx.Config().Once(bootImageConfigKey, func() interface{} {
- global := dexpreoptGlobalConfig(ctx)
+ global := dexpreopt.GetGlobalConfig(ctx)
targets := dexpreoptTargets(ctx)
deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName())
@@ -143,7 +102,7 @@
artModules = append(artModules, "jacocoagent")
}
frameworkModules := android.RemoveListFromList(global.BootJars,
- concat(artModules, getJarsFromApexJarPairs(global.UpdatableBootJars)))
+ concat(artModules, dexpreopt.GetJarsFromApexJarPairs(global.UpdatableBootJars)))
artSubdir := "apex/com.android.art/javalib"
frameworkSubdir := "system/framework"
@@ -180,39 +139,13 @@
dexLocationsDeps: append(artLocations, frameworkLocations...),
}
- // ART config for JIT-zygote boot image.
- artJZCfg := bootImageConfig{
- extension: false,
- name: artJZBootImageName,
- stem: "apex",
- installSubdir: artSubdir,
- modules: artModules,
- dexLocations: artLocations,
- dexLocationsDeps: artLocations,
- }
-
- // Framework config for JIT-zygote boot image extension.
- frameworkJZCfg := bootImageConfig{
- extension: true,
- name: frameworkJZBootImageName,
- stem: "apex",
- installSubdir: frameworkSubdir,
- modules: frameworkModules,
- dexLocations: frameworkLocations,
- dexLocationsDeps: append(artLocations, frameworkLocations...),
- }
-
configs := map[string]*bootImageConfig{
- artBootImageName: &artCfg,
- frameworkBootImageName: &frameworkCfg,
- artJZBootImageName: &artJZCfg,
- frameworkJZBootImageName: &frameworkJZCfg,
+ artBootImageName: &artCfg,
+ frameworkBootImageName: &frameworkCfg,
}
// common to all configs
for _, c := range configs {
- c.targets = targets
-
c.dir = deviceDir.Join(ctx, "dex_"+c.name+"jars")
c.symbolsDir = deviceDir.Join(ctx, "dex_"+c.name+"jars_unstripped")
@@ -231,14 +164,17 @@
}
c.dexPathsDeps = c.dexPaths
- c.images = make(map[android.ArchType]android.OutputPath)
- c.imagesDeps = make(map[android.ArchType]android.OutputPaths)
-
+ // Create target-specific variants.
for _, target := range targets {
arch := target.Arch.ArchType
imageDir := c.dir.Join(ctx, c.installSubdir, arch.String())
- c.images[arch] = imageDir.Join(ctx, imageName)
- c.imagesDeps[arch] = c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex")
+ variant := &bootImageVariant{
+ bootImageConfig: c,
+ target: target,
+ images: imageDir.Join(ctx, imageName),
+ imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"),
+ }
+ c.variants = append(c.variants, variant)
}
c.zip = c.dir.Join(ctx, c.name+".zip")
@@ -246,37 +182,26 @@
// specific to the framework config
frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...)
- frameworkCfg.primaryImages = artCfg.images
+ for i := range targets {
+ frameworkCfg.variants[i].primaryImages = artCfg.variants[i].images
+ }
frameworkCfg.imageLocations = append(artCfg.imageLocations, frameworkCfg.imageLocations...)
- // specific to the jitzygote-framework config
- frameworkJZCfg.dexPathsDeps = append(artJZCfg.dexPathsDeps, frameworkJZCfg.dexPathsDeps...)
- frameworkJZCfg.primaryImages = artJZCfg.images
- frameworkJZCfg.imageLocations = append(artJZCfg.imageLocations, frameworkJZCfg.imageLocations...)
-
return configs
}).(map[string]*bootImageConfig)
}
-func artBootImageConfig(ctx android.PathContext) bootImageConfig {
- return *genBootImageConfigs(ctx)[artBootImageName]
+func artBootImageConfig(ctx android.PathContext) *bootImageConfig {
+ return genBootImageConfigs(ctx)[artBootImageName]
}
-func defaultBootImageConfig(ctx android.PathContext) bootImageConfig {
- return *genBootImageConfigs(ctx)[frameworkBootImageName]
-}
-
-func artJZBootImageConfig(ctx android.PathContext) bootImageConfig {
- return *genBootImageConfigs(ctx)[artJZBootImageName]
-}
-
-func frameworkJZBootImageConfig(ctx android.PathContext) bootImageConfig {
- return *genBootImageConfigs(ctx)[frameworkJZBootImageName]
+func defaultBootImageConfig(ctx android.PathContext) *bootImageConfig {
+ return genBootImageConfigs(ctx)[frameworkBootImageName]
}
func defaultBootclasspath(ctx android.PathContext) []string {
return ctx.Config().OnceStringSlice(defaultBootclasspathKey, func() []string {
- global := dexpreoptGlobalConfig(ctx)
+ global := dexpreopt.GetGlobalConfig(ctx)
image := defaultBootImageConfig(ctx)
updatableBootclasspath := make([]string, len(global.UpdatableBootJars))
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 098400b..5437499 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -534,6 +534,9 @@
ctx.AddMissingDependencies(sdkDep.java9Classpath)
} else if sdkDep.useFiles {
deps.bootClasspath = append(deps.bootClasspath, sdkDep.jars...)
+ deps.aidlPreprocess = sdkDep.aidl
+ } else {
+ deps.aidlPreprocess = sdkDep.aidl
}
ctx.VisitDirectDeps(func(module android.Module) {
@@ -544,10 +547,10 @@
case bootClasspathTag:
if dep, ok := module.(Dependency); ok {
deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars()...)
- } else if sm, ok := module.(*SystemModules); ok {
+ } else if sm, ok := module.(SystemModulesProvider); ok {
// A system modules dependency has been added to the bootclasspath
// so add its libs to the bootclasspath.
- deps.bootClasspath = append(deps.bootClasspath, sm.headerJars...)
+ deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars()...)
} else {
panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
}
@@ -575,11 +578,9 @@
if deps.systemModules != nil {
panic("Found two system module dependencies")
}
- sm := module.(*SystemModules)
- if sm.outputDir == nil && len(sm.outputDeps) == 0 {
- panic("Missing directory for system module dependency")
- }
- deps.systemModules = &systemModules{sm.outputDir, sm.outputDeps}
+ sm := module.(SystemModulesProvider)
+ outputDir, outputDeps := sm.OutputDirAndDeps()
+ deps.systemModules = &systemModules{outputDir, outputDeps}
}
})
// do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
@@ -602,11 +603,8 @@
continue
}
packageName := strings.ReplaceAll(filepath.Dir(src.Rel()), "/", ".")
- for _, pkg := range filterPackages {
- if strings.HasPrefix(packageName, pkg) {
- filtered = append(filtered, src)
- break
- }
+ if android.HasAnyPrefix(packageName, filterPackages) {
+ filtered = append(filtered, src)
}
}
return filtered
@@ -775,6 +773,7 @@
}
func (d *Droiddoc) doclavaDocsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, docletPath classpath) {
+ buildNumberFile := ctx.Config().BuildNumberFile(ctx)
// Droiddoc always gets "-source 1.8" because it doesn't support 1.9 sources. For modules with 1.9
// sources, droiddoc will get sources produced by metalava which will have already stripped out the
// 1.9 language features.
@@ -784,7 +783,7 @@
Flag("-XDignore.symbol.file").
FlagWithArg("-doclet ", "com.google.doclava.Doclava").
FlagWithInputList("-docletpath ", docletPath.Paths(), ":").
- FlagWithArg("-hdf page.build ", ctx.Config().BuildId()+"-"+ctx.Config().BuildNumberFromFile()).
+ FlagWithArg("-hdf page.build ", ctx.Config().BuildId()+"-$(cat "+buildNumberFile.String()+")").OrderOnly(buildNumberFile).
FlagWithArg("-hdf page.now ", `"$(date -d @$(cat `+ctx.Config().Getenv("BUILD_DATETIME_FILE")+`) "+%d %b %Y %k:%M")" `)
if String(d.properties.Custom_template) == "" {
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 6020aba..884a757 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -28,9 +28,10 @@
}, "outFlag", "stubAPIFlags")
type hiddenAPI struct {
- flagsCSVPath android.Path
- metadataCSVPath android.Path
bootDexJarPath android.Path
+ flagsCSVPath android.Path
+ indexCSVPath android.Path
+ metadataCSVPath android.Path
}
func (h *hiddenAPI) flagsCSV() android.Path {
@@ -45,17 +46,21 @@
return h.bootDexJarPath
}
+func (h *hiddenAPI) indexCSV() android.Path {
+ return h.indexCSVPath
+}
+
type hiddenAPIIntf interface {
- flagsCSV() android.Path
- metadataCSV() android.Path
bootDexJar() android.Path
+ flagsCSV() android.Path
+ indexCSV() android.Path
+ metadataCSV() android.Path
}
var _ hiddenAPIIntf = (*hiddenAPI)(nil)
-func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, dexJar android.ModuleOutPath, implementationJar android.Path,
- uncompressDex bool) android.ModuleOutPath {
-
+func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, dexJar android.ModuleOutPath,
+ implementationJar android.Path, uncompressDex bool) android.ModuleOutPath {
if !ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
name := ctx.ModuleName()
@@ -77,9 +82,8 @@
// Derive the greylist from classes jar.
flagsCSV := android.PathForModuleOut(ctx, "hiddenapi", "flags.csv")
metadataCSV := android.PathForModuleOut(ctx, "hiddenapi", "metadata.csv")
- hiddenAPIGenerateCSV(ctx, flagsCSV, metadataCSV, implementationJar)
- h.flagsCSVPath = flagsCSV
- h.metadataCSVPath = metadataCSV
+ indexCSV := android.PathForModuleOut(ctx, "hiddenapi", "index.csv")
+ h.hiddenAPIGenerateCSV(ctx, flagsCSV, metadataCSV, indexCSV, implementationJar)
// If this module is actually on the boot jars list and not providing
// hiddenapi information for a module on the boot jars list then encode
@@ -96,9 +100,7 @@
return dexJar
}
-func hiddenAPIGenerateCSV(ctx android.ModuleContext, flagsCSV, metadataCSV android.WritablePath,
- classesJar android.Path) {
-
+func (h *hiddenAPI) hiddenAPIGenerateCSV(ctx android.ModuleContext, flagsCSV, metadataCSV, indexCSV android.WritablePath, classesJar android.Path) {
stubFlagsCSV := hiddenAPISingletonPaths(ctx).stubFlags
ctx.Build(pctx, android.BuildParams{
@@ -112,6 +114,7 @@
"stubAPIFlags": stubFlagsCSV.String(),
},
})
+ h.flagsCSVPath = flagsCSV
ctx.Build(pctx, android.BuildParams{
Rule: hiddenAPIGenerateCSVRule,
@@ -124,18 +127,26 @@
"stubAPIFlags": stubFlagsCSV.String(),
},
})
+ h.metadataCSVPath = metadataCSV
+ rule := android.NewRuleBuilder()
+ rule.Command().
+ BuiltTool(ctx, "merge_csv").
+ FlagWithInput("--zip_input=", classesJar).
+ FlagWithOutput("--output=", indexCSV)
+ rule.Build(pctx, ctx, "merged-hiddenapi-index", "Merged Hidden API index")
+ h.indexCSVPath = indexCSV
}
var hiddenAPIEncodeDexRule = pctx.AndroidStaticRule("hiddenAPIEncodeDex", blueprint.RuleParams{
- Command: `rm -rf $tmpDir && mkdir -p $tmpDir && mkdir $tmpDir/dex-input && mkdir $tmpDir/dex-output && ` +
- `unzip -o -q $in 'classes*.dex' -d $tmpDir/dex-input && ` +
- `for INPUT_DEX in $$(find $tmpDir/dex-input -maxdepth 1 -name 'classes*.dex' | sort); do ` +
- ` echo "--input-dex=$${INPUT_DEX}"; ` +
- ` echo "--output-dex=$tmpDir/dex-output/$$(basename $${INPUT_DEX})"; ` +
- `done | xargs ${config.HiddenAPI} encode --api-flags=$flagsCsv $hiddenapiFlags && ` +
- `${config.SoongZipCmd} $soongZipFlags -o $tmpDir/dex.jar -C $tmpDir/dex-output -f "$tmpDir/dex-output/classes*.dex" && ` +
- `${config.MergeZipsCmd} -D -zipToNotStrip $tmpDir/dex.jar -stripFile "classes*.dex" $out $tmpDir/dex.jar $in`,
+ Command: `rm -rf $tmpDir && mkdir -p $tmpDir && mkdir $tmpDir/dex-input && mkdir $tmpDir/dex-output &&
+ unzip -o -q $in 'classes*.dex' -d $tmpDir/dex-input &&
+ for INPUT_DEX in $$(find $tmpDir/dex-input -maxdepth 1 -name 'classes*.dex' | sort); do
+ echo "--input-dex=$${INPUT_DEX}";
+ echo "--output-dex=$tmpDir/dex-output/$$(basename $${INPUT_DEX})";
+ done | xargs ${config.HiddenAPI} encode --api-flags=$flagsCsv $hiddenapiFlags &&
+ ${config.SoongZipCmd} $soongZipFlags -o $tmpDir/dex.jar -C $tmpDir/dex-output -f "$tmpDir/dex-output/classes*.dex" &&
+ ${config.MergeZipsCmd} -D -zipToNotStrip $tmpDir/dex.jar -stripFile "classes*.dex" -stripFile "**/*.uau" $out $tmpDir/dex.jar $in`,
CommandDeps: []string{
"${config.HiddenAPI}",
"${config.SoongZipCmd}",
@@ -159,9 +170,21 @@
tmpOutput = android.PathForModuleOut(ctx, "hiddenapi", "unaligned", "unaligned.jar")
tmpDir = android.PathForModuleOut(ctx, "hiddenapi", "unaligned")
}
+
+ enforceHiddenApiFlagsToAllMembers := true
// If frameworks/base doesn't exist we must be building with the 'master-art' manifest.
// Disable assertion that all methods/fields have hidden API flags assigned.
if !ctx.Config().FrameworksBaseDirExists(ctx) {
+ enforceHiddenApiFlagsToAllMembers = false
+ }
+ // b/149353192: when a module is instrumented, jacoco adds synthetic members
+ // $jacocoData and $jacocoInit. Since they don't exist when building the hidden API flags,
+ // don't complain when we don't find hidden API flags for the synthetic members.
+ if j, ok := ctx.Module().(*Library); ok && j.shouldInstrument(ctx) {
+ enforceHiddenApiFlagsToAllMembers = false
+ }
+
+ if !enforceHiddenApiFlagsToAllMembers {
hiddenapiFlags = "--no-force-assign-all"
}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 3243e43..7e7e955 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -22,13 +22,15 @@
func init() {
android.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
+ android.RegisterSingletonType("hiddenapi_index", hiddenAPIIndexSingletonFactory)
android.RegisterModuleType("hiddenapi_flags", hiddenAPIFlagsFactory)
}
type hiddenAPISingletonPathsStruct struct {
- stubFlags android.OutputPath
flags android.OutputPath
+ index android.OutputPath
metadata android.OutputPath
+ stubFlags android.OutputPath
}
var hiddenAPISingletonPathsKey = android.NewOnceKey("hiddenAPISingletonPathsKey")
@@ -39,9 +41,10 @@
func hiddenAPISingletonPaths(ctx android.PathContext) hiddenAPISingletonPathsStruct {
return ctx.Config().Once(hiddenAPISingletonPathsKey, func() interface{} {
return hiddenAPISingletonPathsStruct{
- stubFlags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-stub-flags.txt"),
flags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-flags.csv"),
+ index: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-index.csv"),
metadata: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-greylist.csv"),
+ stubFlags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-stub-flags.txt"),
}
}).(hiddenAPISingletonPathsStruct)
}
@@ -294,9 +297,8 @@
rule.Command().
BuiltTool(ctx, "merge_csv").
- Inputs(metadataCSV).
- Text(">").
- Output(outputPath)
+ FlagWithOutput("--output=", outputPath).
+ Inputs(metadataCSV)
rule.Build(pctx, ctx, "hiddenAPIGreylistMetadataFile", "hiddenapi greylist metadata")
@@ -365,3 +367,45 @@
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
return module
}
+
+func hiddenAPIIndexSingletonFactory() android.Singleton {
+ return &hiddenAPIIndexSingleton{}
+}
+
+type hiddenAPIIndexSingleton struct {
+ index android.Path
+}
+
+func (h *hiddenAPIIndexSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ // Don't run any hiddenapi rules if UNSAFE_DISABLE_HIDDENAPI_FLAGS=true
+ if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ return
+ }
+
+ indexes := android.Paths{}
+ ctx.VisitAllModules(func(module android.Module) {
+ if h, ok := module.(hiddenAPIIntf); ok {
+ if h.indexCSV() != nil {
+ indexes = append(indexes, h.indexCSV())
+ }
+ }
+ })
+
+ rule := android.NewRuleBuilder()
+ rule.Command().
+ BuiltTool(ctx, "merge_csv").
+ FlagWithArg("--header=", "signature,file,startline,startcol,endline,endcol,properties").
+ FlagWithOutput("--output=", hiddenAPISingletonPaths(ctx).index).
+ Inputs(indexes)
+ rule.Build(pctx, ctx, "singleton-merged-hiddenapi-index", "Singleton merged Hidden API index")
+
+ h.index = hiddenAPISingletonPaths(ctx).index
+}
+
+func (h *hiddenAPIIndexSingleton) MakeVars(ctx android.MakeVarsContext) {
+ if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ return
+ }
+
+ ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_INDEX", h.index.String())
+}
diff --git a/java/java.go b/java/java.go
index ed3dca9..8d58a90 100644
--- a/java/java.go
+++ b/java/java.go
@@ -23,12 +23,14 @@
"path/filepath"
"strconv"
"strings"
+ "sync"
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/dexpreopt"
"android/soong/java/config"
"android/soong/tradefed"
)
@@ -37,14 +39,7 @@
RegisterJavaBuildComponents(android.InitRegistrationContext)
// Register sdk member types.
- android.RegisterSdkMemberType(&headerLibrarySdkMemberType{
- librarySdkMemberType{
- android.SdkMemberTypeBase{
- PropertyName: "java_header_libs",
- SupportsSdk: true,
- },
- },
- })
+ android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
android.RegisterSdkMemberType(&implLibrarySdkMemberType{
librarySdkMemberType{
@@ -59,6 +54,8 @@
PropertyName: "java_tests",
},
})
+
+ android.PostDepsMutators(RegisterPostDepsMutators)
}
func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
@@ -79,10 +76,52 @@
ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
ctx.RegisterModuleType("dex_import", DexImportFactory)
+ ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator).Parallel()
+ })
+
ctx.RegisterSingletonType("logtags", LogtagsSingleton)
ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
}
+func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("ordered_system_server_jars", systemServerJarsDepsMutator)
+}
+
+var (
+ dexpreoptedSystemServerJarsKey = android.NewOnceKey("dexpreoptedSystemServerJars")
+ dexpreoptedSystemServerJarsLock sync.Mutex
+)
+
+func DexpreoptedSystemServerJars(config android.Config) *[]string {
+ return config.Once(dexpreoptedSystemServerJarsKey, func() interface{} {
+ return &[]string{}
+ }).(*[]string)
+}
+
+// A PostDepsMutator pass that enforces total order on non-updatable system server jars. A total
+// order is neededed because such jars must be dexpreopted together (each jar on the list must have
+// all preceding jars in its class loader context). The total order must be compatible with the
+// partial order imposed by genuine dependencies between system server jars (which is not always
+// respected by the PRODUCT_SYSTEM_SERVER_JARS variable).
+//
+// An earlier mutator pass creates genuine dependencies, and this pass traverses the jars in that
+// order (which is partial and non-deterministic). This pass adds additional dependencies between
+// jars, making the order total and deterministic. It also constructs a global ordered list.
+func systemServerJarsDepsMutator(ctx android.BottomUpMutatorContext) {
+ jars := dexpreopt.NonUpdatableSystemServerJars(ctx, dexpreopt.GetGlobalConfig(ctx))
+ name := ctx.ModuleName()
+ if android.InList(name, jars) {
+ dexpreoptedSystemServerJarsLock.Lock()
+ defer dexpreoptedSystemServerJarsLock.Unlock()
+ jars := DexpreoptedSystemServerJars(ctx.Config())
+ for _, dep := range *jars {
+ ctx.AddDependency(ctx.Module(), dexpreopt.SystemServerDepTag, dep)
+ }
+ *jars = append(*jars, name)
+ }
+}
+
func (j *Module) checkSdkVersion(ctx android.ModuleContext) {
if j.SocSpecific() || j.DeviceSpecific() ||
(j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
@@ -666,6 +705,11 @@
} else if j.shouldInstrumentStatic(ctx) {
ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
}
+
+ // services depend on com.android.location.provider, but dependency in not registered in a Blueprint file
+ if ctx.ModuleName() == "services" {
+ ctx.AddDependency(ctx.Module(), dexpreopt.SystemServerForcedDepTag, "com.android.location.provider")
+ }
}
func hasSrcExt(srcs []string, ext string) bool {
@@ -757,9 +801,13 @@
type linkType int
const (
+ // TODO(jiyong) rename these for better readability. Make the allowed
+ // and disallowed link types explicit
javaCore linkType = iota
javaSdk
javaSystem
+ javaModule
+ javaSystemServer
javaPlatform
)
@@ -789,6 +837,14 @@
return javaSdk, true
case ver.kind == sdkPublic:
return javaSdk, false
+ case name == "android_module_lib_stubs_current":
+ return javaModule, true
+ case ver.kind == sdkModule:
+ return javaModule, false
+ case name == "services-stubs":
+ return javaSystemServer, true
+ case ver.kind == sdkSystemServer:
+ return javaSystemServer, false
case ver.kind == sdkPrivate || ver.kind == sdkNone || ver.kind == sdkCorePlatform:
return javaPlatform, false
case !ver.valid():
@@ -824,11 +880,23 @@
}
break
case javaSystem:
- if otherLinkType == javaPlatform {
+ if otherLinkType == javaPlatform || otherLinkType == javaModule || otherLinkType == javaSystemServer {
ctx.ModuleErrorf("compiles against system API, but dependency %q is compiling against private API."+commonMessage,
ctx.OtherModuleName(to))
}
break
+ case javaModule:
+ if otherLinkType == javaPlatform || otherLinkType == javaSystemServer {
+ ctx.ModuleErrorf("compiles against module API, but dependency %q is compiling against private API."+commonMessage,
+ ctx.OtherModuleName(to))
+ }
+ break
+ case javaSystemServer:
+ if otherLinkType == javaPlatform {
+ ctx.ModuleErrorf("compiles against system server API, but dependency %q is compiling against private API."+commonMessage,
+ ctx.OtherModuleName(to))
+ }
+ break
case javaPlatform:
// no restriction on link-type
break
@@ -963,18 +1031,16 @@
case bootClasspathTag:
// If a system modules dependency has been added to the bootclasspath
// then add its libs to the bootclasspath.
- sm := module.(*SystemModules)
- deps.bootClasspath = append(deps.bootClasspath, sm.headerJars...)
+ sm := module.(SystemModulesProvider)
+ deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars()...)
case systemModulesTag:
if deps.systemModules != nil {
panic("Found two system module dependencies")
}
- sm := module.(*SystemModules)
- if sm.outputDir == nil || len(sm.outputDeps) == 0 {
- panic("Missing directory for system module dependency")
- }
- deps.systemModules = &systemModules{sm.outputDir, sm.outputDeps}
+ sm := module.(SystemModulesProvider)
+ outputDir, outputDeps := sm.OutputDirAndDeps()
+ deps.systemModules = &systemModules{outputDir, outputDeps}
}
}
})
@@ -1257,6 +1323,7 @@
j.compiledSrcJars = srcJars
enable_sharding := false
+ var headerJarFileWithoutJarjar android.Path
if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !deps.disableTurbine {
if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
enable_sharding = true
@@ -1266,7 +1333,8 @@
// allow for the use of annotation processors that do function correctly
// with sharding enabled. See: b/77284273.
}
- j.headerJarFile = j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars)
+ headerJarFileWithoutJarjar, j.headerJarFile =
+ j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars)
if ctx.Failed() {
return
}
@@ -1285,7 +1353,7 @@
}
if enable_sharding {
- flags.classpath = append(flags.classpath, j.headerJarFile)
+ flags.classpath = append(flags.classpath, headerJarFileWithoutJarjar)
shardSize := int(*(j.properties.Javac_shard_size))
var shardSrcs []android.Paths
if len(uniqueSrcFiles) > 0 {
@@ -1453,6 +1521,14 @@
j.headerJarFile = j.implementationJarFile
}
+ // Force enable the instrumentation for java code that is built for APEXes ...
+ // except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
+ // doesn't make sense)
+ isJacocoAgent := ctx.ModuleName() == "jacocoagent"
+ if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !isJacocoAgent && !j.IsForPlatform() {
+ j.properties.Instrument = true
+ }
+
if j.shouldInstrument(ctx) {
outputFile = j.instrument(ctx, flags, outputFile, jarName)
}
@@ -1469,6 +1545,16 @@
j.implementationAndResourcesJar = implementationAndResourcesJar
+ // Enable dex compilation for the APEX variants, unless it is disabled explicitly
+ if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !j.IsForPlatform() {
+ if j.deviceProperties.Compile_dex == nil {
+ j.deviceProperties.Compile_dex = proptools.BoolPtr(true)
+ }
+ if j.deviceProperties.Hostdex == nil {
+ j.deviceProperties.Hostdex = proptools.BoolPtr(true)
+ }
+ }
+
if ctx.Device() && j.hasCode(ctx) &&
(Bool(j.properties.Installable) || Bool(j.deviceProperties.Compile_dex)) {
// Dex compilation
@@ -1566,7 +1652,8 @@
}
func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
- deps deps, flags javaBuilderFlags, jarName string, extraJars android.Paths) android.Path {
+ deps deps, flags javaBuilderFlags, jarName string,
+ extraJars android.Paths) (headerJar, jarjarHeaderJar android.Path) {
var jars android.Paths
if len(srcFiles) > 0 || len(srcJars) > 0 {
@@ -1574,7 +1661,7 @@
turbineJar := android.PathForModuleOut(ctx, "turbine", jarName)
TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags)
if ctx.Failed() {
- return nil
+ return nil, nil
}
jars = append(jars, turbineJar)
}
@@ -1583,7 +1670,6 @@
// Combine any static header libraries into classes-header.jar. If there is only
// one input jar this step will be skipped.
- var headerJar android.Path
jars = append(jars, deps.staticHeaderJars...)
// we cannot skip the combine step for now if there is only one jar
@@ -1592,18 +1678,19 @@
TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{},
false, nil, []string{"META-INF/TRANSITIVE"})
headerJar = combinedJar
+ jarjarHeaderJar = combinedJar
if j.expandJarjarRules != nil {
// Transform classes.jar into classes-jarjar.jar
jarjarFile := android.PathForModuleOut(ctx, "turbine-jarjar", jarName)
TransformJarJar(ctx, jarjarFile, headerJar, j.expandJarjarRules)
- headerJar = jarjarFile
+ jarjarHeaderJar = jarjarFile
if ctx.Failed() {
- return nil
+ return nil, nil
}
}
- return headerJar
+ return headerJar, jarjarHeaderJar
}
func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
@@ -1704,8 +1791,10 @@
func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
depTag := ctx.OtherModuleDependencyTag(dep)
- // dependencies other than the static linkage are all considered crossing APEX boundary
- return depTag == staticLibTag
+ // Dependencies other than the static linkage are all considered crossing APEX boundary
+ // Also, a dependency to an sdk member is also considered as such. This is required because
+ // sdk members should be mutated into APEXes. Refer to sdk.sdkDepsReplaceMutator.
+ return depTag == staticLibTag || j.IsInAnySdk()
}
func (j *Module) Stem() string {
@@ -1716,6 +1805,10 @@
return j.jacocoReportClassesFile
}
+func (j *Module) IsInstallable() bool {
+ return Bool(j.properties.Installable)
+}
+
//
// Java libraries (.jar file)
//
@@ -1753,7 +1846,6 @@
j.checkSdkVersion(ctx)
j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
- j.dexpreopter.isInstallable = Bool(j.properties.Installable)
j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
j.deviceProperties.UncompressDex = j.dexpreopter.uncompressedDex
j.compile(ctx, nil)
@@ -1834,6 +1926,15 @@
module.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
}
+var javaHeaderLibsSdkMemberType android.SdkMemberType = &headerLibrarySdkMemberType{
+ librarySdkMemberType{
+ android.SdkMemberTypeBase{
+ PropertyName: "java_header_libs",
+ SupportsSdk: true,
+ },
+ },
+}
+
type headerLibrarySdkMemberType struct {
librarySdkMemberType
}
@@ -2393,6 +2494,14 @@
return nil, nil
}
+func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+ depTag := ctx.OtherModuleDependencyTag(dep)
+ // dependencies other than the static linkage are all considered crossing APEX boundary
+ // Also, a dependency to an sdk member is also considered as such. This is required because
+ // sdk members should be mutated into APEXes. Refer to sdk.sdkDepsReplaceMutator.
+ return depTag == staticLibTag || j.IsInAnySdk()
+}
+
// Add compile time check for interface implementation
var _ android.IDEInfo = (*Import)(nil)
var _ android.IDECustomizedModuleName = (*Import)(nil)
@@ -2493,13 +2602,16 @@
return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
}
+func (j *DexImport) IsInstallable() bool {
+ return true
+}
+
func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if len(j.properties.Jars) != 1 {
ctx.PropertyErrorf("jars", "exactly one jar must be provided")
}
j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
- j.dexpreopter.isInstallable = true
j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
inputJar := ctx.ExpandSource(j.properties.Jars[0], "jars")
diff --git a/java/java_test.go b/java/java_test.go
index 8815c09..6d972be 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -57,7 +57,15 @@
}
func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config {
- return TestConfig(buildDir, env, bp, fs)
+ bp += dexpreopt.BpToolModulesForTest()
+
+ config := TestConfig(buildDir, env, bp, fs)
+
+ // Set up the global Once cache used for dexpreopt.GlobalSoongConfig, so that
+ // it doesn't create a real one, which would fail.
+ _ = dexpreopt.GlobalSoongConfigForTests(config)
+
+ return config
}
func testContext() *android.TestContext {
@@ -84,7 +92,8 @@
// Register module types and mutators from cc needed for JNI testing
cc.RegisterRequiredBuildComponentsForTest(ctx)
- ctx.RegisterModuleType("ndk_prebuilt_shared_stl", cc.NdkPrebuiltSharedStlFactory)
+
+ dexpreopt.RegisterToolModulesForTest(ctx)
return ctx
}
@@ -93,7 +102,7 @@
t.Helper()
pathCtx := android.PathContextForTesting(config)
- setDexpreoptTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
+ dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
ctx.Register(config)
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
@@ -112,7 +121,7 @@
ctx := testContext()
pathCtx := android.PathContextForTesting(config)
- setDexpreoptTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
+ dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
ctx.Register(config)
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
@@ -972,6 +981,65 @@
}
}
+func TestDroidstubsWithSystemModules(t *testing.T) {
+ ctx, _ := testJava(t, `
+ droidstubs {
+ name: "stubs-source-system-modules",
+ srcs: [
+ "bar-doc/*.java",
+ ],
+ sdk_version: "none",
+ system_modules: "source-system-modules",
+ }
+
+ java_library {
+ name: "source-jar",
+ srcs: [
+ "a.java",
+ ],
+ }
+
+ java_system_modules {
+ name: "source-system-modules",
+ libs: ["source-jar"],
+ }
+
+ droidstubs {
+ name: "stubs-prebuilt-system-modules",
+ srcs: [
+ "bar-doc/*.java",
+ ],
+ sdk_version: "none",
+ system_modules: "prebuilt-system-modules",
+ }
+
+ java_import {
+ name: "prebuilt-jar",
+ jars: ["a.jar"],
+ }
+
+ java_system_modules_import {
+ name: "prebuilt-system-modules",
+ libs: ["prebuilt-jar"],
+ }
+ `)
+
+ checkSystemModulesUseByDroidstubs(t, ctx, "stubs-source-system-modules", "source-jar.jar")
+
+ checkSystemModulesUseByDroidstubs(t, ctx, "stubs-prebuilt-system-modules", "prebuilt-jar.jar")
+}
+
+func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, moduleName string, systemJar string) {
+ metalavaRule := ctx.ModuleForTests(moduleName, "android_common").Rule("metalava")
+ var systemJars []string
+ for _, i := range metalavaRule.Implicits {
+ systemJars = append(systemJars, i.Base())
+ }
+ if len(systemJars) != 1 || systemJars[0] != systemJar {
+ t.Errorf("inputs of %q must be []string{%q}, but was %#v.", moduleName, systemJar, systemJars)
+ }
+}
+
func TestJarGenrules(t *testing.T) {
ctx, _ := testJava(t, `
java_library {
@@ -1112,10 +1180,10 @@
ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix, "android_common")
ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix+sdkSystemApiSuffix, "android_common")
ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix+sdkTestApiSuffix, "android_common")
- ctx.ModuleForTests("foo"+sdkDocsSuffix, "android_common")
- ctx.ModuleForTests("foo"+sdkDocsSuffix+sdkSystemApiSuffix, "android_common")
- ctx.ModuleForTests("foo"+sdkDocsSuffix+sdkTestApiSuffix, "android_common")
- ctx.ModuleForTests("foo"+sdkXmlFileSuffix, "android_arm64_armv8-a")
+ ctx.ModuleForTests("foo"+sdkStubsSourceSuffix, "android_common")
+ ctx.ModuleForTests("foo"+sdkStubsSourceSuffix+sdkSystemApiSuffix, "android_common")
+ ctx.ModuleForTests("foo"+sdkStubsSourceSuffix+sdkTestApiSuffix, "android_common")
+ ctx.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common")
ctx.ModuleForTests("foo.api.public.28", "")
ctx.ModuleForTests("foo.api.system.28", "")
ctx.ModuleForTests("foo.api.test.28", "")
@@ -1367,3 +1435,59 @@
}
}
}
+
+func TestJavaLibraryWithSystemModules(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library {
+ name: "lib-with-source-system-modules",
+ srcs: [
+ "a.java",
+ ],
+ sdk_version: "none",
+ system_modules: "source-system-modules",
+ }
+
+ java_library {
+ name: "source-jar",
+ srcs: [
+ "a.java",
+ ],
+ }
+
+ java_system_modules {
+ name: "source-system-modules",
+ libs: ["source-jar"],
+ }
+
+ java_library {
+ name: "lib-with-prebuilt-system-modules",
+ srcs: [
+ "a.java",
+ ],
+ sdk_version: "none",
+ system_modules: "prebuilt-system-modules",
+ }
+
+ java_import {
+ name: "prebuilt-jar",
+ jars: ["a.jar"],
+ }
+
+ java_system_modules_import {
+ name: "prebuilt-system-modules",
+ libs: ["prebuilt-jar"],
+ }
+ `)
+
+ checkBootClasspathForSystemModule(t, ctx, "lib-with-source-system-modules", "/source-jar.jar")
+
+ checkBootClasspathForSystemModule(t, ctx, "lib-with-prebuilt-system-modules", "/prebuilt-jar.jar")
+}
+
+func checkBootClasspathForSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) {
+ javacRule := ctx.ModuleForTests(moduleName, "android_common").Rule("javac")
+ bootClasspath := javacRule.Args["bootClasspath"]
+ if strings.HasPrefix(bootClasspath, "--system ") && strings.HasSuffix(bootClasspath, expectedSuffix) {
+ t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath)
+ }
+}
diff --git a/java/sdk.go b/java/sdk.go
index f388358..1e60d67 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -71,6 +71,8 @@
sdkPublic
sdkSystem
sdkTest
+ sdkModule
+ sdkSystemServer
sdkPrivate
)
@@ -91,6 +93,10 @@
return "core"
case sdkCorePlatform:
return "core_platform"
+ case sdkModule:
+ return "module"
+ case sdkSystemServer:
+ return "system_server"
default:
return "invalid"
}
@@ -256,6 +262,10 @@
kind = sdkSystem
case "test":
kind = sdkTest
+ case "module":
+ kind = sdkModule
+ case "system_server":
+ kind = sdkSystemServer
default:
return sdkSpec{sdkInvalid, sdkVersionNone, str}
}
@@ -319,13 +329,13 @@
}
}
- toModule := func(m, r string, aidl android.Path) sdkDep {
+ toModule := func(modules []string, res string, aidl android.Path) sdkDep {
return sdkDep{
useModule: true,
- bootclasspath: []string{m, config.DefaultLambdaStubsLibrary},
+ bootclasspath: append(modules, config.DefaultLambdaStubsLibrary),
systemModules: "core-current-stubs-system-modules",
- java9Classpath: []string{m},
- frameworkResModule: r,
+ java9Classpath: modules,
+ frameworkResModule: res,
aidl: android.OptionalPathForPath(aidl),
}
}
@@ -375,13 +385,19 @@
noFrameworksLibs: true,
}
case sdkPublic:
- return toModule("android_stubs_current", "framework-res", sdkFrameworkAidlPath(ctx))
+ return toModule([]string{"android_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
case sdkSystem:
- return toModule("android_system_stubs_current", "framework-res", sdkFrameworkAidlPath(ctx))
+ return toModule([]string{"android_system_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
case sdkTest:
- return toModule("android_test_stubs_current", "framework-res", sdkFrameworkAidlPath(ctx))
+ return toModule([]string{"android_test_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
case sdkCore:
- return toModule("core.current.stubs", "", nil)
+ return toModule([]string{"core.current.stubs"}, "", nil)
+ case sdkModule:
+ // TODO(146757305): provide .apk and .aidl that have more APIs for modules
+ return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
+ case sdkSystemServer:
+ // TODO(146757305): provide .apk and .aidl that have more APIs for modules
+ return toModule([]string{"android_module_lib_stubs_current", "services-stubs"}, "framework-res", sdkFrameworkAidlPath(ctx))
default:
panic(fmt.Errorf("invalid sdk %q", sdkVersion.raw))
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index fb8ae95..a8edf1d 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -33,25 +33,25 @@
sdkStubsLibrarySuffix = ".stubs"
sdkSystemApiSuffix = ".system"
sdkTestApiSuffix = ".test"
- sdkDocsSuffix = ".docs"
+ sdkStubsSourceSuffix = ".stubs.source"
sdkXmlFileSuffix = ".xml"
- permissionsTemplate = `<?xml version="1.0" encoding="utf-8"?>\n` +
+ permissionsTemplate = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n` +
`<!-- Copyright (C) 2018 The Android Open Source Project\n` +
`\n` +
- ` Licensed under the Apache License, Version 2.0 (the "License");\n` +
+ ` Licensed under the Apache License, Version 2.0 (the \"License\");\n` +
` you may not use this file except in compliance with the License.\n` +
` You may obtain a copy of the License at\n` +
`\n` +
` http://www.apache.org/licenses/LICENSE-2.0\n` +
`\n` +
` Unless required by applicable law or agreed to in writing, software\n` +
- ` distributed under the License is distributed on an "AS IS" BASIS,\n` +
+ ` distributed under the License is distributed on an \"AS IS\" BASIS,\n` +
` WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n` +
` See the License for the specific language governing permissions and\n` +
` limitations under the License.\n` +
`-->\n` +
`<permissions>\n` +
- ` <library name="%s" file="%s"/>\n` +
+ ` <library name=\"%s\" file=\"%s\"/>\n` +
`</permissions>\n`
)
@@ -108,7 +108,7 @@
}
func (scope *apiScope) docsModuleName(baseName string) string {
- return baseName + sdkDocsSuffix + scope.moduleSuffix
+ return baseName + sdkStubsSourceSuffix + scope.moduleSuffix
}
type apiScopes []*apiScope
@@ -249,8 +249,6 @@
sdkLibraryProperties sdkLibraryProperties
commonToSdkLibraryAndImport
-
- permissionsFile android.Path
}
var _ Dependency = (*SdkLibrary)(nil)
@@ -264,17 +262,29 @@
}
}
+var xmlPermissionsFileTag = dependencyTag{name: "xml-permissions-file"}
+
+func IsXmlPermissionsFileDepTag(depTag blueprint.DependencyTag) bool {
+ if dt, ok := depTag.(dependencyTag); ok {
+ return dt == xmlPermissionsFileTag
+ }
+ return false
+}
+
func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
- useBuiltStubs := !ctx.Config().UnbundledBuildUsePrebuiltSdks()
for _, apiScope := range module.getActiveApiScopes() {
// Add dependencies to the stubs library
- if useBuiltStubs {
- ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsName(apiScope))
- }
+ ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsName(apiScope))
+ // And the api file
ctx.AddVariationDependencies(nil, apiScope.apiFileTag, module.docsName(apiScope))
}
+ if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
+ // Add dependency to the rule for generating the xml permissions file
+ ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlFileName())
+ }
+
module.Library.deps(ctx)
}
@@ -284,8 +294,6 @@
module.Library.GenerateAndroidBuildActions(ctx)
}
- module.buildPermissionsFile(ctx)
-
// Record the paths to the header jars of the library (stubs and impl).
// When this java_sdk_library is depended upon from others via "libs" property,
// the recorded paths will be returned depending on the link type of the caller.
@@ -313,30 +321,6 @@
})
}
-func (module *SdkLibrary) buildPermissionsFile(ctx android.ModuleContext) {
- xmlContent := fmt.Sprintf(permissionsTemplate, module.BaseModuleName(), module.implPath())
- permissionsFile := android.PathForModuleOut(ctx, module.xmlFileName())
-
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Output: permissionsFile,
- Description: "Generating " + module.BaseModuleName() + " permissions",
- Args: map[string]string{
- "content": xmlContent,
- },
- })
-
- module.permissionsFile = permissionsFile
-}
-
-func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case ".xml":
- return android.Paths{module.permissionsFile}, nil
- }
- return module.Library.OutputFiles(tag)
-}
-
func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
if proptools.Bool(module.sdkLibraryProperties.Api_only) {
return nil
@@ -397,27 +381,6 @@
return module.BaseModuleName()
}
-// File path to the runtime implementation library
-func (module *SdkLibrary) implPath() string {
- if apexName := module.ApexName(); apexName != "" {
- // TODO(b/146468504): ApexName() is only a soong module name, not apex name.
- // In most cases, this works fine. But when apex_name is set or override_apex is used
- // this can be wrong.
- return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexName, module.implName())
- }
- partition := "system"
- if module.SocSpecific() {
- partition = "vendor"
- } else if module.DeviceSpecific() {
- partition = "odm"
- } else if module.ProductSpecific() {
- partition = "product"
- } else if module.SystemExtSpecific() {
- partition = "system_ext"
- }
- return "/" + partition + "/framework/" + module.implName() + ".jar"
-}
-
// Module name of the XML file for the lib
func (module *SdkLibrary) xmlFileName() string {
return module.BaseModuleName() + sdkXmlFileSuffix
@@ -458,6 +421,7 @@
Installable *bool
Sdk_version *string
System_modules *string
+ Patch_module *string
Libs []string
Soc_specific *bool
Device_specific *bool
@@ -466,9 +430,6 @@
Compile_dex *bool
Java_version *string
Product_variables struct {
- Unbundled_build struct {
- Enabled *bool
- }
Pdk struct {
Enabled *bool
}
@@ -485,12 +446,9 @@
sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
props.Sdk_version = proptools.StringPtr(sdkVersion)
props.System_modules = module.Library.Module.deviceProperties.System_modules
+ props.Patch_module = module.Library.Module.properties.Patch_module
props.Installable = proptools.BoolPtr(false)
props.Libs = module.sdkLibraryProperties.Stub_only_libs
- // Unbundled apps will use the prebult one from /prebuilts/sdk
- if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
- props.Product_variables.Unbundled_build.Enabled = proptools.BoolPtr(false)
- }
props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false)
props.Openjdk9.Srcs = module.Library.Module.properties.Openjdk9.Srcs
props.Openjdk9.Javacflags = module.Library.Module.properties.Openjdk9.Javacflags
@@ -625,33 +583,32 @@
// Creates the xml file that publicizes the runtime library
func (module *SdkLibrary) createXmlFile(mctx android.LoadHookContext) {
- // creates a prebuilt_etc module to actually place the xml file under
- // <partition>/etc/permissions
- etcProps := struct {
+ props := struct {
Name *string
- Src *string
- Sub_dir *string
+ Lib_name *string
Soc_specific *bool
Device_specific *bool
Product_specific *bool
System_ext_specific *bool
- }{}
- etcProps.Name = proptools.StringPtr(module.xmlFileName())
- etcProps.Src = proptools.StringPtr(":" + module.BaseModuleName() + "{.xml}")
- etcProps.Sub_dir = proptools.StringPtr("permissions")
- if module.SocSpecific() {
- etcProps.Soc_specific = proptools.BoolPtr(true)
- } else if module.DeviceSpecific() {
- etcProps.Device_specific = proptools.BoolPtr(true)
- } else if module.ProductSpecific() {
- etcProps.Product_specific = proptools.BoolPtr(true)
- } else if module.SystemExtSpecific() {
- etcProps.System_ext_specific = proptools.BoolPtr(true)
+ }{
+ Name: proptools.StringPtr(module.xmlFileName()),
+ Lib_name: proptools.StringPtr(module.BaseModuleName()),
}
- mctx.CreateModule(android.PrebuiltEtcFactory, &etcProps)
+
+ if module.SocSpecific() {
+ props.Soc_specific = proptools.BoolPtr(true)
+ } else if module.DeviceSpecific() {
+ props.Device_specific = proptools.BoolPtr(true)
+ } else if module.ProductSpecific() {
+ props.Product_specific = proptools.BoolPtr(true)
+ } else if module.SystemExtSpecific() {
+ props.System_ext_specific = proptools.BoolPtr(true)
+ }
+
+ mctx.CreateModule(sdkLibraryXmlFactory, &props)
}
-func (module *SdkLibrary) PrebuiltJars(ctx android.BaseModuleContext, s sdkSpec) android.Paths {
+func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s sdkSpec) android.Paths {
var ver sdkVersion
var kind sdkKind
if s.usePrebuilt(ctx) {
@@ -665,7 +622,7 @@
}
dir := filepath.Join("prebuilts", "sdk", ver.String(), kind.String())
- jar := filepath.Join(dir, module.BaseModuleName()+".jar")
+ jar := filepath.Join(dir, baseName+".jar")
jarPath := android.ExistentPathForSource(ctx, jar)
if !jarPath.Valid() {
if ctx.Config().AllowMissingDependencies() {
@@ -683,10 +640,9 @@
sdkVersion sdkSpec,
headerJars bool) android.Paths {
- // If a specific numeric version has been requested or the build is explicitly configured
- // for it then use prebuilt versions of the sdk.
- if sdkVersion.version.isNumbered() || ctx.Config().UnbundledBuildUsePrebuiltSdks() {
- return module.PrebuiltJars(ctx, sdkVersion)
+ // If a specific numeric version has been requested then use prebuilt versions of the sdk.
+ if sdkVersion.version.isNumbered() {
+ return PrebuiltJars(ctx, module.BaseModuleName(), sdkVersion)
} else {
if !sdkVersion.specified() {
if headerJars {
@@ -882,7 +838,7 @@
module.AddProperties(&module.properties)
- android.InitPrebuiltModule(module, &[]string{})
+ android.InitPrebuiltModule(module, &[]string{""})
InitJavaModule(module, android.HostAndDeviceSupported)
android.AddLoadHook(module, func(mctx android.LoadHookContext) { module.createInternalModules(mctx) })
@@ -899,6 +855,11 @@
func (module *sdkLibraryImport) createInternalModules(mctx android.LoadHookContext) {
+ // If the build is configured to use prebuilts then force this to be preferred.
+ if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
+ module.prebuilt.ForcePrefer()
+ }
+
for apiScope, scopeProperties := range module.scopeProperties() {
if len(scopeProperties.Jars) == 0 {
continue
@@ -914,6 +875,7 @@
Sdk_version *string
Libs []string
Jars []string
+ Prefer *bool
}{}
props.Name = proptools.StringPtr(apiScope.stubsModuleName(module.BaseModuleName()))
@@ -933,6 +895,12 @@
props.System_ext_specific = proptools.BoolPtr(true)
}
+ // If the build should use prebuilt sdks then set prefer to true on the stubs library.
+ // That will cause the prebuilt version of the stubs to override the source version.
+ if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
+ props.Prefer = proptools.BoolPtr(true)
+ }
+
mctx.CreateModule(ImportFactory, &props)
}
@@ -980,6 +948,11 @@
ctx android.BaseModuleContext,
sdkVersion sdkSpec) android.Paths {
+ // If a specific numeric version has been requested then use prebuilt versions of the sdk.
+ if sdkVersion.version.isNumbered() {
+ return PrebuiltJars(ctx, module.BaseModuleName(), sdkVersion)
+ }
+
var apiScope *apiScope
switch sdkVersion.kind {
case sdkSystem:
@@ -1005,3 +978,111 @@
// This module is just a wrapper for the stubs.
return module.sdkJars(ctx, sdkVersion)
}
+
+//
+// java_sdk_library_xml
+//
+type sdkLibraryXml struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ android.ApexModuleBase
+
+ properties sdkLibraryXmlProperties
+
+ outputFilePath android.OutputPath
+ installDirPath android.InstallPath
+}
+
+type sdkLibraryXmlProperties struct {
+ // canonical name of the lib
+ Lib_name *string
+}
+
+// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
+// Not to be used directly by users. java_sdk_library internally uses this.
+func sdkLibraryXmlFactory() android.Module {
+ module := &sdkLibraryXml{}
+
+ module.AddProperties(&module.properties)
+
+ android.InitApexModule(module)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+
+ return module
+}
+
+// from android.PrebuiltEtcModule
+func (module *sdkLibraryXml) SubDir() string {
+ return "permissions"
+}
+
+// from android.PrebuiltEtcModule
+func (module *sdkLibraryXml) OutputFile() android.OutputPath {
+ return module.outputFilePath
+}
+
+// from android.ApexModule
+func (module *sdkLibraryXml) AvailableFor(what string) bool {
+ return true
+}
+
+func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // do nothing
+}
+
+// File path to the runtime implementation library
+func (module *sdkLibraryXml) implPath() string {
+ implName := proptools.String(module.properties.Lib_name)
+ if apexName := module.ApexName(); apexName != "" {
+ // TODO(b/146468504): ApexName() is only a soong module name, not apex name.
+ // In most cases, this works fine. But when apex_name is set or override_apex is used
+ // this can be wrong.
+ return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexName, implName)
+ }
+ partition := "system"
+ if module.SocSpecific() {
+ partition = "vendor"
+ } else if module.DeviceSpecific() {
+ partition = "odm"
+ } else if module.ProductSpecific() {
+ partition = "product"
+ } else if module.SystemExtSpecific() {
+ partition = "system_ext"
+ }
+ return "/" + partition + "/framework/" + implName + ".jar"
+}
+
+func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ libName := proptools.String(module.properties.Lib_name)
+ xmlContent := fmt.Sprintf(permissionsTemplate, libName, module.implPath())
+
+ module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath
+ rule := android.NewRuleBuilder()
+ rule.Command().
+ Text("/bin/bash -c \"echo -e '" + xmlContent + "'\" > ").
+ Output(module.outputFilePath)
+
+ rule.Build(pctx, ctx, "java_sdk_xml", "Permission XML")
+
+ module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir())
+}
+
+func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
+ if !module.IsForPlatform() {
+ return []android.AndroidMkEntries{android.AndroidMkEntries{
+ Disabled: true,
+ }}
+ }
+
+ return []android.AndroidMkEntries{android.AndroidMkEntries{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(module.outputFilePath),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_TAGS", "optional")
+ entries.SetString("LOCAL_MODULE_PATH", module.installDirPath.ToMakePath().String())
+ entries.SetString("LOCAL_INSTALLED_MODULE_STEM", module.outputFilePath.Base())
+ },
+ },
+ }}
+}
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 9cabd77..ea6733d 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -211,6 +211,22 @@
java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
aidl: "-pprebuilts/sdk/29/public/framework.aidl",
},
+ {
+ name: "module_current",
+ properties: `sdk_version: "module_current",`,
+ bootclasspath: []string{"android_module_lib_stubs_current", "core-lambda-stubs"},
+ system: "core-current-stubs-system-modules",
+ java9classpath: []string{"android_module_lib_stubs_current"},
+ aidl: "-p" + buildDir + "/framework.aidl",
+ },
+ {
+ name: "system_server_current",
+ properties: `sdk_version: "system_server_current",`,
+ bootclasspath: []string{"android_module_lib_stubs_current", "services-stubs", "core-lambda-stubs"},
+ system: "core-current-stubs-system-modules",
+ java9classpath: []string{"android_module_lib_stubs_current", "services-stubs"},
+ aidl: "-p" + buildDir + "/framework.aidl",
+ },
}
for _, testcase := range classpathTestcases {
diff --git a/java/system_modules.go b/java/system_modules.go
index 92297c4..47de6e3 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -31,6 +31,15 @@
RegisterSystemModulesBuildComponents(android.InitRegistrationContext)
pctx.SourcePathVariable("moduleInfoJavaPath", "build/soong/scripts/jars-to-module-info-java.sh")
+
+ // Register sdk member types.
+ android.RegisterSdkMemberType(&systemModulesSdkMemberType{
+ android.SdkMemberTypeBase{
+ PropertyName: "java_system_modules",
+ SupportsSdk: true,
+ TransitiveSdkMembers: true,
+ },
+ })
}
func RegisterSystemModulesBuildComponents(ctx android.RegistrationContext) {
@@ -66,6 +75,10 @@
},
},
"classpath", "outDir", "workDir")
+
+ // Dependency tag that causes the added dependencies to be added as java_header_libs
+ // to the sdk/module_exports/snapshot.
+ systemModulesLibsTag = android.DependencyTagForSdkMemberType(javaHeaderLibsSdkMemberType)
)
func TransformJarsToSystemModules(ctx android.ModuleContext, jars android.Paths) (android.Path, android.Paths) {
@@ -104,9 +117,19 @@
return module
}
+type SystemModulesProvider interface {
+ HeaderJars() android.Paths
+ OutputDirAndDeps() (android.Path, android.Paths)
+}
+
+var _ SystemModulesProvider = (*SystemModules)(nil)
+
+var _ SystemModulesProvider = (*systemModulesImport)(nil)
+
type SystemModules struct {
android.ModuleBase
android.DefaultableModuleBase
+ android.SdkBase
properties SystemModulesProperties
@@ -122,10 +145,21 @@
Libs []string
}
+func (system *SystemModules) HeaderJars() android.Paths {
+ return system.headerJars
+}
+
+func (system *SystemModules) OutputDirAndDeps() (android.Path, android.Paths) {
+ if system.outputDir == nil || len(system.outputDeps) == 0 {
+ panic("Missing directory for system module dependency")
+ }
+ return system.outputDir, system.outputDeps
+}
+
func (system *SystemModules) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var jars android.Paths
- ctx.VisitDirectDepsWithTag(libTag, func(module android.Module) {
+ ctx.VisitDirectDepsWithTag(systemModulesLibsTag, func(module android.Module) {
dep, _ := module.(Dependency)
jars = append(jars, dep.HeaderJars()...)
})
@@ -136,7 +170,7 @@
}
func (system *SystemModules) DepsMutator(ctx android.BottomUpMutatorContext) {
- ctx.AddVariationDependencies(nil, libTag, system.properties.Libs...)
+ ctx.AddVariationDependencies(nil, systemModulesLibsTag, system.properties.Libs...)
}
func (system *SystemModules) AndroidMk() android.AndroidMkData {
@@ -173,6 +207,7 @@
android.InitPrebuiltModule(module, &module.properties.Libs)
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
+ android.InitSdkAwareModule(module)
return module
}
@@ -188,3 +223,37 @@
func (system *systemModulesImport) Prebuilt() *android.Prebuilt {
return &system.prebuilt
}
+
+type systemModulesSdkMemberType struct {
+ android.SdkMemberTypeBase
+}
+
+func (mt *systemModulesSdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
+ mctx.AddVariationDependencies(nil, dependencyTag, names...)
+}
+
+func (mt *systemModulesSdkMemberType) IsInstance(module android.Module) bool {
+ if _, ok := module.(*SystemModules); ok {
+ // A prebuilt system module cannot be added as a member of an sdk because the source and
+ // snapshot instances would conflict.
+ _, ok := module.(*systemModulesImport)
+ return !ok
+ }
+ return false
+}
+
+func (mt *systemModulesSdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
+ variants := member.Variants()
+ if len(variants) != 1 {
+ sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name())
+ for _, variant := range variants {
+ sdkModuleContext.ModuleErrorf(" %q", variant)
+ }
+ }
+ variant := variants[0]
+ systemModule := variant.(*SystemModules)
+
+ pbm := builder.AddPrebuiltModule(member, "java_system_modules_import")
+ // Add the references to the libraries that form the system module.
+ pbm.AddPropertyWithTag("libs", systemModule.properties.Libs, builder.SdkMemberReferencePropertyTag())
+}
diff --git a/java/testing.go b/java/testing.go
index c409a46..5b6a39b 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -18,6 +18,7 @@
"fmt"
"android/soong/android"
+ "android/soong/cc"
)
func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) android.Config {
@@ -52,8 +53,6 @@
"assets_a/a": nil,
"assets_b/b": nil,
- "prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so": nil,
-
"prebuilts/sdk/14/public/android.jar": nil,
"prebuilts/sdk/14/public/framework.aidl": nil,
"prebuilts/sdk/14/system/android.jar": nil,
@@ -122,6 +121,8 @@
"stubs/sources/foo/Foo.java": nil,
}
+ cc.GatherRequiredFilesForTest(mockFS)
+
for k, v := range fs {
mockFS[k] = v
}
@@ -146,6 +147,8 @@
"android_stubs_current",
"android_system_stubs_current",
"android_test_stubs_current",
+ "android_module_lib_stubs_current",
+ "services-stubs",
"core.current.stubs",
"core.platform.api.stubs",
"kotlin-stdlib",
diff --git a/python/tests/py-cmd_test.py b/python/tests/py-cmd_test.py
new file mode 100644
index 0000000..acda2d7
--- /dev/null
+++ b/python/tests/py-cmd_test.py
@@ -0,0 +1,78 @@
+# Copyright 2020 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.
+
+import os
+import site
+import sys
+
+# This file checks the visible python state against expected values when run
+# using a prebuilt python.
+
+failed = False
+def assert_equal(what, a, b):
+ global failed
+ if a != b:
+ print("Expected %s('%s') == '%s'" % (what, a, b))
+ failed = True
+
+assert_equal("__name__", __name__, "__main__")
+assert_equal("os.path.basename(__file__)", os.path.basename(__file__), "py-cmd_test.py")
+
+if os.getenv('ARGTEST', False):
+ assert_equal("len(sys.argv)", len(sys.argv), 3)
+ assert_equal("sys.argv[1]", sys.argv[1], "arg1")
+ assert_equal("sys.argv[2]", sys.argv[2], "arg2")
+elif os.getenv('ARGTEST2', False):
+ assert_equal("len(sys.argv)", len(sys.argv), 3)
+ assert_equal("sys.argv[1]", sys.argv[1], "--arg1")
+ assert_equal("sys.argv[2]", sys.argv[2], "arg2")
+else:
+ assert_equal("len(sys.argv)", len(sys.argv), 1)
+
+if os.getenv('ARGTEST_ONLY', False):
+ if failed:
+ sys.exit(1)
+ sys.exit(0)
+
+assert_equal("__package__", __package__, None)
+assert_equal("sys.argv[0]", sys.argv[0], 'py-cmd_test.py')
+if sys.version_info[0] == 2:
+ assert_equal("basename(sys.executable)", os.path.basename(sys.executable), 'py2-cmd')
+else:
+ assert_equal("basename(sys.executable)", os.path.basename(sys.executable), 'py3-cmd')
+assert_equal("sys.exec_prefix", sys.exec_prefix, sys.executable)
+assert_equal("sys.prefix", sys.prefix, sys.executable)
+assert_equal("site.ENABLE_USER_SITE", site.ENABLE_USER_SITE, None)
+
+if sys.version_info[0] == 2:
+ assert_equal("len(sys.path)", len(sys.path), 4)
+ assert_equal("sys.path[0]", sys.path[0], os.path.dirname(__file__))
+ assert_equal("sys.path[1]", sys.path[1], "/extra")
+ assert_equal("sys.path[2]", sys.path[2], os.path.join(sys.executable, "internal"))
+ assert_equal("sys.path[3]", sys.path[3], os.path.join(sys.executable, "internal", "stdlib"))
+else:
+ assert_equal("len(sys.path)", len(sys.path), 8)
+ assert_equal("sys.path[0]", sys.path[0], os.path.abspath(os.path.dirname(__file__)))
+ assert_equal("sys.path[1]", sys.path[1], "/extra")
+ assert_equal("sys.path[2]", sys.path[2], os.path.join(sys.executable, 'lib', 'python' + str(sys.version_info[0]) + str(sys.version_info[1]) + '.zip'))
+ assert_equal("sys.path[3]", sys.path[3], os.path.join(sys.executable, 'lib', 'python' + str(sys.version_info[0]) + '.' + str(sys.version_info[1]), '..'))
+ assert_equal("sys.path[4]", sys.path[4], os.path.join(sys.executable, 'lib', 'python' + str(sys.version_info[0]) + '.' + str(sys.version_info[1])))
+ assert_equal("sys.path[5]", sys.path[5], os.path.join(sys.executable, 'lib', 'python' + str(sys.version_info[0]) + '.' + str(sys.version_info[1]), 'lib-dynload'))
+ assert_equal("sys.path[6]", sys.path[6], os.path.join(sys.executable, "internal"))
+ assert_equal("sys.path[7]", sys.path[7], os.path.join(sys.executable, "internal", "stdlib"))
+
+if failed:
+ sys.exit(1)
+
+import testpkg.pycmd_test
diff --git a/python/tests/runtest.sh b/python/tests/runtest.sh
index 21187ed..35941dc 100755
--- a/python/tests/runtest.sh
+++ b/python/tests/runtest.sh
@@ -23,8 +23,11 @@
exit 1
fi
-if [[ ( ! -f $ANDROID_HOST_OUT/nativetest64/par_test/par_test ) || ( ! -f $ANDROID_HOST_OUT/nativetest64/par_test3/par_test3 ) ]]; then
- echo "Run 'm par_test par_test3' first"
+if [[ ( ! -f $ANDROID_HOST_OUT/nativetest64/par_test/par_test ) ||
+ ( ! -f $ANDROID_HOST_OUT/nativetest64/par_test3/par_test3 ) ||
+ ( ! -f $ANDROID_HOST_OUT/bin/py2-cmd ) ||
+ ( ! -f $ANDROID_HOST_OUT/bin/py3-cmd )]]; then
+ echo "Run 'm par_test par_test3 py2-cmd py3-cmd' first"
exit 1
fi
@@ -44,4 +47,15 @@
ARGTEST=true $ANDROID_HOST_OUT/nativetest64/par_test3/par_test3 --arg1 arg2
+cd $(dirname ${BASH_SOURCE[0]})
+
+PYTHONPATH=/extra $ANDROID_HOST_OUT/bin/py2-cmd py-cmd_test.py
+PYTHONPATH=/extra $ANDROID_HOST_OUT/bin/py3-cmd py-cmd_test.py
+
+ARGTEST=true PYTHONPATH=/extra $ANDROID_HOST_OUT/bin/py2-cmd py-cmd_test.py arg1 arg2
+ARGTEST2=true PYTHONPATH=/extra $ANDROID_HOST_OUT/bin/py2-cmd py-cmd_test.py --arg1 arg2
+
+ARGTEST=true PYTHONPATH=/extra $ANDROID_HOST_OUT/bin/py3-cmd py-cmd_test.py arg1 arg2
+ARGTEST2=true PYTHONPATH=/extra $ANDROID_HOST_OUT/bin/py3-cmd py-cmd_test.py --arg1 arg2
+
echo "Passed!"
diff --git a/python/tests/testpkg/__init__.py b/python/tests/testpkg/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/python/tests/testpkg/__init__.py
diff --git a/python/tests/testpkg/pycmd_test.py b/python/tests/testpkg/pycmd_test.py
new file mode 100644
index 0000000..6b8a263
--- /dev/null
+++ b/python/tests/testpkg/pycmd_test.py
@@ -0,0 +1,33 @@
+# Copyright 2018 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.
+
+import os
+import sys
+
+# This file checks the visible python state against expected values when run
+# via the py*-cmd prebuilts
+
+failed = False
+def assert_equal(what, a, b):
+ global failed
+ if a != b:
+ print("Expected %s('%s') == '%s'" % (what, a, b))
+ failed = True
+
+assert_equal("__name__", __name__, "testpkg.pycmd_test")
+assert_equal("basename(__file__)", os.path.basename(__file__), "pycmd_test.py")
+assert_equal("__package__", __package__, "testpkg")
+
+if failed:
+ sys.exit(1)
diff --git a/rust/config/whitelist.go b/rust/config/whitelist.go
index 7dfb002..a339050 100644
--- a/rust/config/whitelist.go
+++ b/rust/config/whitelist.go
@@ -2,6 +2,7 @@
var (
RustAllowedPaths = []string{
+ "external/minijail",
"external/rust",
"external/crosvm",
"external/adhd",
diff --git a/rust/rust.go b/rust/rust.go
index e2af6f0..de6512c 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -354,11 +354,6 @@
return nil
}
-func (mod *Module) AllStaticDeps() []string {
- // TODO(jiyong): do this for rust?
- return nil
-}
-
func (mod *Module) Module() android.Module {
return mod
}
@@ -623,21 +618,24 @@
linkFile := ccDep.OutputFile()
linkPath := linkPathFromFilePath(linkFile.Path())
libName := libNameFromFilePath(linkFile.Path())
+ depFlag := "-l" + libName
+
if !linkFile.Valid() {
ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
}
exportDep := false
-
switch depTag {
case cc.StaticDepTag:
+ depFlag = "-lstatic=" + libName
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
- depPaths.depFlags = append(depPaths.depFlags, "-l"+libName)
+ depPaths.depFlags = append(depPaths.depFlags, depFlag)
directStaticLibDeps = append(directStaticLibDeps, ccDep)
mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, depName)
case cc.SharedDepTag:
+ depFlag = "-ldylib=" + libName
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
- depPaths.depFlags = append(depPaths.depFlags, "-l"+libName)
+ depPaths.depFlags = append(depPaths.depFlags, depFlag)
directSharedLibDeps = append(directSharedLibDeps, ccDep)
mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName)
exportDep = true
@@ -650,10 +648,10 @@
// Make sure these dependencies are propagated
if lib, ok := mod.compiler.(*libraryDecorator); ok && exportDep {
lib.linkDirs = append(lib.linkDirs, linkPath)
- lib.depFlags = append(lib.depFlags, "-l"+libName)
+ lib.depFlags = append(lib.depFlags, depFlag)
} else if procMacro, ok := mod.compiler.(*procMacroDecorator); ok && exportDep {
procMacro.linkDirs = append(procMacro.linkDirs, linkPath)
- procMacro.depFlags = append(procMacro.depFlags, "-l"+libName)
+ procMacro.depFlags = append(procMacro.depFlags, depFlag)
}
}
@@ -705,13 +703,15 @@
func linkPathFromFilePath(filepath android.Path) string {
return strings.Split(filepath.String(), filepath.Base())[0]
}
+
func libNameFromFilePath(filepath android.Path) string {
- libName := strings.Split(filepath.Base(), filepath.Ext())[0]
+ libName := strings.TrimSuffix(filepath.Base(), filepath.Ext())
if strings.HasPrefix(libName, "lib") {
libName = libName[3:]
}
return libName
}
+
func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
ctx := &depsContext{
BottomUpMutatorContext: actx,
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 3be9ee7..020581d 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -22,6 +22,7 @@
"testing"
"android/soong/android"
+ "android/soong/cc"
)
var (
@@ -61,6 +62,8 @@
"libz.so": nil,
}
+ cc.GatherRequiredFilesForTest(fs)
+
return android.TestArchConfig(buildDir, nil, bp, fs)
}
@@ -114,13 +117,13 @@
// Test that we can extract the lib name from a lib path.
func TestLibNameFromFilePath(t *testing.T) {
- libBarPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so")
+ libBarPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so.so")
libLibPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/liblib.dylib.so")
libBarName := libNameFromFilePath(libBarPath)
libLibName := libNameFromFilePath(libLibPath)
- expectedResult := "bar"
+ expectedResult := "bar.so"
if libBarName != expectedResult {
t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libBarName)
}
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 4aaff9a..e848b50 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -3,7 +3,6 @@
main: "manifest_fixer.py",
srcs: [
"manifest_fixer.py",
- "manifest.py",
],
version: {
py2: {
@@ -13,6 +12,9 @@
enabled: false,
},
},
+ libs: [
+ "manifest_utils",
+ ],
}
python_test_host {
@@ -21,6 +23,24 @@
srcs: [
"manifest_fixer_test.py",
"manifest_fixer.py",
+ ],
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: false,
+ },
+ },
+ libs: [
+ "manifest_utils",
+ ],
+ test_suites: ["general-tests"],
+}
+
+python_library_host {
+ name: "manifest_utils",
+ srcs: [
"manifest.py",
],
version: {
@@ -31,7 +51,6 @@
enabled: false,
},
},
- test_suites: ["general-tests"],
}
python_binary_host {
@@ -39,7 +58,6 @@
main: "manifest_check.py",
srcs: [
"manifest_check.py",
- "manifest.py",
],
version: {
py2: {
@@ -49,6 +67,9 @@
enabled: false,
},
},
+ libs: [
+ "manifest_utils",
+ ],
}
python_test_host {
@@ -57,7 +78,6 @@
srcs: [
"manifest_check_test.py",
"manifest_check.py",
- "manifest.py",
],
version: {
py2: {
@@ -67,6 +87,9 @@
enabled: false,
},
},
+ libs: [
+ "manifest_utils",
+ ],
test_suites: ["general-tests"],
}
@@ -91,7 +114,6 @@
main: "test_config_fixer.py",
srcs: [
"test_config_fixer.py",
- "manifest.py",
],
version: {
py2: {
@@ -101,6 +123,9 @@
enabled: false,
},
},
+ libs: [
+ "manifest_utils",
+ ],
}
python_test_host {
@@ -109,7 +134,6 @@
srcs: [
"test_config_fixer_test.py",
"test_config_fixer.py",
- "manifest.py",
],
version: {
py2: {
@@ -119,5 +143,8 @@
enabled: false,
},
},
+ libs: [
+ "manifest_utils",
+ ],
test_suites: ["general-tests"],
-}
\ No newline at end of file
+}
diff --git a/scripts/jsonmodify.py b/scripts/jsonmodify.py
index 4b2c3c2..ba1109e 100755
--- a/scripts/jsonmodify.py
+++ b/scripts/jsonmodify.py
@@ -112,9 +112,10 @@
if args.out:
with open(args.out, "w") as f:
- json.dump(obj, f, indent=2)
+ json.dump(obj, f, indent=2, separators=(',', ': '))
+ f.write('\n')
else:
- print(json.dumps(obj, indent=2))
+ print(json.dumps(obj, indent=2, separators=(',', ': ')))
if __name__ == '__main__':
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index 945bc18..c59732b 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -51,6 +51,9 @@
help='specify additional <uses-library> tag to add. android:requred is set to false')
parser.add_argument('--uses-non-sdk-api', dest='uses_non_sdk_api', action='store_true',
help='manifest is for a package built against the platform')
+ parser.add_argument('--logging-parent', dest='logging_parent', default='',
+ help=('specify logging parent as an additional <meta-data> tag. '
+ 'This value is ignored if the logging_parent meta-data tag is present.'))
parser.add_argument('--use-embedded-dex', dest='use_embedded_dex', action='store_true',
help=('specify if the app wants to use embedded dex and avoid extracted,'
'locally compiled code. Must not conflict if already declared '
@@ -124,6 +127,52 @@
element.setAttributeNode(target_attr)
+def add_logging_parent(doc, logging_parent_value):
+ """Add logging parent as an additional <meta-data> tag.
+
+ Args:
+ doc: The XML document. May be modified by this function.
+ logging_parent_value: A string representing the logging
+ parent value.
+ Raises:
+ RuntimeError: Invalid manifest
+ """
+ manifest = parse_manifest(doc)
+
+ logging_parent_key = 'android.content.pm.LOGGING_PARENT'
+ elems = get_children_with_tag(manifest, 'application')
+ application = elems[0] if len(elems) == 1 else None
+ if len(elems) > 1:
+ raise RuntimeError('found multiple <application> tags')
+ elif not elems:
+ application = doc.createElement('application')
+ indent = get_indent(manifest.firstChild, 1)
+ first = manifest.firstChild
+ manifest.insertBefore(doc.createTextNode(indent), first)
+ manifest.insertBefore(application, first)
+
+ indent = get_indent(application.firstChild, 2)
+
+ last = application.lastChild
+ if last is not None and last.nodeType != minidom.Node.TEXT_NODE:
+ last = None
+
+ if not find_child_with_attribute(application, 'meta-data', android_ns,
+ 'name', logging_parent_key):
+ ul = doc.createElement('meta-data')
+ ul.setAttributeNS(android_ns, 'android:name', logging_parent_key)
+ ul.setAttributeNS(android_ns, 'android:value', logging_parent_value)
+ application.insertBefore(doc.createTextNode(indent), last)
+ application.insertBefore(ul, last)
+ last = application.lastChild
+
+ # align the closing tag with the opening tag if it's not
+ # indented
+ if last and last.nodeType != minidom.Node.TEXT_NODE:
+ indent = get_indent(application.previousSibling, 1)
+ application.appendChild(doc.createTextNode(indent))
+
+
def add_uses_libraries(doc, new_uses_libraries, required):
"""Add additional <uses-library> tags
@@ -291,6 +340,9 @@
if args.uses_non_sdk_api:
add_uses_non_sdk_api(doc)
+ if args.logging_parent:
+ add_logging_parent(doc, args.logging_parent)
+
if args.use_embedded_dex:
add_use_embedded_dex(doc)
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
index ea8095e..d6e7f26 100755
--- a/scripts/manifest_fixer_test.py
+++ b/scripts/manifest_fixer_test.py
@@ -226,6 +226,47 @@
self.assertEqual(output, expected)
+class AddLoggingParentTest(unittest.TestCase):
+ """Unit tests for add_logging_parent function."""
+
+ def add_logging_parent_test(self, input_manifest, logging_parent=None):
+ doc = minidom.parseString(input_manifest)
+ if logging_parent:
+ manifest_fixer.add_logging_parent(doc, logging_parent)
+ output = StringIO.StringIO()
+ manifest_fixer.write_xml(output, doc)
+ return output.getvalue()
+
+ manifest_tmpl = (
+ '<?xml version="1.0" encoding="utf-8"?>\n'
+ '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
+ '%s'
+ '</manifest>\n')
+
+ def uses_logging_parent(self, logging_parent=None):
+ attrs = ''
+ if logging_parent:
+ meta_text = ('<meta-data android:name="android.content.pm.LOGGING_PARENT" '
+ 'android:value="%s"/>\n') % (logging_parent)
+ attrs += ' <application>\n %s </application>\n' % (meta_text)
+
+ return attrs
+
+ def test_no_logging_parent(self):
+ """Tests manifest_fixer with no logging_parent."""
+ manifest_input = self.manifest_tmpl % ''
+ expected = self.manifest_tmpl % self.uses_logging_parent()
+ output = self.add_logging_parent_test(manifest_input)
+ self.assertEqual(output, expected)
+
+ def test_logging_parent(self):
+ """Tests manifest_fixer with no logging_parent."""
+ manifest_input = self.manifest_tmpl % ''
+ expected = self.manifest_tmpl % self.uses_logging_parent('FOO')
+ output = self.add_logging_parent_test(manifest_input, 'FOO')
+ self.assertEqual(output, expected)
+
+
class AddUsesLibrariesTest(unittest.TestCase):
"""Unit tests for add_uses_libraries function."""
diff --git a/sdk/bp.go b/sdk/bp.go
index 6936daf..c2a75e4 100644
--- a/sdk/bp.go
+++ b/sdk/bp.go
@@ -48,8 +48,7 @@
}
func (s *bpPropertySet) AddPropertySet(name string) android.BpPropertySet {
- set := &bpPropertySet{}
- set.init()
+ set := newPropertySet()
s.AddProperty(name, set)
return set
}
@@ -62,7 +61,7 @@
return s.tags[name]
}
-func (s *bpPropertySet) transform(transformer bpPropertyTransformer) {
+func (s *bpPropertySet) transformContents(transformer bpPropertyTransformer) {
var newOrder []string
for _, name := range s.order {
value := s.properties[name]
@@ -70,7 +69,13 @@
var newValue interface{}
var newTag android.BpPropertyTag
if propertySet, ok := value.(*bpPropertySet); ok {
- newValue, newTag = transformer.transformPropertySet(name, propertySet, tag)
+ var newPropertySet *bpPropertySet
+ newPropertySet, newTag = transformPropertySet(transformer, name, propertySet, tag)
+ if newPropertySet == nil {
+ newValue = nil
+ } else {
+ newValue = newPropertySet
+ }
} else {
newValue, newTag = transformer.transformProperty(name, value, tag)
}
@@ -88,6 +93,16 @@
s.order = newOrder
}
+func transformPropertySet(transformer bpPropertyTransformer, name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
+ newPropertySet, newTag := transformer.transformPropertySetBeforeContents(name, propertySet, tag)
+ if newPropertySet != nil {
+ newPropertySet.transformContents(transformer)
+
+ newPropertySet, newTag = transformer.transformPropertySetAfterContents(name, newPropertySet, newTag)
+ }
+ return newPropertySet, newTag
+}
+
func (s *bpPropertySet) setProperty(name string, value interface{}) {
if s.properties[name] == nil {
s.AddProperty(name, value)
@@ -136,7 +151,17 @@
// The name will be "" for the top level property set.
//
// Returning (nil, ...) will cause the property set to be removed.
- transformPropertySet(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag)
+ transformPropertySetBeforeContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag)
+
+ // Transform the property set, returning the new property set/tag to insert back into the
+ // parent property set (or module if this is the top level property set).
+ //
+ // This will be called after transforming the properties in the supplied set.
+ //
+ // The name will be "" for the top level property set.
+ //
+ // Returning (nil, ...) will cause the property set to be removed.
+ transformPropertySetAfterContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag)
// Transform a property, return the new value/tag to insert back into the property set.
//
@@ -165,7 +190,11 @@
return module
}
-func (t identityTransformation) transformPropertySet(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
+func (t identityTransformation) transformPropertySetBeforeContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
+ return propertySet, tag
+}
+
+func (t identityTransformation) transformPropertySetAfterContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
return propertySet, tag
}
@@ -180,12 +209,13 @@
func (m *bpModule) transform(transformer bpTransformer) *bpModule {
transformedModule := transformer.transformModule(m)
// Copy the contents of the returned property set into the module and then transform that.
- transformedModule.bpPropertySet, _ = transformer.transformPropertySet("", transformedModule.bpPropertySet, nil)
- transformedModule.bpPropertySet.transform(transformer)
+ transformedModule.bpPropertySet, _ = transformPropertySet(transformer, "", transformedModule.bpPropertySet, nil)
return transformedModule
}
-type deepCopyTransformation struct{}
+type deepCopyTransformation struct {
+ identityTransformation
+}
func (t deepCopyTransformation) transformModule(module *bpModule) *bpModule {
// Take a shallow copy of the module. Any mutable property values will be copied by the
@@ -194,7 +224,7 @@
return &moduleCopy
}
-func (t deepCopyTransformation) transformPropertySet(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
+func (t deepCopyTransformation) transformPropertySetBeforeContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
// Create a shallow copy of the properties map. Any mutable property values will be copied by the
// transformer.
propertiesCopy := make(map[string]interface{})
@@ -253,10 +283,19 @@
}
func (f *bpFile) newModule(moduleType string) *bpModule {
+ return newModule(moduleType)
+}
+
+func newModule(moduleType string) *bpModule {
module := &bpModule{
moduleType: moduleType,
- bpPropertySet: &bpPropertySet{},
+ bpPropertySet: newPropertySet(),
}
- module.bpPropertySet.init()
return module
}
+
+func newPropertySet() *bpPropertySet {
+ set := &bpPropertySet{}
+ set.init()
+ return set
+}
diff --git a/sdk/bp_test.go b/sdk/bp_test.go
new file mode 100644
index 0000000..f89f38c
--- /dev/null
+++ b/sdk/bp_test.go
@@ -0,0 +1,76 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// 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 sdk
+
+import (
+ "testing"
+
+ "android/soong/android"
+)
+
+type removeFredTransformation struct {
+ identityTransformation
+}
+
+func (t removeFredTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) {
+ if name == "fred" {
+ return nil, nil
+ }
+ return value, tag
+}
+
+func (t removeFredTransformation) transformPropertySetBeforeContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
+ if name == "fred" {
+ return nil, nil
+ }
+ return propertySet, tag
+}
+
+func (t removeFredTransformation) transformPropertySetAfterContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
+ if len(propertySet.properties) == 0 {
+ return nil, nil
+ }
+ return propertySet, tag
+}
+
+func TestTransformRemoveProperty(t *testing.T) {
+
+ helper := &TestHelper{t}
+
+ set := newPropertySet()
+ set.AddProperty("name", "name")
+ set.AddProperty("fred", "12")
+
+ set.transformContents(removeFredTransformation{})
+
+ contents := &generatedContents{}
+ outputPropertySet(contents, set)
+ helper.AssertTrimmedStringEquals("removing property failed", "name: \"name\",\\n", contents.content.String())
+}
+
+func TestTransformRemovePropertySet(t *testing.T) {
+
+ helper := &TestHelper{t}
+
+ set := newPropertySet()
+ set.AddProperty("name", "name")
+ set.AddPropertySet("fred")
+
+ set.transformContents(removeFredTransformation{})
+
+ contents := &generatedContents{}
+ outputPropertySet(contents, set)
+ helper.AssertTrimmedStringEquals("removing property set failed", "name: \"name\",\\n", contents.content.String())
+}
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 9a75610..ecb1da0 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -75,6 +75,7 @@
cc_library_shared {
name: "sdkmember",
+ system_shared_libs: [],
}
sdk_snapshot {
@@ -337,6 +338,68 @@
)
}
+func TestSnapshotWithCcBinary(t *testing.T) {
+ result := testSdkWithCc(t, `
+ module_exports {
+ name: "mymodule_exports",
+ native_binaries: ["mynativebinary"],
+ }
+
+ cc_binary {
+ name: "mynativebinary",
+ srcs: [
+ "Test.cpp",
+ ],
+ compile_multilib: "both",
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+
+ result.CheckSnapshot("mymodule_exports", "android_common", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_binary {
+ name: "mymodule_exports_mynativebinary@current",
+ sdk_member_name: "mynativebinary",
+ compile_multilib: "both",
+ arch: {
+ arm64: {
+ srcs: ["arm64/bin/mynativebinary"],
+ },
+ arm: {
+ srcs: ["arm/bin/mynativebinary"],
+ },
+ },
+}
+
+cc_prebuilt_binary {
+ name: "mynativebinary",
+ prefer: false,
+ compile_multilib: "both",
+ arch: {
+ arm64: {
+ srcs: ["arm64/bin/mynativebinary"],
+ },
+ arm: {
+ srcs: ["arm/bin/mynativebinary"],
+ },
+ },
+}
+
+module_exports_snapshot {
+ name: "mymodule_exports@current",
+ native_binaries: ["mymodule_exports_mynativebinary@current"],
+}
+`),
+ checkAllCopyRules(`
+.intermediates/mynativebinary/android_arm64_armv8-a/mynativebinary -> arm64/bin/mynativebinary
+.intermediates/mynativebinary/android_arm_armv7-a-neon/mynativebinary -> arm/bin/mynativebinary
+`),
+ )
+}
+
func TestSnapshotWithCcSharedLibrary(t *testing.T) {
result := testSdkWithCc(t, `
sdk {
@@ -686,3 +749,199 @@
`),
)
}
+
+func TestHostSnapshotWithMultiLib64(t *testing.T) {
+ // b/145598135 - Generating host snapshots for anything other than linux is not supported.
+ SkipIfNotLinux(t)
+
+ result := testSdkWithCc(t, `
+ module_exports {
+ name: "myexports",
+ device_supported: false,
+ host_supported: true,
+ target: {
+ host: {
+ compile_multilib: "64",
+ },
+ },
+ native_static_libs: ["mynativelib"],
+ }
+
+ cc_library_static {
+ name: "mynativelib",
+ device_supported: false,
+ host_supported: true,
+ srcs: [
+ "Test.cpp",
+ "aidl/foo/bar/Test.aidl",
+ ],
+ export_include_dirs: ["include"],
+ aidl: {
+ export_aidl_headers: true,
+ },
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+
+ result.CheckSnapshot("myexports", "linux_glibc_common", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_static {
+ name: "myexports_mynativelib@current",
+ sdk_member_name: "mynativelib",
+ device_supported: false,
+ host_supported: true,
+ export_include_dirs: ["include/include"],
+ arch: {
+ x86_64: {
+ srcs: ["x86_64/lib/mynativelib.a"],
+ export_include_dirs: ["x86_64/include_gen/mynativelib"],
+ },
+ },
+ stl: "none",
+ system_shared_libs: [],
+}
+
+cc_prebuilt_library_static {
+ name: "mynativelib",
+ prefer: false,
+ device_supported: false,
+ host_supported: true,
+ export_include_dirs: ["include/include"],
+ arch: {
+ x86_64: {
+ srcs: ["x86_64/lib/mynativelib.a"],
+ export_include_dirs: ["x86_64/include_gen/mynativelib"],
+ },
+ },
+ stl: "none",
+ system_shared_libs: [],
+}
+
+module_exports_snapshot {
+ name: "myexports@current",
+ device_supported: false,
+ host_supported: true,
+ target: {
+ host: {
+ compile_multilib: "64",
+ },
+ },
+ native_static_libs: ["myexports_mynativelib@current"],
+}`),
+ checkAllCopyRules(`
+include/Test.h -> include/include/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/mynativelib.a -> x86_64/lib/mynativelib.a
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+`),
+ )
+}
+
+func TestSnapshotWithCcHeadersLibrary(t *testing.T) {
+ result := testSdkWithCc(t, `
+ sdk {
+ name: "mysdk",
+ native_header_libs: ["mynativeheaders"],
+ }
+
+ cc_library_headers {
+ name: "mynativeheaders",
+ export_include_dirs: ["include"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "android_common", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_headers {
+ name: "mysdk_mynativeheaders@current",
+ sdk_member_name: "mynativeheaders",
+ export_include_dirs: ["include/include"],
+ stl: "none",
+ system_shared_libs: [],
+}
+
+cc_prebuilt_library_headers {
+ name: "mynativeheaders",
+ prefer: false,
+ export_include_dirs: ["include/include"],
+ stl: "none",
+ system_shared_libs: [],
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ native_header_libs: ["mysdk_mynativeheaders@current"],
+}
+`),
+ checkAllCopyRules(`
+include/Test.h -> include/include/Test.h
+`),
+ )
+}
+
+func TestHostSnapshotWithCcHeadersLibrary(t *testing.T) {
+ // b/145598135 - Generating host snapshots for anything other than linux is not supported.
+ SkipIfNotLinux(t)
+
+ result := testSdkWithCc(t, `
+ sdk {
+ name: "mysdk",
+ device_supported: false,
+ host_supported: true,
+ native_header_libs: ["mynativeheaders"],
+ }
+
+ cc_library_headers {
+ name: "mynativeheaders",
+ device_supported: false,
+ host_supported: true,
+ export_include_dirs: ["include"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "linux_glibc_common", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_headers {
+ name: "mysdk_mynativeheaders@current",
+ sdk_member_name: "mynativeheaders",
+ device_supported: false,
+ host_supported: true,
+ export_include_dirs: ["include/include"],
+ stl: "none",
+ system_shared_libs: [],
+}
+
+cc_prebuilt_library_headers {
+ name: "mynativeheaders",
+ prefer: false,
+ device_supported: false,
+ host_supported: true,
+ export_include_dirs: ["include/include"],
+ stl: "none",
+ system_shared_libs: [],
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ device_supported: false,
+ host_supported: true,
+ native_header_libs: ["mysdk_mynativeheaders@current"],
+}
+`),
+ checkAllCopyRules(`
+include/Test.h -> include/include/Test.h
+`),
+ )
+}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 692c205..0737e5e 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -34,7 +34,7 @@
result := testSdkWithJava(t, `
sdk {
name: "mysdk",
- java_header_libs: ["myjavalib"],
+ java_header_libs: ["sdkmember"],
}
sdk_snapshot {
@@ -47,22 +47,36 @@
java_header_libs: ["sdkmember_mysdk_2"],
}
- java_import {
+ java_library {
name: "sdkmember",
- prefer: false,
+ srcs: ["Test.java"],
+ system_modules: "none",
+ sdk_version: "none",
host_supported: true,
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
}
java_import {
name: "sdkmember_mysdk_1",
sdk_member_name: "sdkmember",
host_supported: true,
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
}
java_import {
name: "sdkmember_mysdk_2",
sdk_member_name: "sdkmember",
host_supported: true,
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
}
java_library {
@@ -569,3 +583,170 @@
checkMergeZip(".intermediates/myexports/linux_glibc_common/tmp/java/myjavaapistubs_stubs_sources.zip"),
)
}
+
+func TestSnapshotWithJavaSystemModules(t *testing.T) {
+ result := testSdkWithJava(t, `
+ sdk {
+ name: "mysdk",
+ java_header_libs: ["exported-system-module"],
+ java_system_modules: ["my-system-modules"],
+ }
+
+ java_system_modules {
+ name: "my-system-modules",
+ libs: ["system-module", "exported-system-module"],
+ }
+
+ java_library {
+ name: "system-module",
+ srcs: ["Test.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ }
+
+ java_library {
+ name: "exported-system-module",
+ srcs: ["Test.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "android_common", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_import {
+ name: "mysdk_exported-system-module@current",
+ sdk_member_name: "exported-system-module",
+ jars: ["java/exported-system-module.jar"],
+}
+
+java_import {
+ name: "exported-system-module",
+ prefer: false,
+ jars: ["java/exported-system-module.jar"],
+}
+
+java_import {
+ name: "mysdk_system-module@current",
+ sdk_member_name: "system-module",
+ visibility: ["//visibility:private"],
+ jars: ["java/system-module.jar"],
+}
+
+java_import {
+ name: "mysdk_system-module",
+ prefer: false,
+ visibility: ["//visibility:private"],
+ jars: ["java/system-module.jar"],
+}
+
+java_system_modules_import {
+ name: "mysdk_my-system-modules@current",
+ sdk_member_name: "my-system-modules",
+ libs: [
+ "mysdk_system-module@current",
+ "mysdk_exported-system-module@current",
+ ],
+}
+
+java_system_modules_import {
+ name: "my-system-modules",
+ prefer: false,
+ libs: [
+ "mysdk_system-module",
+ "exported-system-module",
+ ],
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ java_header_libs: ["mysdk_exported-system-module@current"],
+ java_system_modules: ["mysdk_my-system-modules@current"],
+}
+`),
+ checkAllCopyRules(`
+.intermediates/exported-system-module/android_common/turbine-combined/exported-system-module.jar -> java/exported-system-module.jar
+.intermediates/system-module/android_common/turbine-combined/system-module.jar -> java/system-module.jar
+`),
+ )
+}
+
+func TestHostSnapshotWithJavaSystemModules(t *testing.T) {
+ // b/145598135 - Generating host snapshots for anything other than linux is not supported.
+ SkipIfNotLinux(t)
+
+ result := testSdkWithJava(t, `
+ sdk {
+ name: "mysdk",
+ device_supported: false,
+ host_supported: true,
+ java_system_modules: ["my-system-modules"],
+ }
+
+ java_system_modules {
+ name: "my-system-modules",
+ device_supported: false,
+ host_supported: true,
+ libs: ["system-module"],
+ }
+
+ java_library {
+ name: "system-module",
+ device_supported: false,
+ host_supported: true,
+ srcs: ["Test.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "linux_glibc_common", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_import {
+ name: "mysdk_system-module@current",
+ sdk_member_name: "system-module",
+ visibility: ["//visibility:private"],
+ device_supported: false,
+ host_supported: true,
+ jars: ["java/system-module.jar"],
+}
+
+java_import {
+ name: "mysdk_system-module",
+ prefer: false,
+ visibility: ["//visibility:private"],
+ device_supported: false,
+ host_supported: true,
+ jars: ["java/system-module.jar"],
+}
+
+java_system_modules_import {
+ name: "mysdk_my-system-modules@current",
+ sdk_member_name: "my-system-modules",
+ device_supported: false,
+ host_supported: true,
+ libs: ["mysdk_system-module@current"],
+}
+
+java_system_modules_import {
+ name: "my-system-modules",
+ prefer: false,
+ device_supported: false,
+ host_supported: true,
+ libs: ["mysdk_system-module"],
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ device_supported: false,
+ host_supported: true,
+ java_system_modules: ["mysdk_my-system-modules@current"],
+}
+`),
+ checkAllCopyRules(".intermediates/system-module/linux_glibc_common/javac/system-module.jar -> java/system-module.jar"),
+ )
+}
diff --git a/sdk/sdk.go b/sdk/sdk.go
index f22763c..c194ac1 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -50,6 +50,9 @@
// list properties, e.g. java_libs.
dynamicMemberTypeListProperties interface{}
+ // The set of exported members.
+ exportedMembers map[string]struct{}
+
properties sdkProperties
snapshotFile android.OptionalPath
@@ -217,6 +220,33 @@
return s
}
+func (s *sdk) memberListProperties() []*sdkMemberListProperty {
+ return s.dynamicSdkMemberTypes.memberListProperties
+}
+
+func (s *sdk) getExportedMembers() map[string]struct{} {
+ if s.exportedMembers == nil {
+ // Collect all the exported members.
+ s.exportedMembers = make(map[string]struct{})
+
+ for _, memberListProperty := range s.memberListProperties() {
+ names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
+
+ // Every member specified explicitly in the properties is exported by the sdk.
+ for _, name := range names {
+ s.exportedMembers[name] = struct{}{}
+ }
+ }
+ }
+
+ return s.exportedMembers
+}
+
+func (s *sdk) isInternalMember(memberName string) bool {
+ _, ok := s.getExportedMembers()[memberName]
+ return !ok
+}
+
func (s *sdk) snapshot() bool {
return s.properties.Snapshot
}
@@ -290,10 +320,14 @@
// Step 1: create dependencies from an SDK module to its members.
func memberMutator(mctx android.BottomUpMutatorContext) {
if s, ok := mctx.Module().(*sdk); ok {
- for _, memberListProperty := range s.dynamicSdkMemberTypes.memberListProperties {
- names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
- tag := memberListProperty.dependencyTag
- memberListProperty.memberType.AddDependencies(mctx, tag, names)
+ if s.Enabled() {
+ for _, memberListProperty := range s.memberListProperties() {
+ names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
+ if len(names) > 0 {
+ tag := memberListProperty.dependencyTag
+ memberListProperty.memberType.AddDependencies(mctx, tag, names)
+ }
+ }
}
}
}
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index d376e59..934bdae 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -111,8 +111,14 @@
sdk_version: "none",
}
+ java_defaults {
+ name: "java-defaults",
+ visibility: ["//other/bar"],
+ }
+
java_library {
name: "mypublicjavalib",
+ defaults: ["java-defaults"],
visibility: ["//visibility:public"],
srcs: ["Test.java"],
system_modules: "none",
diff --git a/sdk/testing.go b/sdk/testing.go
index c9cc30f..7352c74 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -53,12 +53,20 @@
"myapex.pk8": nil,
}
+ cc.GatherRequiredFilesForTest(mockFS)
+
for k, v := range fs {
mockFS[k] = v
}
config := android.TestArchConfig(buildDir, nil, bp, mockFS)
+ // Add windows as a default disable OS to test behavior when some OS variants
+ // are disabled.
+ config.Targets[android.Windows] = []android.Target{
+ {android.Windows, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", ""},
+ }
+
ctx := android.NewTestArchContext()
// from android package
@@ -72,6 +80,7 @@
java.RegisterJavaBuildComponents(ctx)
java.RegisterAppBuildComponents(ctx)
java.RegisterStubsBuildComponents(ctx)
+ java.RegisterSystemModulesBuildComponents(ctx)
// from cc package
cc.RegisterRequiredBuildComponentsForTest(ctx)
diff --git a/sdk/update.go b/sdk/update.go
index 97bafa1..d211e80 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -105,24 +105,28 @@
// Collect all the members.
//
// The members are first grouped by type and then grouped by name. The order of
-// the types is the order they are referenced in android.SdkMemberTypes. The
-// names are in order in which the dependencies were added.
-func (s *sdk) collectMembers(ctx android.ModuleContext) []*sdkMember {
+// the types is the order they are referenced in android.SdkMemberTypesRegistry.
+// The names are in the order in which the dependencies were added.
+//
+// Returns the members as well as the multilib setting to use.
+func (s *sdk) collectMembers(ctx android.ModuleContext) ([]*sdkMember, string) {
byType := make(map[android.SdkMemberType][]*sdkMember)
byName := make(map[string]*sdkMember)
- ctx.VisitDirectDeps(func(m android.Module) {
- tag := ctx.OtherModuleDependencyTag(m)
+ lib32 := false // True if any of the members have 32 bit version.
+ lib64 := false // True if any of the members have 64 bit version.
+
+ ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
+ tag := ctx.OtherModuleDependencyTag(child)
if memberTag, ok := tag.(android.SdkMemberTypeDependencyTag); ok {
memberType := memberTag.SdkMemberType()
// Make sure that the resolved module is allowed in the member list property.
- if !memberType.IsInstance(m) {
- ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(m), memberType.SdkPropertyName())
+ if !memberType.IsInstance(child) {
+ ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(child), memberType.SdkPropertyName())
}
- name := ctx.OtherModuleName(m)
-
+ name := ctx.OtherModuleName(child)
member := byName[name]
if member == nil {
member = &sdkMember{memberType: memberType, name: name}
@@ -130,17 +134,51 @@
byType[memberType] = append(byType[memberType], member)
}
- member.variants = append(member.variants, m.(android.SdkAware))
+ multilib := child.Target().Arch.ArchType.Multilib
+ if multilib == "lib32" {
+ lib32 = true
+ } else if multilib == "lib64" {
+ lib64 = true
+ }
+
+ // Only append new variants to the list. This is needed because a member can be both
+ // exported by the sdk and also be a transitive sdk member.
+ member.variants = appendUniqueVariants(member.variants, child.(android.SdkAware))
+
+ // If the member type supports transitive sdk members then recurse down into
+ // its dependencies, otherwise exit traversal.
+ return memberType.HasTransitiveSdkMembers()
}
+
+ return false
})
var members []*sdkMember
- for _, memberListProperty := range s.dynamicSdkMemberTypes.memberListProperties {
+ for _, memberListProperty := range s.memberListProperties() {
membersOfType := byType[memberListProperty.memberType]
members = append(members, membersOfType...)
}
- return members
+ // Compute the setting of multilib.
+ var multilib string
+ if lib32 && lib64 {
+ multilib = "both"
+ } else if lib32 {
+ multilib = "32"
+ } else if lib64 {
+ multilib = "64"
+ }
+
+ return members, multilib
+}
+
+func appendUniqueVariants(variants []android.SdkAware, newVariant android.SdkAware) []android.SdkAware {
+ for _, v := range variants {
+ if v == newVariant {
+ return variants
+ }
+ }
+ return append(variants, newVariant)
}
// SDK directory structure
@@ -190,24 +228,31 @@
}
s.builderForTests = builder
- for _, member := range s.collectMembers(ctx) {
+ members, multilib := s.collectMembers(ctx)
+ for _, member := range members {
member.memberType.BuildSnapshot(ctx, builder, member)
}
// Create a transformer that will transform an unversioned module into a versioned module.
unversionedToVersionedTransformer := unversionedToVersionedTransformation{builder: builder}
+ // Create a transformer that will transform an unversioned module by replacing any references
+ // to internal members with a unique module name and setting prefer: false.
+ unversionedTransformer := unversionedTransformation{builder: builder}
+
for _, unversioned := range builder.prebuiltOrder {
+ // Prune any empty property sets.
+ unversioned = unversioned.transform(pruneEmptySetTransformer{})
+
// Copy the unversioned module so it can be modified to make it versioned.
versioned := unversioned.deepCopy()
// Transform the unversioned module into a versioned one.
versioned.transform(unversionedToVersionedTransformer)
-
bpFile.AddModule(versioned)
- // Set prefer: false - this is not strictly required as that is the default.
- unversioned.insertAfter("name", "prefer", false)
+ // Transform the unversioned module to make it suitable for use in the snapshot.
+ unversioned.transform(unversionedTransformer)
bpFile.AddModule(unversioned)
}
@@ -229,7 +274,17 @@
}
addHostDeviceSupportedProperties(&s.ModuleBase, snapshotModule)
- for _, memberListProperty := range s.dynamicSdkMemberTypes.memberListProperties {
+
+ // Compile_multilib defaults to both and must always be set to both on the
+ // device and so only needs to be set when targeted at the host and is neither
+ // unspecified or both.
+ if s.HostSupported() && multilib != "" && multilib != "both" {
+ targetSet := snapshotModule.AddPropertySet("target")
+ hostSet := targetSet.AddPropertySet("host")
+ hostSet.AddProperty("compile_multilib", multilib)
+ }
+
+ for _, memberListProperty := range s.memberListProperties() {
names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
if len(names) > 0 {
snapshotModule.AddProperty(memberListProperty.propertyName(), builder.versionedSdkMemberNames(names))
@@ -285,13 +340,17 @@
return outputZipFile
}
+type propertyTag struct {
+ name string
+}
+
+var sdkMemberReferencePropertyTag = propertyTag{"sdkMemberReferencePropertyTag"}
+
type unversionedToVersionedTransformation struct {
identityTransformation
builder *snapshotBuilder
}
-var _ bpTransformer = (*unversionedToVersionedTransformation)(nil)
-
func (t unversionedToVersionedTransformation) transformModule(module *bpModule) *bpModule {
// Use a versioned name for the module but remember the original name for the
// snapshot.
@@ -301,6 +360,52 @@
return module
}
+func (t unversionedToVersionedTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) {
+ if tag == sdkMemberReferencePropertyTag {
+ return t.builder.versionedSdkMemberNames(value.([]string)), tag
+ } else {
+ return value, tag
+ }
+}
+
+type unversionedTransformation struct {
+ identityTransformation
+ builder *snapshotBuilder
+}
+
+func (t unversionedTransformation) transformModule(module *bpModule) *bpModule {
+ // If the module is an internal member then use a unique name for it.
+ name := module.getValue("name").(string)
+ module.setProperty("name", t.builder.unversionedSdkMemberName(name))
+
+ // Set prefer: false - this is not strictly required as that is the default.
+ module.insertAfter("name", "prefer", false)
+
+ return module
+}
+
+func (t unversionedTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) {
+ if tag == sdkMemberReferencePropertyTag {
+ return t.builder.unversionedSdkMemberNames(value.([]string)), tag
+ } else {
+ return value, tag
+ }
+}
+
+type pruneEmptySetTransformer struct {
+ identityTransformation
+}
+
+var _ bpTransformer = (*pruneEmptySetTransformer)(nil)
+
+func (t pruneEmptySetTransformer) transformPropertySetAfterContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
+ if len(propertySet.properties) == 0 {
+ return nil, nil
+ } else {
+ return propertySet, tag
+ }
+}
+
func generateBpContents(contents *generatedContents, bpFile *bpFile) {
contents.Printfln("// This is auto-generated. DO NOT EDIT.")
for _, bpModule := range bpFile.order {
@@ -424,11 +529,17 @@
m := s.bpFile.newModule(moduleType)
m.AddProperty("name", name)
- // Extract visibility information from a member variant. All variants have the same
- // visibility so it doesn't matter which one is used.
- visibility := android.EffectiveVisibilityRules(s.ctx, member.Variants()[0])
- if len(visibility) != 0 {
- m.AddProperty("visibility", visibility)
+ if s.sdk.isInternalMember(name) {
+ // An internal member is only referenced from the sdk snapshot which is in the
+ // same package so can be marked as private.
+ m.AddProperty("visibility", []string{"//visibility:private"})
+ } else {
+ // Extract visibility information from a member variant. All variants have the same
+ // visibility so it doesn't matter which one is used.
+ visibility := android.EffectiveVisibilityRules(s.ctx, member.Variants()[0])
+ if len(visibility) != 0 {
+ m.AddProperty("visibility", visibility)
+ }
}
addHostDeviceSupportedProperties(&s.sdk.ModuleBase, m)
@@ -447,6 +558,10 @@
}
}
+func (s *snapshotBuilder) SdkMemberReferencePropertyTag() android.BpPropertyTag {
+ return sdkMemberReferencePropertyTag
+}
+
// Get a versioned name appropriate for the SDK snapshot version being taken.
func (s *snapshotBuilder) versionedSdkMemberName(unversionedName string) string {
return versionedSdkMemberName(s.ctx, unversionedName, s.version)
@@ -460,6 +575,23 @@
return references
}
+// Get an internal name unique to the sdk.
+func (s *snapshotBuilder) unversionedSdkMemberName(unversionedName string) string {
+ if s.sdk.isInternalMember(unversionedName) {
+ return s.ctx.ModuleName() + "_" + unversionedName
+ } else {
+ return unversionedName
+ }
+}
+
+func (s *snapshotBuilder) unversionedSdkMemberNames(members []string) []string {
+ var references []string = nil
+ for _, m := range members {
+ references = append(references, s.unversionedSdkMemberName(m))
+ }
+ return references
+}
+
var _ android.SdkMember = (*sdkMember)(nil)
type sdkMember struct {
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index ce404f8..65dbb22 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -144,6 +144,9 @@
// list of .sysprop files which defines the properties.
Srcs []string `android:"path"`
+ // If set to true, build a variant of the module for the host. Defaults to false.
+ Host_supported *bool
+
// Whether public stub exists or not.
Public_stub *bool `blueprint:"mutated"`
}
@@ -306,12 +309,20 @@
Sysprop struct {
Platform *bool
}
- Header_libs []string
- Shared_libs []string
+ Target struct {
+ Android struct {
+ Header_libs []string
+ Shared_libs []string
+ }
+ Host struct {
+ Static_libs []string
+ }
+ }
Required []string
Recovery *bool
Recovery_available *bool
Vendor_available *bool
+ Host_supported *bool
}
type javaLibraryProperties struct {
@@ -394,10 +405,12 @@
ccProps.Device_specific = proptools.BoolPtr(ctx.DeviceSpecific())
ccProps.Product_specific = proptools.BoolPtr(ctx.ProductSpecific())
ccProps.Sysprop.Platform = proptools.BoolPtr(isOwnerPlatform)
- ccProps.Header_libs = []string{"libbase_headers"}
- ccProps.Shared_libs = []string{"liblog"}
+ ccProps.Target.Android.Header_libs = []string{"libbase_headers"}
+ ccProps.Target.Android.Shared_libs = []string{"liblog"}
+ ccProps.Target.Host.Static_libs = []string{"libbase", "liblog"}
ccProps.Recovery_available = m.properties.Recovery_available
ccProps.Vendor_available = m.properties.Vendor_available
+ ccProps.Host_supported = m.properties.Host_supported
ctx.CreateModule(cc.LibraryFactory, &ccProps)
scope := "internal"
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 7cad3da..51da222 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -161,6 +161,7 @@
api_packages: ["android.sysprop"],
property_owner: "Platform",
vendor_available: true,
+ host_supported: true,
}
sysprop_library {
@@ -244,6 +245,11 @@
static_libs: ["sysprop-platform", "sysprop-vendor"],
}
+ cc_library {
+ name: "libbase",
+ host_supported: true,
+ }
+
cc_library_headers {
name: "libbase_headers",
vendor_available: true,
@@ -256,6 +262,12 @@
nocrt: true,
system_shared_libs: [],
recovery_available: true,
+ host_supported: true,
+ }
+
+ cc_binary_host {
+ name: "hostbin",
+ static_libs: ["sysprop-platform"],
}
llndk_library {
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index c35d8b9..a46dce9 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -44,17 +44,16 @@
CommandDeps: []string{"$template"},
}, "name", "template", "extraConfigs")
-func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string, autoGenConfig *bool) (path android.Path, autogenPath android.WritablePath) {
+func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string, autoGenConfig *bool, testConfigTemplateProp *string) (path android.Path, autogenPath android.WritablePath) {
p := getTestConfig(ctx, prop)
if !Bool(autoGenConfig) && p != nil {
return p, nil
- } else if !android.InList("cts", testSuites) && BoolDefault(autoGenConfig, true) {
+ } else if BoolDefault(autoGenConfig, true) && (!android.InList("cts", testSuites) || testConfigTemplateProp != nil) {
outputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".config")
return nil, outputFile
} else {
// CTS modules can be used for test data, so test config files must be
- // explicitly created using AndroidTest.xml
- // TODO(b/112602712): remove the path check
+ // explicitly created using AndroidTest.xml or test_config_template.
return nil, nil
}
}
@@ -130,7 +129,7 @@
func AutoGenNativeTestConfig(ctx android.ModuleContext, testConfigProp *string,
testConfigTemplateProp *string, testSuites []string, config []Config, autoGenConfig *bool) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
@@ -149,7 +148,7 @@
func AutoGenNativeBenchmarkTestConfig(ctx android.ModuleContext, testConfigProp *string,
testConfigTemplateProp *string, testSuites []string, configs []Config, autoGenConfig *bool) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
@@ -164,7 +163,7 @@
func AutoGenJavaTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string,
testSuites []string, autoGenConfig *bool) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
@@ -184,7 +183,7 @@
func AutoGenPythonBinaryHostTestConfig(ctx android.ModuleContext, testConfigProp *string,
testConfigTemplateProp *string, testSuites []string, autoGenConfig *bool) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
@@ -199,7 +198,7 @@
func AutoGenRustTestConfig(ctx android.ModuleContext, name string, testConfigProp *string,
testConfigTemplateProp *string, testSuites []string, autoGenConfig *bool) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
if autogenPath != nil {
templatePathString := "${RustHostTestConfigTemplate}"
if ctx.Device() {
@@ -226,7 +225,7 @@
func AutoGenInstrumentationTestConfig(ctx android.ModuleContext, testConfigProp *string,
testConfigTemplateProp *string, manifest android.Path, testSuites []string, autoGenConfig *bool) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
if autogenPath != nil {
template := "${InstrumentationTestConfigTemplate}"
moduleTemplate := getTestConfigTemplate(ctx, testConfigTemplateProp)
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index 1c4f574..36d4f04 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -237,6 +237,7 @@
if fi.IsDir() {
if err := os.Remove(old); err == nil {
ctx.Println("Removed directory that is no longer installed: ", old)
+ cleanEmptyDirs(ctx, filepath.Dir(old))
} else {
ctx.Println("Failed to remove directory that is no longer installed (%q): %v", old, err)
ctx.Println("It's recommended to run `m installclean`")
@@ -244,6 +245,7 @@
} else {
if err := os.Remove(old); err == nil {
ctx.Println("Removed file that is no longer installed: ", old)
+ cleanEmptyDirs(ctx, filepath.Dir(old))
} else if !os.IsNotExist(err) {
ctx.Fatalf("Failed to remove file that is no longer installed (%q): %v", old, err)
}
@@ -254,3 +256,16 @@
// Use the new list as the base for the next build
os.Rename(file, oldFile)
}
+
+func cleanEmptyDirs(ctx Context, dir string) {
+ files, err := ioutil.ReadDir(dir)
+ if err != nil || len(files) > 0 {
+ return
+ }
+ if err := os.Remove(dir); err == nil {
+ ctx.Println("Removed directory that is no longer installed: ", dir)
+ } else {
+ ctx.Fatalf("Failed to remove directory that is no longer installed (%q): %v", dir, err)
+ }
+ cleanEmptyDirs(ctx, filepath.Dir(dir))
+}
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 22ec1f1..0749fe3 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -142,6 +142,7 @@
"CCACHE_SLOPPINESS",
"CCACHE_BASEDIR",
"CCACHE_CPP2",
+ "CCACHE_DIR",
}, config.BuildBrokenNinjaUsesEnvVars()...)...)
}
diff --git a/vnames.go.json b/vnames.go.json
index 5842097..7ce2d4b 100644
--- a/vnames.go.json
+++ b/vnames.go.json
@@ -3,7 +3,7 @@
"pattern": "(.*)",
"vname": {
"corpus": "android.googlesource.com/platform/superproject",
- "path": "build/soong/@1@"
+ "path": "@1@"
}
}
]