Merge "Revert "m <apex_name>-deps-info prints the internal/external deps of the APEX""
diff --git a/android/hooks.go b/android/hooks.go
index 604cb9c..04ba69e 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -15,7 +15,10 @@
package android
import (
+ "reflect"
+
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
// This file implements hooks that external module types can use to inject logic into existing
@@ -26,53 +29,78 @@
// before the module has been split into architecture variants, and before defaults modules have
// been applied.
type LoadHookContext interface {
- // TODO: a new context that includes Config() but not Target(), etc.?
- BaseModuleContext
+ EarlyModuleContext
+
AppendProperties(...interface{})
PrependProperties(...interface{})
CreateModule(ModuleFactory, ...interface{}) Module
}
-// Arch hooks are run after the module has been split into architecture variants, and can be used
-// to add architecture-specific properties.
-type ArchHookContext interface {
- BaseModuleContext
- AppendProperties(...interface{})
- PrependProperties(...interface{})
-}
-
func AddLoadHook(m blueprint.Module, hook func(LoadHookContext)) {
- h := &m.(Module).base().hooks
- h.load = append(h.load, hook)
+ blueprint.AddLoadHook(m, func(ctx blueprint.LoadHookContext) {
+ actx := &loadHookContext{
+ earlyModuleContext: m.(Module).base().earlyModuleContextFactory(ctx),
+ bp: ctx,
+ }
+ hook(actx)
+ })
}
-func AddArchHook(m blueprint.Module, hook func(ArchHookContext)) {
- h := &m.(Module).base().hooks
- h.arch = append(h.arch, hook)
+type loadHookContext struct {
+ earlyModuleContext
+ bp blueprint.LoadHookContext
+ module Module
}
-func (x *hooks) runLoadHooks(ctx LoadHookContext, m *ModuleBase) {
- if len(x.load) > 0 {
- for _, x := range x.load {
- x(ctx)
- if ctx.Failed() {
- return
+func (l *loadHookContext) AppendProperties(props ...interface{}) {
+ for _, p := range props {
+ err := proptools.AppendMatchingProperties(l.Module().base().customizableProperties,
+ p, nil)
+ if err != nil {
+ if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+ l.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+ } else {
+ panic(err)
}
}
}
}
-func (x *hooks) runArchHooks(ctx ArchHookContext, m *ModuleBase) {
- if len(x.arch) > 0 {
- for _, x := range x.arch {
- x(ctx)
- if ctx.Failed() {
- return
+func (l *loadHookContext) PrependProperties(props ...interface{}) {
+ for _, p := range props {
+ err := proptools.PrependMatchingProperties(l.Module().base().customizableProperties,
+ p, nil)
+ if err != nil {
+ if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+ l.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+ } else {
+ panic(err)
}
}
}
}
+func (l *loadHookContext) CreateModule(factory ModuleFactory, props ...interface{}) Module {
+ inherited := []interface{}{&l.Module().base().commonProperties}
+ module := l.bp.CreateModule(ModuleFactoryAdaptor(factory), append(inherited, props...)...).(Module)
+
+ if l.Module().base().variableProperties != nil && module.base().variableProperties != nil {
+ src := l.Module().base().variableProperties
+ dst := []interface{}{
+ module.base().variableProperties,
+ // 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(src).Elem()).Interface(),
+ }
+ err := proptools.AppendMatchingProperties(dst, src, nil)
+ if err != nil {
+ panic(err)
+ }
+ }
+
+ return module
+}
+
type InstallHookContext interface {
ModuleContext
Path() InstallPath
@@ -118,31 +146,5 @@
}
type hooks struct {
- load []func(LoadHookContext)
- arch []func(ArchHookContext)
install []func(InstallHookContext)
}
-
-func registerLoadHookMutator(ctx RegisterMutatorsContext) {
- ctx.TopDown("load_hooks", LoadHookMutator).Parallel()
-}
-
-func LoadHookMutator(ctx TopDownMutatorContext) {
- if m, ok := ctx.Module().(Module); ok {
- m.base().commonProperties.DebugName = ctx.ModuleName()
-
- // Cast through *topDownMutatorContext because AppendProperties is implemented
- // on *topDownMutatorContext but not exposed through TopDownMutatorContext
- var loadHookCtx LoadHookContext = ctx.(*topDownMutatorContext)
- m.base().hooks.runLoadHooks(loadHookCtx, m.base())
- }
-}
-
-func archHookMutator(ctx TopDownMutatorContext) {
- if m, ok := ctx.Module().(Module); ok {
- // Cast through *topDownMutatorContext because AppendProperties is implemented
- // on *topDownMutatorContext but not exposed through TopDownMutatorContext
- var archHookCtx ArchHookContext = ctx.(*topDownMutatorContext)
- m.base().hooks.runArchHooks(archHookCtx, m.base())
- }
-}
diff --git a/android/module.go b/android/module.go
index a14e575..c998007 100644
--- a/android/module.go
+++ b/android/module.go
@@ -55,16 +55,51 @@
type ModuleBuildParams BuildParams
+// EarlyModuleContext provides methods that can be called early, as soon as the properties have
+// been parsed into the module and before any mutators have run.
+type EarlyModuleContext interface {
+ Module() Module
+ ModuleName() string
+ ModuleDir() string
+ ModuleType() string
+
+ ContainsProperty(name string) bool
+ Errorf(pos scanner.Position, fmt string, args ...interface{})
+ ModuleErrorf(fmt string, args ...interface{})
+ PropertyErrorf(property, fmt string, args ...interface{})
+ Failed() bool
+
+ AddNinjaFileDeps(deps ...string)
+
+ DeviceSpecific() bool
+ SocSpecific() bool
+ ProductSpecific() bool
+ SystemExtSpecific() bool
+ Platform() bool
+
+ Config() Config
+ DeviceConfig() DeviceConfig
+
+ // Deprecated: use Config()
+ AConfig() Config
+
+ // GlobWithDeps returns a list of files that match the specified pattern but do not match any
+ // of the patterns in excludes. It also adds efficient dependencies to rerun the primary
+ // builder whenever a file matching the pattern as added or removed, without rerunning if a
+ // file that does not match the pattern is added to a searched directory.
+ GlobWithDeps(pattern string, excludes []string) ([]string, error)
+
+ Glob(globPattern string, excludes []string) Paths
+ GlobFiles(globPattern string, excludes []string) Paths
+ Fs() pathtools.FileSystem
+}
+
// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
// a Config instead of an interface{}, and some methods have been wrapped to use an android.Module
// instead of a blueprint.Module, plus some extra methods that return Android-specific information
// about the current module.
type BaseModuleContext interface {
- Module() Module
- ModuleName() string
- ModuleDir() string
- ModuleType() string
- Config() Config
+ EarlyModuleContext
OtherModuleName(m blueprint.Module) string
OtherModuleDir(m blueprint.Module) string
@@ -91,24 +126,6 @@
// and returns a top-down dependency path from a start module to current child module.
GetWalkPath() []Module
- ContainsProperty(name string) bool
- Errorf(pos scanner.Position, fmt string, args ...interface{})
- ModuleErrorf(fmt string, args ...interface{})
- PropertyErrorf(property, fmt string, args ...interface{})
- Failed() bool
-
- // GlobWithDeps returns a list of files that match the specified pattern but do not match any
- // of the patterns in excludes. It also adds efficient dependencies to rerun the primary
- // builder whenever a file matching the pattern as added or removed, without rerunning if a
- // file that does not match the pattern is added to a searched directory.
- GlobWithDeps(pattern string, excludes []string) ([]string, error)
-
- Glob(globPattern string, excludes []string) Paths
- GlobFiles(globPattern string, excludes []string) Paths
-
- Fs() pathtools.FileSystem
- AddNinjaFileDeps(deps ...string)
-
AddMissingDependencies(missingDeps []string)
Target() Target
@@ -123,18 +140,11 @@
Windows() bool
Debug() bool
PrimaryArch() bool
- Platform() bool
- DeviceSpecific() bool
- SocSpecific() bool
- ProductSpecific() bool
- SystemExtSpecific() bool
- AConfig() Config
- DeviceConfig() DeviceConfig
}
-// Deprecated: use BaseModuleContext instead
+// Deprecated: use EarlyModuleContext instead
type BaseContext interface {
- BaseModuleContext
+ EarlyModuleContext
}
type ModuleContext interface {
@@ -221,6 +231,10 @@
// Get the visibility rules that control the visibility of this module.
visibility() []string
+
+ RequiredModuleNames() []string
+ HostRequiredModuleNames() []string
+ TargetRequiredModuleNames() []string
}
// Qualified id for a module
@@ -887,6 +901,18 @@
return m.base().commonProperties.ImageVariation == RecoveryVariation
}
+func (m *ModuleBase) RequiredModuleNames() []string {
+ return m.base().commonProperties.Required
+}
+
+func (m *ModuleBase) HostRequiredModuleNames() []string {
+ return m.base().commonProperties.Host_required
+}
+
+func (m *ModuleBase) TargetRequiredModuleNames() []string {
+ return m.base().commonProperties.Target_required
+}
+
func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
allInstalledFiles := Paths{}
allCheckbuildFiles := Paths{}
@@ -943,7 +969,7 @@
}
}
-func determineModuleKind(m *ModuleBase, ctx blueprint.BaseModuleContext) moduleKind {
+func determineModuleKind(m *ModuleBase, ctx blueprint.EarlyModuleContext) moduleKind {
var socSpecific = Bool(m.commonProperties.Vendor) || Bool(m.commonProperties.Proprietary) || Bool(m.commonProperties.Soc_specific)
var deviceSpecific = Bool(m.commonProperties.Device_specific)
var productSpecific = Bool(m.commonProperties.Product_specific)
@@ -1002,15 +1028,22 @@
}
}
+func (m *ModuleBase) earlyModuleContextFactory(ctx blueprint.EarlyModuleContext) earlyModuleContext {
+ return earlyModuleContext{
+ EarlyModuleContext: ctx,
+ kind: determineModuleKind(m, ctx),
+ config: ctx.Config().(Config),
+ }
+}
+
func (m *ModuleBase) baseModuleContextFactory(ctx blueprint.BaseModuleContext) baseModuleContext {
return baseModuleContext{
- BaseModuleContext: ctx,
- os: m.commonProperties.CompileOS,
- target: m.commonProperties.CompileTarget,
- targetPrimary: m.commonProperties.CompilePrimary,
- multiTargets: m.commonProperties.CompileMultiTargets,
- kind: determineModuleKind(m, ctx),
- config: ctx.Config().(Config),
+ bp: ctx,
+ earlyModuleContext: m.earlyModuleContextFactory(ctx),
+ os: m.commonProperties.CompileOS,
+ target: m.commonProperties.CompileTarget,
+ targetPrimary: m.commonProperties.CompilePrimary,
+ multiTargets: m.commonProperties.CompileMultiTargets,
}
}
@@ -1116,21 +1149,95 @@
m.variables = ctx.variables
}
+type earlyModuleContext struct {
+ blueprint.EarlyModuleContext
+
+ kind moduleKind
+ config Config
+}
+
+func (e *earlyModuleContext) Glob(globPattern string, excludes []string) Paths {
+ ret, err := e.GlobWithDeps(globPattern, excludes)
+ if err != nil {
+ e.ModuleErrorf("glob: %s", err.Error())
+ }
+ return pathsForModuleSrcFromFullPath(e, ret, true)
+}
+
+func (e *earlyModuleContext) GlobFiles(globPattern string, excludes []string) Paths {
+ ret, err := e.GlobWithDeps(globPattern, excludes)
+ if err != nil {
+ e.ModuleErrorf("glob: %s", err.Error())
+ }
+ return pathsForModuleSrcFromFullPath(e, ret, false)
+}
+
+func (e *earlyModuleContext) Module() Module {
+ module, _ := e.EarlyModuleContext.Module().(Module)
+ return module
+}
+
+func (e *earlyModuleContext) Config() Config {
+ return e.EarlyModuleContext.Config().(Config)
+}
+
+func (e *earlyModuleContext) AConfig() Config {
+ return e.config
+}
+
+func (e *earlyModuleContext) DeviceConfig() DeviceConfig {
+ return DeviceConfig{e.config.deviceConfig}
+}
+
+func (e *earlyModuleContext) Platform() bool {
+ return e.kind == platformModule
+}
+
+func (e *earlyModuleContext) DeviceSpecific() bool {
+ return e.kind == deviceSpecificModule
+}
+
+func (e *earlyModuleContext) SocSpecific() bool {
+ return e.kind == socSpecificModule
+}
+
+func (e *earlyModuleContext) ProductSpecific() bool {
+ return e.kind == productSpecificModule
+}
+
+func (e *earlyModuleContext) SystemExtSpecific() bool {
+ return e.kind == systemExtSpecificModule
+}
+
type baseModuleContext struct {
- blueprint.BaseModuleContext
+ bp blueprint.BaseModuleContext
+ earlyModuleContext
os OsType
target Target
multiTargets []Target
targetPrimary bool
debug bool
- kind moduleKind
- config Config
walkPath []Module
strictVisitDeps bool // If true, enforce that all dependencies are enabled
}
+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)
+}
+func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
+ return b.bp.OtherModuleDependencyTag(m)
+}
+func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
+func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string { return b.bp.OtherModuleType(m) }
+
+func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
+ return b.bp.GetDirectDepWithTag(name, tag)
+}
+
type moduleContext struct {
bp blueprint.ModuleContext
baseModuleContext
@@ -1245,16 +1352,6 @@
m.bp.Build(pctx.PackageContext, convertBuildParams(params))
}
-
-func (b *baseModuleContext) Module() Module {
- module, _ := b.BaseModuleContext.Module().(Module)
- return module
-}
-
-func (b *baseModuleContext) Config() Config {
- return b.BaseModuleContext.Config().(Config)
-}
-
func (m *moduleContext) GetMissingDependencies() []string {
var missingDeps []string
missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
@@ -1302,7 +1399,7 @@
var deps []dep
b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
if aModule, _ := module.(Module); aModule != nil && aModule.base().BaseModuleName() == name {
- returnedTag := b.BaseModuleContext.OtherModuleDependencyTag(aModule)
+ returnedTag := b.bp.OtherModuleDependencyTag(aModule)
if tag == nil || returnedTag == tag {
deps = append(deps, dep{aModule, returnedTag})
}
@@ -1322,7 +1419,7 @@
var deps []Module
b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
if aModule, _ := module.(Module); aModule != nil {
- if b.BaseModuleContext.OtherModuleDependencyTag(aModule) == tag {
+ if b.bp.OtherModuleDependencyTag(aModule) == tag {
deps = append(deps, aModule)
}
}
@@ -1340,11 +1437,11 @@
}
func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
- b.BaseModuleContext.VisitDirectDeps(visit)
+ b.bp.VisitDirectDeps(visit)
}
func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
- b.BaseModuleContext.VisitDirectDeps(func(module blueprint.Module) {
+ b.bp.VisitDirectDeps(func(module blueprint.Module) {
if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
visit(aModule)
}
@@ -1352,9 +1449,9 @@
}
func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
- b.BaseModuleContext.VisitDirectDeps(func(module blueprint.Module) {
+ b.bp.VisitDirectDeps(func(module blueprint.Module) {
if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
- if b.BaseModuleContext.OtherModuleDependencyTag(aModule) == tag {
+ if b.bp.OtherModuleDependencyTag(aModule) == tag {
visit(aModule)
}
}
@@ -1362,7 +1459,7 @@
}
func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
- b.BaseModuleContext.VisitDirectDepsIf(
+ b.bp.VisitDirectDepsIf(
// pred
func(module blueprint.Module) bool {
if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
@@ -1378,7 +1475,7 @@
}
func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
- b.BaseModuleContext.VisitDepsDepthFirst(func(module blueprint.Module) {
+ b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
visit(aModule)
}
@@ -1386,7 +1483,7 @@
}
func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
- b.BaseModuleContext.VisitDepsDepthFirstIf(
+ b.bp.VisitDepsDepthFirstIf(
// pred
func(module blueprint.Module) bool {
if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
@@ -1402,12 +1499,12 @@
}
func (b *baseModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
- b.BaseModuleContext.WalkDeps(visit)
+ b.bp.WalkDeps(visit)
}
func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
b.walkPath = []Module{b.Module()}
- b.BaseModuleContext.WalkDeps(func(child, parent blueprint.Module) bool {
+ b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
childAndroidModule, _ := child.(Module)
parentAndroidModule, _ := parent.(Module)
if childAndroidModule != nil && parentAndroidModule != nil {
@@ -1496,34 +1593,6 @@
return b.target.Arch.ArchType == b.config.Targets[b.target.Os][0].Arch.ArchType
}
-func (b *baseModuleContext) AConfig() Config {
- return b.config
-}
-
-func (b *baseModuleContext) DeviceConfig() DeviceConfig {
- return DeviceConfig{b.config.deviceConfig}
-}
-
-func (b *baseModuleContext) Platform() bool {
- return b.kind == platformModule
-}
-
-func (b *baseModuleContext) DeviceSpecific() bool {
- return b.kind == deviceSpecificModule
-}
-
-func (b *baseModuleContext) SocSpecific() bool {
- return b.kind == socSpecificModule
-}
-
-func (b *baseModuleContext) ProductSpecific() bool {
- return b.kind == productSpecificModule
-}
-
-func (b *baseModuleContext) SystemExtSpecific() bool {
- return b.kind == systemExtSpecificModule
-}
-
// Makes this module a platform module, i.e. not specific to soc, device,
// product, or system_ext.
func (m *ModuleBase) MakeAsPlatform() {
@@ -1877,31 +1946,15 @@
}
func (m *moduleContext) RequiredModuleNames() []string {
- return m.module.base().commonProperties.Required
+ return m.module.RequiredModuleNames()
}
func (m *moduleContext) HostRequiredModuleNames() []string {
- return m.module.base().commonProperties.Host_required
+ return m.module.HostRequiredModuleNames()
}
func (m *moduleContext) TargetRequiredModuleNames() []string {
- return m.module.base().commonProperties.Target_required
-}
-
-func (b *baseModuleContext) Glob(globPattern string, excludes []string) Paths {
- ret, err := b.GlobWithDeps(globPattern, excludes)
- if err != nil {
- b.ModuleErrorf("glob: %s", err.Error())
- }
- return pathsForModuleSrcFromFullPath(b, ret, true)
-}
-
-func (b *baseModuleContext) GlobFiles(globPattern string, excludes []string) Paths {
- ret, err := b.GlobWithDeps(globPattern, excludes)
- if err != nil {
- b.ModuleErrorf("glob: %s", err.Error())
- }
- return pathsForModuleSrcFromFullPath(b, ret, false)
+ return m.module.TargetRequiredModuleNames()
}
func init() {
diff --git a/android/mutator.go b/android/mutator.go
index c2bae44..f2f9663 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -75,7 +75,6 @@
type RegisterMutatorFunc func(RegisterMutatorsContext)
var preArch = []RegisterMutatorFunc{
- registerLoadHookMutator,
RegisterNamespaceMutator,
// Rename package module types.
RegisterPackageRenamer,
@@ -89,7 +88,6 @@
ctx.BottomUp("os", osMutator).Parallel()
ctx.BottomUp("image", imageMutator).Parallel()
ctx.BottomUp("arch", archMutator).Parallel()
- ctx.TopDown("arch_hooks", archHookMutator).Parallel()
}
var preDeps = []RegisterMutatorFunc{
diff --git a/android/namespace.go b/android/namespace.go
index 27ec163..64ad7e9 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -185,6 +185,7 @@
if ok {
// inform the module whether its namespace is one that we want to export to Make
amod.base().commonProperties.NamespaceExportedToMake = ns.exportToKati
+ amod.base().commonProperties.DebugName = module.Name()
}
return ns, nil
diff --git a/android/paths.go b/android/paths.go
index c841372..a03fe17 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -409,7 +409,7 @@
// each string. If incDirs is false, strip paths with a trailing '/' from the list.
// It intended for use in globs that only list files that exist, so it allows '$' in
// filenames.
-func pathsForModuleSrcFromFullPath(ctx BaseModuleContext, paths []string, incDirs bool) Paths {
+func pathsForModuleSrcFromFullPath(ctx EarlyModuleContext, paths []string, incDirs bool) Paths {
prefix := filepath.Join(ctx.Config().srcDir, ctx.ModuleDir()) + "/"
if prefix == "./" {
prefix = ""
diff --git a/android/paths_test.go b/android/paths_test.go
index 5ff5f99..ec5e598 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -286,7 +286,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: socSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: socSpecificModule,
+ },
},
},
in: []string{"bin", "my_test"},
@@ -298,7 +300,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: deviceSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: deviceSpecificModule,
+ },
},
},
in: []string{"bin", "my_test"},
@@ -310,7 +314,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: productSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: productSpecificModule,
+ },
},
},
in: []string{"bin", "my_test"},
@@ -322,7 +328,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: systemExtSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: systemExtSpecificModule,
+ },
},
},
in: []string{"bin", "my_test"},
@@ -384,7 +392,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: socSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: socSpecificModule,
+ },
},
inData: true,
},
@@ -397,7 +407,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: deviceSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: deviceSpecificModule,
+ },
},
inData: true,
},
@@ -410,7 +422,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: productSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: productSpecificModule,
+ },
},
inData: true,
},
@@ -424,7 +438,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: systemExtSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: systemExtSpecificModule,
+ },
},
inData: true,
},
@@ -450,7 +466,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: socSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: socSpecificModule,
+ },
},
inSanitizerDir: true,
},
@@ -463,7 +481,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: deviceSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: deviceSpecificModule,
+ },
},
inSanitizerDir: true,
},
@@ -476,7 +496,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: productSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: productSpecificModule,
+ },
},
inSanitizerDir: true,
},
@@ -490,7 +512,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: systemExtSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: systemExtSpecificModule,
+ },
},
inSanitizerDir: true,
},
@@ -517,7 +541,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: socSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: socSpecificModule,
+ },
},
inData: true,
inSanitizerDir: true,
@@ -531,7 +557,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: deviceSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: deviceSpecificModule,
+ },
},
inData: true,
inSanitizerDir: true,
@@ -545,7 +573,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: productSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: productSpecificModule,
+ },
},
inData: true,
inSanitizerDir: true,
@@ -559,7 +589,9 @@
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
- kind: systemExtSpecificModule,
+ earlyModuleContext: earlyModuleContext{
+ kind: systemExtSpecificModule,
+ },
},
inData: true,
inSanitizerDir: true,
diff --git a/android/testing.go b/android/testing.go
index 4f0591b..6663728 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -37,8 +37,6 @@
ctx.SetNameInterface(nameResolver)
- ctx.preArch = append(ctx.preArch, registerLoadHookMutator)
-
ctx.postDeps = append(ctx.postDeps, registerPathDepsMutator)
return ctx
@@ -54,6 +52,7 @@
*Context
preArch, preDeps, postDeps []RegisterMutatorFunc
NameResolver *NameResolver
+ config Config
}
func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
@@ -76,6 +75,20 @@
registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps)
ctx.RegisterSingletonType("env", EnvSingleton)
+
+ ctx.config = config
+}
+
+func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
+ // This function adapts the old style ParseFileList calls that are spread throughout the tests
+ // to the new style that takes a config.
+ return ctx.Context.ParseFileList(rootDir, filePaths, ctx.config)
+}
+
+func (ctx *TestContext) ParseBlueprintsFiles(rootDir string) (deps []string, errs []error) {
+ // This function adapts the old style ParseBlueprintsFiles calls that are spread throughout the
+ // tests to the new style that takes a config.
+ return ctx.Context.ParseBlueprintsFiles(rootDir, ctx.config)
}
func (ctx *TestContext) RegisterModuleType(name string, factory ModuleFactory) {
diff --git a/apex/androidmk.go b/apex/androidmk.go
index c42b348..b5c5331 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -117,6 +117,9 @@
fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
}
}
+ if fi.jacocoReportClassesFile != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", fi.jacocoReportClassesFile.String())
+ }
if fi.class == javaSharedLib {
javaModule := fi.module.(javaLibrary)
// soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar Therefore
@@ -128,6 +131,12 @@
fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", fi.builtFile.String())
fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false")
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
+ } else if fi.class == app {
+ // soong_app_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .apk Therefore
+ // we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
+ // we will have foo.apk.apk
+ fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.builtFile.Base(), ".apk"))
+ fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_app_prebuilt.mk")
} else if fi.class == nativeSharedLib || fi.class == nativeExecutable || fi.class == nativeTest {
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
if cc, ok := fi.module.(*cc.Module); ok {
@@ -152,6 +161,27 @@
return moduleNames
}
+func (a *apexBundle) writeRequiredModules(w io.Writer) {
+ var required []string
+ var targetRequired []string
+ var hostRequired []string
+ for _, fi := range a.filesInfo {
+ required = append(required, fi.requiredModuleNames...)
+ targetRequired = append(targetRequired, fi.targetRequiredModuleNames...)
+ hostRequired = append(hostRequired, fi.hostRequiredModuleNames...)
+ }
+
+ if len(required) > 0 {
+ fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(required, " "))
+ }
+ if len(targetRequired) > 0 {
+ fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES +=", strings.Join(targetRequired, " "))
+ }
+ if len(hostRequired) > 0 {
+ fmt.Fprintln(w, "LOCAL_HOST_REQUIRED_MODULES +=", strings.Join(hostRequired, " "))
+ }
+}
+
func (a *apexBundle) androidMkForType() android.AndroidMkData {
return android.AndroidMkData{
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
@@ -170,6 +200,7 @@
if len(moduleNames) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(moduleNames, " "))
}
+ a.writeRequiredModules(w)
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
} else {
@@ -188,6 +219,7 @@
if len(a.externalDeps) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.externalDeps, " "))
}
+ a.writeRequiredModules(w)
var postInstallCommands []string
if a.prebuiltFileToDelete != "" {
postInstallCommands = append(postInstallCommands, "rm -rf "+
diff --git a/apex/apex.go b/apex/apex.go
index b27b54e..51c85ba 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -461,6 +461,12 @@
symlinks []string
transitiveDep bool
moduleDir string
+
+ requiredModuleNames []string
+ targetRequiredModuleNames []string
+ hostRequiredModuleNames []string
+
+ jacocoReportClassesFile android.Path // only for javalibs and apps
}
func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, moduleName string, installDir string, class apexFileClass, module android.Module) apexFile {
@@ -473,6 +479,9 @@
}
if module != nil {
ret.moduleDir = ctx.OtherModuleDir(module)
+ ret.requiredModuleNames = module.RequiredModuleNames()
+ ret.targetRequiredModuleNames = module.TargetRequiredModuleNames()
+ ret.hostRequiredModuleNames = module.HostRequiredModuleNames()
}
return ret
}
@@ -692,6 +701,12 @@
ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
javaLibTag, a.properties.Java_libs...)
+ // With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library.
+ if a.artApex && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
+ ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
+ javaLibTag, "jacocoagent")
+ }
+
if String(a.properties.Key) == "" {
ctx.ModuleErrorf("key is missing")
return
@@ -882,7 +897,9 @@
func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib javaLibrary) apexFile {
dirInApex := "javalib"
fileToCopy := lib.DexJar()
- return newApexFile(ctx, fileToCopy, lib.Name(), dirInApex, javaSharedLib, lib)
+ af := newApexFile(ctx, fileToCopy, lib.Name(), dirInApex, javaSharedLib, lib)
+ af.jacocoReportClassesFile = lib.JacocoReportClassesFile()
+ return af
}
func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt android.PrebuiltEtcModule, depName string) apexFile {
@@ -895,6 +912,7 @@
android.Module
Privileged() bool
OutputFile() android.Path
+ JacocoReportClassesFile() android.Path
}, pkgName string) apexFile {
appDir := "app"
if aapp.Privileged() {
@@ -902,7 +920,9 @@
}
dirInApex := filepath.Join(appDir, pkgName)
fileToCopy := aapp.OutputFile()
- return newApexFile(ctx, fileToCopy, aapp.Name(), dirInApex, app, aapp)
+ af := newApexFile(ctx, fileToCopy, aapp.Name(), dirInApex, app, aapp)
+ af.jacocoReportClassesFile = aapp.JacocoReportClassesFile()
+ return af
}
// Context "decorator", overriding the InstallBypassMake method to always reply `true`.
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 0d929ed..cc346e9 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3328,6 +3328,43 @@
`)
}
+func TestCarryRequiredModuleNames(t *testing.T) {
+ ctx, config := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ required: ["a", "b"],
+ host_required: ["c", "d"],
+ target_required: ["e", "f"],
+ }
+ `)
+
+ 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_REQUIRED_MODULES += a b\n")
+ ensureContains(t, androidMk, "LOCAL_HOST_REQUIRED_MODULES += c d\n")
+ ensureContains(t, androidMk, "LOCAL_TARGET_REQUIRED_MODULES += e f\n")
+}
+
func TestMain(m *testing.M) {
run := func() int {
setUp()
diff --git a/apex/builder.go b/apex/builder.go
index fe465f5..4a760b9 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -105,6 +105,7 @@
`${apexer} --force --manifest ${manifest} ` +
`--file_contexts ${file_contexts} ` +
`--canned_fs_config ${canned_fs_config} ` +
+ `--include_build_info ` +
`--payload_type image ` +
`--key ${key} ${opt_flags} ${image_dir} ${out} `,
CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}",
@@ -378,7 +379,7 @@
optFlags = append(optFlags, "--assets_dir "+filepath.Dir(noticeFile.String()))
}
- if ctx.ModuleDir() != "system/apex/apexd/apexd_testdata" && a.testOnlyShouldSkipHashtreeGeneration() {
+ if ctx.ModuleDir() != "system/apex/apexd/apexd_testdata" && ctx.ModuleDir() != "system/apex/shim/build" && a.testOnlyShouldSkipHashtreeGeneration() {
ctx.PropertyErrorf("test_only_no_hashtree", "not available")
return
}
diff --git a/build_kzip.bash b/build_kzip.bash
index ccd6bad..02b346d 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -19,12 +19,13 @@
# 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.
+declare -r abspath_out=$(realpath "${out}")
(cd build/soong;
../../prebuilts/build-tools/linux-x86/bin/go_extractor \
--goroot="${PWD}/../../prebuilts/go/linux-x86" \
--rules=vnames.go.json \
--canonicalize_package_corpus \
- --output "${out}/soong/all.go.kzip" \
+ --output "${abspath_out}/soong/all.go.kzip" \
./... )
declare -r kzip_count=$(find "$out" -name '*.kzip' | wc -l)
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 988ebd4..ff88091 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -284,6 +284,9 @@
fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=", benchmark.testConfig.String())
}
fmt.Fprintln(w, "LOCAL_NATIVE_BENCHMARK := true")
+ if !BoolDefault(benchmark.Properties.Auto_gen_config, true) {
+ fmt.Fprintln(w, "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG := true")
+ }
})
androidMkWriteTestData(benchmark.data, ctx, ret)
@@ -304,6 +307,9 @@
if test.testConfig != nil {
fmt.Fprintln(w, "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")
+ }
})
androidMkWriteTestData(test.data, ctx, ret)
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index c3cda49..9feb5a3 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -84,6 +84,7 @@
"android.hardware.thermal@1.0",
"android.hardware.tv.cec@1.0",
"android.hardware.tv.input@1.0",
+ "android.hardware.vibrator-ndk_platform",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
@@ -165,5 +166,4 @@
"libxml2",
"libyuv",
"libziparchive",
- "vintf-vibrator-ndk_platform",
}
diff --git a/cc/pgo.go b/cc/pgo.go
index 4618f4e..0072355 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -210,11 +210,6 @@
ctx.ModuleErrorf("PGO specification is missing properties: " + missingProps)
}
- // Sampling not supported yet
- if isSampling {
- ctx.PropertyErrorf("pgo.sampling", "\"sampling\" is not supported yet)")
- }
-
if isSampling && isInstrumentation {
ctx.PropertyErrorf("pgo", "Exactly one of \"instrumentation\" and \"sampling\" properties must be set")
}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 83e3673..0c79ccc 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -22,7 +22,9 @@
"android/soong/android"
)
-// GlobalConfig stores the configuration for dex preopting set by the product
+// 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.
type GlobalConfig struct {
DisablePreopt bool // disable preopt for all modules
DisablePreoptModules []string // modules with preopt disabled by product-specific config
@@ -82,19 +84,19 @@
Dex2oatImageXmx string // max heap size for dex2oat for the boot image
Dex2oatImageXms string // initial heap size for dex2oat for the boot image
- Tools Tools // paths to tools possibly used by the generated commands
+ SoongConfig GlobalSoongConfig // settings read from dexpreopt_soong.config
}
-// Tools contains paths to tools possibly used by the generated commands. If you add a new tool here you MUST add it
-// to the order-only dependency list in DEXPREOPT_GEN_DEPS.
-type Tools struct {
- Profman android.Path
- Dex2oat android.Path
- Aapt android.Path
- SoongZip android.Path
- Zip2zip android.Path
- ManifestCheck android.Path
-
+// GlobalSoongConfig contains the global config that is generated from Soong,
+// stored in dexpreopt_soong.config.
+type GlobalSoongConfig struct {
+ // Paths to tools possibly used by the generated commands.
+ Profman android.Path
+ Dex2oat android.Path
+ Aapt android.Path
+ SoongZip android.Path
+ Zip2zip android.Path
+ ManifestCheck android.Path
ConstructContext android.Path
}
@@ -133,6 +135,17 @@
PresignedPrebuilt bool
}
+type globalSoongConfigSingleton struct{}
+
+var pctx = android.NewPackageContext("android/soong/dexpreopt")
+
+func init() {
+ pctx.Import("android/soong/android")
+ android.RegisterSingletonType("dexpreopt-soong-config", func() android.Singleton {
+ return &globalSoongConfigSingleton{}
+ })
+}
+
func constructPath(ctx android.PathContext, path string) android.Path {
buildDirPrefix := ctx.Config().BuildDir() + "/"
if path == "" {
@@ -167,9 +180,12 @@
return constructPath(ctx, path).(android.WritablePath)
}
-// LoadGlobalConfig reads the global dexpreopt.config file into a GlobalConfig struct. It 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, path string) (GlobalConfig, []byte, error) {
+// 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, path string, soongConfig GlobalSoongConfig) (GlobalConfig, []byte, error) {
type GlobalJSONConfig struct {
GlobalConfig
@@ -177,17 +193,6 @@
// used to construct the real value manually below.
DirtyImageObjects string
BootImageProfiles []string
-
- Tools struct {
- Profman string
- Dex2oat string
- Aapt string
- SoongZip string
- Zip2zip string
- ManifestCheck string
-
- ConstructContext string
- }
}
config := GlobalJSONConfig{}
@@ -200,13 +205,9 @@
config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects))
config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles)
- config.GlobalConfig.Tools.Profman = constructPath(ctx, config.Tools.Profman)
- config.GlobalConfig.Tools.Dex2oat = constructPath(ctx, config.Tools.Dex2oat)
- config.GlobalConfig.Tools.Aapt = constructPath(ctx, config.Tools.Aapt)
- config.GlobalConfig.Tools.SoongZip = constructPath(ctx, config.Tools.SoongZip)
- config.GlobalConfig.Tools.Zip2zip = constructPath(ctx, config.Tools.Zip2zip)
- config.GlobalConfig.Tools.ManifestCheck = constructPath(ctx, config.Tools.ManifestCheck)
- config.GlobalConfig.Tools.ConstructContext = constructPath(ctx, config.Tools.ConstructContext)
+ // 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, data, nil
}
@@ -253,6 +254,104 @@
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.
+ // 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"
+ } else {
+ dex2oatBinary = "dex2oatd"
+ }
+
+ return GlobalSoongConfig{
+ Profman: ctx.Config().HostToolPath(ctx, "profman"),
+ Dex2oat: ctx.Config().HostToolPath(ctx, dex2oatBinary),
+ Aapt: ctx.Config().HostToolPath(ctx, "aapt"),
+ SoongZip: ctx.Config().HostToolPath(ctx, "soong_zip"),
+ Zip2zip: ctx.Config().HostToolPath(ctx, "zip2zip"),
+ ManifestCheck: ctx.Config().HostToolPath(ctx, "manifest_check"),
+ ConstructContext: android.PathForSource(ctx, "build/make/core/construct_context.sh"),
+ }
+}
+
+type globalJsonSoongConfig struct {
+ Profman string
+ Dex2oat string
+ Aapt string
+ SoongZip string
+ Zip2zip string
+ ManifestCheck string
+ 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, path string) (GlobalSoongConfig, error) {
+ var jc globalJsonSoongConfig
+
+ _, err := loadConfig(ctx, path, &jc)
+ if err != nil {
+ return GlobalSoongConfig{}, err
+ }
+
+ config := GlobalSoongConfig{
+ Profman: constructPath(ctx, jc.Profman),
+ Dex2oat: constructPath(ctx, jc.Dex2oat),
+ Aapt: constructPath(ctx, jc.Aapt),
+ SoongZip: constructPath(ctx, jc.SoongZip),
+ Zip2zip: constructPath(ctx, jc.Zip2zip),
+ ManifestCheck: constructPath(ctx, jc.ManifestCheck),
+ ConstructContext: constructPath(ctx, jc.ConstructContext),
+ }
+
+ return config, nil
+}
+
+func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ config := CreateGlobalSoongConfig(ctx)
+ jc := globalJsonSoongConfig{
+ Profman: config.Profman.String(),
+ Dex2oat: config.Dex2oat.String(),
+ Aapt: config.Aapt.String(),
+ SoongZip: config.SoongZip.String(),
+ Zip2zip: config.Zip2zip.String(),
+ ManifestCheck: config.ManifestCheck.String(),
+ ConstructContext: config.ConstructContext.String(),
+ }
+
+ data, err := json.Marshal(jc)
+ if err != nil {
+ ctx.Errorf("failed to JSON marshal GlobalSoongConfig: %v", err)
+ return
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.WriteFile,
+ Output: android.PathForOutput(ctx, "dexpreopt_soong.config"),
+ Args: map[string]string{
+ "content": string(data),
+ },
+ })
+}
+
+func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
+ config := CreateGlobalSoongConfig(ctx)
+
+ ctx.Strict("DEX2OAT", config.Dex2oat.String())
+ ctx.Strict("DEXPREOPT_GEN_DEPS", strings.Join([]string{
+ config.Profman.String(),
+ config.Dex2oat.String(),
+ config.Aapt.String(),
+ config.SoongZip.String(),
+ config.Zip2zip.String(),
+ config.ManifestCheck.String(),
+ config.ConstructContext.String(),
+ }, " "))
+}
+
func loadConfig(ctx android.PathContext, path string, config interface{}) ([]byte, error) {
r, err := ctx.Fs().Open(path)
if err != nil {
@@ -312,7 +411,7 @@
BootFlags: "",
Dex2oatImageXmx: "",
Dex2oatImageXms: "",
- Tools: Tools{
+ SoongConfig: GlobalSoongConfig{
Profman: android.PathForTesting("profman"),
Dex2oat: android.PathForTesting("dex2oat"),
Aapt: android.PathForTesting("aapt"),
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index fc1bae1..ac5b691 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -131,7 +131,7 @@
cmd := rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
- Tool(global.Tools.Profman)
+ Tool(global.SoongConfig.Profman)
if module.ProfileIsTextListing {
// The profile is a test listing of classes (used for framework jars).
@@ -170,7 +170,7 @@
cmd := rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
- Tool(global.Tools.Profman)
+ Tool(global.SoongConfig.Profman)
// The profile is a test listing of methods.
// We need to generate the actual binary profile.
@@ -222,14 +222,6 @@
invocationPath := odexPath.ReplaceExtension(ctx, "invocation")
- // TODO(skvadrik): fix this to use boot image location in the module config (currently it is broken
- // in JIT-zygote builds, because "default" boot image is hard-coded in parts of the module config).
- bootImage := module.DexPreoptImages[archIdx]
- var bootImageLocation string
- if bootImage != nil {
- bootImageLocation = PathToLocation(bootImage, arch)
- }
-
// The class loader context using paths in the build
var classLoaderContextHost android.Paths
@@ -307,14 +299,14 @@
if module.EnforceUsesLibraries {
if module.ManifestPath != nil {
rule.Command().Text(`target_sdk_version="$(`).
- Tool(global.Tools.ManifestCheck).
+ Tool(global.SoongConfig.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.Tools.Aapt).
+ Tool(global.SoongConfig.Aapt).
Flag("dump badging").
Input(module.DexPath).
Text(`| grep "targetSdkVersion" | sed -n "s/targetSdkVersion:'\(.*\)'/\1/p"`).
@@ -335,7 +327,7 @@
Implicits(conditionalClassLoaderContextHost29)
rule.Command().Textf(`conditional_target_libs_29="%s"`,
strings.Join(conditionalClassLoaderContextTarget29, " "))
- rule.Command().Text("source").Tool(global.Tools.ConstructContext).Input(module.DexPath)
+ rule.Command().Text("source").Tool(global.SoongConfig.ConstructContext).Input(module.DexPath)
}
// Devices that do not have a product partition use a symlink from /product to /system/product.
@@ -348,7 +340,7 @@
cmd := rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
- Tool(global.Tools.Dex2oat).
+ Tool(global.SoongConfig.Dex2oat).
Flag("--avoid-storing-invocation").
FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatXms).
@@ -357,7 +349,7 @@
Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", module.PreoptBootClassPathDexLocations, ":").
Flag("${class_loader_context_arg}").
Flag("${stored_class_loader_context_arg}").
- FlagWithArg("--boot-image=", bootImageLocation).Implicits(module.DexPreoptImagesDeps[archIdx].Paths()).
+ FlagWithArg("--boot-image=", strings.Join(module.DexPreoptImageLocations, ":")).Implicits(module.DexPreoptImagesDeps[archIdx].Paths()).
FlagWithInput("--dex-file=", module.DexPath).
FlagWithArg("--dex-location=", dexLocationArg).
FlagWithOutput("--oat-file=", odexPath).ImplicitOutput(vdexPath).
@@ -417,7 +409,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.Tools.SoongZip).
+ rule.Command().Tool(global.SoongConfig.SoongZip).
FlagWithArg("-L", "9").
FlagWithOutput("-o", dmPath).
Flag("-j").
diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
index 6f51080..d2faa00 100644
--- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
+++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
@@ -30,10 +30,11 @@
)
var (
- dexpreoptScriptPath = flag.String("dexpreopt_script", "", "path to output dexpreopt script")
- globalConfigPath = flag.String("global", "", "path to global configuration file")
- moduleConfigPath = flag.String("module", "", "path to module configuration file")
- outDir = flag.String("out_dir", "", "path to output directory")
+ dexpreoptScriptPath = flag.String("dexpreopt_script", "", "path to output dexpreopt script")
+ globalSoongConfigPath = flag.String("global_soong", "", "path to global configuration file for settings originating from Soong")
+ globalConfigPath = flag.String("global", "", "path to global configuration file")
+ moduleConfigPath = flag.String("module", "", "path to module configuration file")
+ outDir = flag.String("out_dir", "", "path to output directory")
)
type pathContext struct {
@@ -63,17 +64,27 @@
usage("path to output dexpreopt script is required")
}
+ if *globalSoongConfigPath == "" {
+ usage("--global_soong configuration file is required")
+ }
+
if *globalConfigPath == "" {
- usage("path to global configuration file is required")
+ usage("--global configuration file is required")
}
if *moduleConfigPath == "" {
- usage("path to module configuration file is required")
+ usage("--module configuration file is required")
}
ctx := &pathContext{android.TestConfig(*outDir, nil, "", nil)}
- globalConfig, _, err := dexpreopt.LoadGlobalConfig(ctx, *globalConfigPath)
+ globalSoongConfig, err := dexpreopt.LoadGlobalSoongConfig(ctx, *globalSoongConfigPath)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalSoongConfigPath, err)
+ os.Exit(2)
+ }
+
+ globalConfig, _, err := dexpreopt.LoadGlobalConfig(ctx, *globalConfigPath, globalSoongConfig)
if err != nil {
fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalConfigPath, err)
os.Exit(2)
@@ -121,7 +132,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.Tools.SoongZip).
+ dexpreoptRule.Command().Tool(global.SoongConfig.SoongZip).
FlagWithArg("-o ", "$2").
FlagWithArg("-C ", installDir.String()).
FlagWithArg("-D ", installDir.String())
diff --git a/java/aar.go b/java/aar.go
index 201e590..ae064e5 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -576,6 +576,10 @@
return a.prebuilt.Name(a.ModuleBase.Name())
}
+func (a *AARImport) JacocoReportClassesFile() android.Path {
+ return nil
+}
+
func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
if !ctx.Config().UnbundledBuildUsePrebuiltSdks() {
sdkDep := decodeSdkDep(ctx, sdkContext(a))
diff --git a/java/androidmk.go b/java/androidmk.go
index 11fea82..04bf15c 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -141,6 +141,9 @@
entries.SetPath("LOCAL_FULL_TEST_CONFIG", j.testConfig)
}
androidMkWriteTestData(j.data, entries)
+ if !BoolDefault(j.testProperties.Auto_gen_config, true) {
+ entries.SetString("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", "true")
+ }
})
return entriesList
@@ -613,7 +616,7 @@
fmt.Fprintln(w, dstubs.Name()+"-check-last-released-api:",
dstubs.checkLastReleasedApiTimestamp.String())
- if dstubs.Name() == "api-stubs-docs" || dstubs.Name() == "system-api-stubs-docs" {
+ if dstubs.Name() != "android.car-system-stubs-docs" {
fmt.Fprintln(w, ".PHONY: checkapi")
fmt.Fprintln(w, "checkapi:",
dstubs.checkLastReleasedApiTimestamp.String())
diff --git a/java/app.go b/java/app.go
index 94f6bb1..05fa505 100755
--- a/java/app.go
+++ b/java/app.go
@@ -897,7 +897,7 @@
MergePropertiesFromVariant(ctx, &a.properties, archProps, archType.Name)
}
-func MergePropertiesFromVariant(ctx android.BaseModuleContext,
+func MergePropertiesFromVariant(ctx android.EarlyModuleContext,
dst interface{}, variantGroup reflect.Value, variant string) {
src := variantGroup.FieldByName(proptools.FieldNameForProperty(variant))
if !src.IsValid() {
@@ -1062,6 +1062,10 @@
return a.outputFile
}
+func (a *AndroidAppImport) JacocoReportClassesFile() android.Path {
+ return nil
+}
+
var dpiVariantGroupType reflect.Type
var archVariantGroupType reflect.Type
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 1524418..b40ab93 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -170,6 +170,10 @@
return d.srcJarArgs, d.srcJarDeps
}
+func (d *DeviceHostConverter) JacocoReportClassesFile() android.Path {
+ return nil
+}
+
func (d *DeviceHostConverter) AndroidMk() android.AndroidMkData {
return android.AndroidMkData{
Class: "JAVA_LIBRARIES",
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 1d363c9..fe5bed5 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -178,12 +178,6 @@
return false
}
-func skipDexpreoptArtBootJars(ctx android.BuilderContext) bool {
- // with EMMA_INSTRUMENT_FRAMEWORK=true ART boot class path libraries have dependencies on framework,
- // therefore dexpreopt ART libraries cannot be dexpreopted in isolation => no ART boot image
- return ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK")
-}
-
type dexpreoptBootJars struct {
defaultBootImage *bootImage
otherImages []*bootImage
@@ -193,7 +187,7 @@
// Accessor function for the apex package. Returns nil if dexpreopt is disabled.
func DexpreoptedArtApexJars(ctx android.BuilderContext) map[android.ArchType]android.OutputPaths {
- if skipDexpreoptBootJars(ctx) || skipDexpreoptArtBootJars(ctx) {
+ if skipDexpreoptBootJars(ctx) {
return nil
}
return artBootImageConfig(ctx).imagesDeps
@@ -222,10 +216,8 @@
// Always create the default boot image first, to get a unique profile rule for all images.
d.defaultBootImage = buildBootImage(ctx, defaultBootImageConfig(ctx))
- if !skipDexpreoptArtBootJars(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)))
- }
+ // 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, apexBootImageConfig(ctx)))
@@ -335,7 +327,7 @@
invocationPath := outputPath.ReplaceExtension(ctx, "invocation")
- cmd.Tool(global.Tools.Dex2oat).
+ cmd.Tool(global.SoongConfig.Dex2oat).
Flag("--avoid-storing-invocation").
FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatImageXms).
@@ -444,7 +436,6 @@
return nil
}
profile := ctx.Config().Once(bootImageProfileRuleKey, func() interface{} {
- tools := global.Tools
defaultProfile := "frameworks/base/config/boot-image-profile.txt"
rule := android.NewRuleBuilder()
@@ -470,7 +461,7 @@
rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
- Tool(tools.Profman).
+ Tool(global.SoongConfig.Profman).
FlagWithInput("--create-profile-from=", bootImageProfile).
FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
FlagForEachArg("--dex-location=", image.dexLocationsDeps).
@@ -499,8 +490,6 @@
return nil
}
return ctx.Config().Once(bootFrameworkProfileRuleKey, func() interface{} {
- tools := global.Tools
-
rule := android.NewRuleBuilder()
rule.MissingDeps(missingDeps)
@@ -521,7 +510,7 @@
rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
- Tool(tools.Profman).
+ Tool(global.SoongConfig.Profman).
Flag("--generate-boot-profile").
FlagWithInput("--create-profile-from=", bootFrameworkProfile).
FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
@@ -598,6 +587,7 @@
func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
if d.dexpreoptConfigForMake != nil {
ctx.Strict("DEX_PREOPT_CONFIG_FOR_MAKE", d.dexpreoptConfigForMake.String())
+ ctx.Strict("DEX_PREOPT_SOONG_CONFIG_FOR_MAKE", android.PathForOutput(ctx, "dexpreopt_soong.config").String())
}
image := d.defaultBootImage
@@ -605,7 +595,6 @@
ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(image.dexPathsDeps.Strings(), " "))
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.dexLocationsDeps, " "))
- ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS", strings.Join(image.imageLocations, ":"))
var imageNames []string
for _, current := range append(d.otherImages, image) {
@@ -618,15 +607,15 @@
sort.Slice(arches, func(i, j int) bool { return arches[i].String() < arches[j].String() })
for _, arch := range arches {
- ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+current.name+"_"+arch.String(), current.vdexInstalls[arch].String())
- ctx.Strict("DEXPREOPT_IMAGE_"+current.name+"_"+arch.String(), current.images[arch].String())
- ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+current.name+"_"+arch.String(), strings.Join(current.imagesDeps[arch].Strings(), " "))
- ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+current.name+"_"+arch.String(), current.installs[arch].String())
- ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+current.name+"_"+arch.String(), current.unstrippedInstalls[arch].String())
- if current.zip != nil {
- }
+ 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())
}
+ ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(current.imageLocations, ":"))
ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String())
}
ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " "))
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 91e0dfb..35748b8 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -37,8 +37,9 @@
func dexpreoptGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw {
return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} {
if f := ctx.Config().DexpreoptGlobalConfig(); f != "" {
+ soongConfig := dexpreopt.CreateGlobalSoongConfig(ctx)
ctx.AddNinjaFileDeps(f)
- globalConfig, data, err := dexpreopt.LoadGlobalConfig(ctx, f)
+ globalConfig, data, err := dexpreopt.LoadGlobalConfig(ctx, f, soongConfig)
if err != nil {
panic(err)
}
@@ -135,6 +136,10 @@
deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName())
artModules := global.ArtApexJars
+ // With EMMA_INSTRUMENT_FRAMEWORK=true the Core libraries depend on jacoco.
+ if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
+ artModules = append(artModules, "jacocoagent")
+ }
frameworkModules := android.RemoveListFromList(global.BootJars,
concat(artModules, getJarsFromApexJarPairs(global.UpdatableBootJars)))
diff --git a/java/java.go b/java/java.go
index 27f69b8..bfdc7fc 100644
--- a/java/java.go
+++ b/java/java.go
@@ -53,6 +53,12 @@
},
},
})
+
+ android.RegisterSdkMemberType(&testSdkMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "java_tests",
+ },
+ })
}
func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
@@ -66,6 +72,7 @@
ctx.RegisterModuleType("java_test", TestFactory)
ctx.RegisterModuleType("java_test_helper_library", TestHelperLibraryFactory)
ctx.RegisterModuleType("java_test_host", TestHostFactory)
+ ctx.RegisterModuleType("java_test_import", JavaTestImportFactory)
ctx.RegisterModuleType("java_import", ImportFactory)
ctx.RegisterModuleType("java_import_host", ImportFactoryHost)
ctx.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
@@ -440,6 +447,7 @@
ExportedPlugins() (android.Paths, []string)
SrcJarArgs() ([]string, android.Paths)
BaseModuleName() string
+ JacocoReportClassesFile() android.Path
}
type SdkLibraryDependency interface {
@@ -1712,6 +1720,10 @@
return proptools.StringDefault(j.deviceProperties.Stem, j.Name())
}
+func (j *Module) JacocoReportClassesFile() android.Path {
+ return j.jacocoReportClassesFile
+}
+
//
// Java libraries (.jar file)
//
@@ -1765,14 +1777,19 @@
}
const (
- aidlIncludeDir = "aidl"
- javaDir = "java"
- jarFileSuffix = ".jar"
+ aidlIncludeDir = "aidl"
+ javaDir = "java"
+ jarFileSuffix = ".jar"
+ testConfigSuffix = "-AndroidTest.xml"
)
// path to the jar file of a java library. Relative to <sdk_root>/<api_dir>
-func (j *Library) sdkSnapshotFilePathForJar() string {
- return filepath.Join(javaDir, j.Name()+jarFileSuffix)
+func sdkSnapshotFilePathForJar(member android.SdkMember) string {
+ return sdkSnapshotFilePathForMember(member, jarFileSuffix)
+}
+
+func sdkSnapshotFilePathForMember(member android.SdkMember, suffix string) string {
+ return filepath.Join(javaDir, member.Name()+suffix)
}
type librarySdkMemberType struct {
@@ -1805,7 +1822,7 @@
j := variant.(*Library)
exportedJar := jarToExportGetter(j)
- snapshotRelativeJavaLibPath := j.sdkSnapshotFilePathForJar()
+ snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(member)
builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
for _, dir := range j.AidlIncludeDirs() {
@@ -1932,6 +1949,16 @@
Test_suites []string `android:"arch_variant"`
}
+type prebuiltTestProperties struct {
+ // list of compatibility suites (for example "cts", "vts") that the module should be
+ // installed into.
+ Test_suites []string `android:"arch_variant"`
+
+ // the name of the test configuration (for example "AndroidTest.xml") that should be
+ // installed with the module.
+ Test_config *string `android:"path,arch_variant"`
+}
+
type Test struct {
Library
@@ -1947,6 +1974,14 @@
testHelperLibraryProperties testHelperLibraryProperties
}
+type JavaTestImport struct {
+ Import
+
+ prebuiltTestProperties prebuiltTestProperties
+
+ testConfig android.Path
+}
+
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
j.testProperties.Test_suites, j.testProperties.Auto_gen_config)
@@ -1959,6 +1994,53 @@
j.Library.GenerateAndroidBuildActions(ctx)
}
+func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.prebuiltTestProperties.Test_config, nil,
+ j.prebuiltTestProperties.Test_suites, nil)
+
+ j.Import.GenerateAndroidBuildActions(ctx)
+}
+
+type testSdkMemberType struct {
+ android.SdkMemberTypeBase
+}
+
+func (mt *testSdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
+ mctx.AddVariationDependencies(nil, dependencyTag, names...)
+}
+
+func (mt *testSdkMemberType) IsInstance(module android.Module) bool {
+ _, ok := module.(*Test)
+ return ok
+}
+
+func (mt *testSdkMemberType) 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]
+ j := variant.(*Test)
+
+ implementationJars := j.ImplementationJars()
+ if len(implementationJars) != 1 {
+ panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
+ }
+
+ snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(member)
+ builder.CopyToSnapshot(implementationJars[0], snapshotRelativeJavaLibPath)
+
+ snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(member, testConfigSuffix)
+ builder.CopyToSnapshot(j.testConfig, snapshotRelativeTestConfigPath)
+
+ module := builder.AddPrebuiltModule(member, "java_test_import")
+ module.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
+ module.AddProperty("test_config", snapshotRelativeTestConfigPath)
+}
+
// java_test builds a and links sources into a `.jar` file for the device, and possibly for the host as well, and
// creates an `AndroidTest.xml` file to allow running the test with `atest` or a `TEST_MAPPING` file.
//
@@ -2002,6 +2084,30 @@
return module
}
+// java_test_import imports one or more `.jar` files into the build graph as if they were built by a java_test module
+// and makes sure that it is added to the appropriate test suite.
+//
+// By default, a java_test_import has a single variant that expects a `.jar` file containing `.class` files that were
+// compiled against an Android classpath.
+//
+// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
+// for host modules.
+func JavaTestImportFactory() android.Module {
+ module := &JavaTestImport{}
+
+ module.AddProperties(
+ &module.Import.properties,
+ &module.prebuiltTestProperties)
+
+ module.Import.properties.Installable = proptools.BoolPtr(true)
+
+ android.InitPrebuiltModule(module, &module.properties.Jars)
+ android.InitApexModule(module)
+ android.InitSdkAwareModule(module)
+ InitJavaModule(module, android.HostAndDeviceSupported)
+ return module
+}
+
// java_test_host builds a and links sources into a `.jar` file for the host, and creates an `AndroidTest.xml` file to
// allow running the test with `atest` or a `TEST_MAPPING` file.
//
@@ -2194,6 +2300,10 @@
return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
}
+func (a *Import) JacocoReportClassesFile() android.Path {
+ return nil
+}
+
func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
}
diff --git a/java/java_test.go b/java/java_test.go
index 2f67cda..30a8ca6 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -486,6 +486,13 @@
name: "stubs-source",
srcs: ["stubs/sources"],
}
+
+ java_test_import {
+ name: "test",
+ jars: ["a.jar"],
+ test_suites: ["cts"],
+ test_config: "AndroidTest.xml",
+ }
`)
fooModule := ctx.ModuleForTests("foo", "android_common")
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index fefd0e6..d5c7579 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -19,9 +19,14 @@
)
func init() {
+ android.RegisterSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory)
android.RegisterModuleType("platform_compat_config", platformCompatConfigFactory)
}
+type platformCompatConfigSingleton struct {
+ metadata android.Path
+}
+
type platformCompatConfigProperties struct {
Src *string `android:"path"`
}
@@ -35,6 +40,52 @@
metadataFile android.OutputPath
}
+func (p *platformCompatConfig) compatConfigMetadata() android.OutputPath {
+ return p.metadataFile
+}
+
+type platformCompatConfigIntf interface {
+ compatConfigMetadata() android.OutputPath
+}
+
+var _ platformCompatConfigIntf = (*platformCompatConfig)(nil)
+
+// compat singleton rules
+func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+
+ var compatConfigMetadata android.Paths
+
+ ctx.VisitAllModules(func(module android.Module) {
+ if c, ok := module.(platformCompatConfigIntf); ok {
+ metadata := c.compatConfigMetadata()
+ compatConfigMetadata = append(compatConfigMetadata, metadata)
+ }
+ })
+
+ if compatConfigMetadata == nil {
+ // nothing to do.
+ return
+ }
+
+ rule := android.NewRuleBuilder()
+ outputPath := android.PathForOutput(ctx, "compat_config", "merged_compat_config.xml")
+
+ rule.Command().
+ BuiltTool(ctx, "process-compat-config").
+ FlagForEachInput("--xml ", compatConfigMetadata).
+ FlagWithOutput("--merged-config ", outputPath)
+
+ rule.Build(pctx, ctx, "merged-compat-config", "Merge compat config")
+
+ p.metadata = outputPath
+}
+
+func (p *platformCompatConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
+ if p.metadata != nil {
+ ctx.Strict("INTERNAL_PLATFORM_MERGED_COMPAT_CONFIG", p.metadata.String())
+ }
+}
+
func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
rule := android.NewRuleBuilder()
@@ -69,6 +120,10 @@
}}
}
+func platformCompatConfigSingletonFactory() android.Singleton {
+ return &platformCompatConfigSingleton{}
+}
+
func platformCompatConfigFactory() android.Module {
module := &platformCompatConfig{}
module.AddProperties(&module.properties)
diff --git a/java/sdk.go b/java/sdk.go
index 6f0f432..66eb284 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -58,7 +58,7 @@
// Returns a sdk version as a number. For modules targeting an unreleased SDK (meaning it does not yet have a number)
// it returns android.FutureApiLevel (10000).
-func sdkVersionToNumber(ctx android.BaseModuleContext, v string) (int, error) {
+func sdkVersionToNumber(ctx android.EarlyModuleContext, v string) (int, error) {
switch v {
case "", "none", "current", "test_current", "system_current", "core_current", "core_platform":
return ctx.Config().DefaultAppTargetSdkInt(), nil
@@ -72,7 +72,7 @@
}
}
-func sdkVersionToNumberAsString(ctx android.BaseModuleContext, v string) (string, error) {
+func sdkVersionToNumberAsString(ctx android.EarlyModuleContext, v string) (string, error) {
n, err := sdkVersionToNumber(ctx, v)
if err != nil {
return "", err
@@ -80,7 +80,7 @@
return strconv.Itoa(n), nil
}
-func decodeSdkDep(ctx android.BaseModuleContext, sdkContext sdkContext) sdkDep {
+func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep {
v := sdkContext.sdkVersion()
// For PDK builds, use the latest SDK version instead of "current"
@@ -127,12 +127,12 @@
}
if !jarPath.Valid() {
- ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, jar)
+ ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", sdk, jar)
return sdkDep{}
}
if !aidlPath.Valid() {
- ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, aidl)
+ ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", sdk, aidl)
return sdkDep{}
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 4067bd3..9b30e2c 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -24,7 +24,6 @@
"strings"
"sync"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -54,11 +53,6 @@
`</permissions>\n`
)
-type stubsLibraryDependencyTag struct {
- blueprint.BaseDependencyTag
- name string
-}
-
var (
publicApiStubsTag = dependencyTag{name: "public"}
systemApiStubsTag = dependencyTag{name: "system"}
@@ -103,12 +97,22 @@
// List of Java libraries that will be in the classpath when building stubs
Stub_only_libs []string `android:"arch_variant"`
- // list of package names that will be documented and publicized as API
+ // list of package names that will be documented and publicized as API.
+ // This allows the API to be restricted to a subset of the source files provided.
+ // If this is unspecified then all the source files will be treated as being part
+ // of the API.
Api_packages []string
// list of package names that must be hidden from the API
Hidden_api_packages []string
+ // the relative path to the directory containing the api specification files.
+ // Defaults to "api".
+ Api_dir *string
+
+ // If set to true there is no runtime library.
+ Api_only *bool
+
// local files that are used within user customized droiddoc options.
Droiddoc_option_files []string
@@ -131,6 +135,9 @@
// don't create dist rules.
No_dist *bool `blueprint:"mutated"`
+ // indicates whether system and test apis should be managed.
+ Has_system_and_test_apis bool `blueprint:"mutated"`
+
// TODO: determines whether to create HTML doc or not
//Html_doc *bool
}
@@ -166,8 +173,7 @@
}
ctx.AddVariationDependencies(nil, publicApiFileTag, module.docsName(apiScopePublic))
- sdkDep := decodeSdkDep(ctx, sdkContext(&module.Library))
- if sdkDep.hasStandardLibs() {
+ if module.sdkLibraryProperties.Has_system_and_test_apis {
if useBuiltStubs {
ctx.AddVariationDependencies(nil, systemApiStubsTag, module.stubsName(apiScopeSystem))
ctx.AddVariationDependencies(nil, testApiStubsTag, module.stubsName(apiScopeTest))
@@ -180,7 +186,10 @@
}
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- module.Library.GenerateAndroidBuildActions(ctx)
+ // Don't build an implementation library if this is api only.
+ if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
+ module.Library.GenerateAndroidBuildActions(ctx)
+ }
module.buildPermissionsFile(ctx)
@@ -244,6 +253,9 @@
}
func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
+ if proptools.Bool(module.sdkLibraryProperties.Api_only) {
+ return nil
+ }
entriesList := module.Library.AndroidMkEntries()
entries := &entriesList[0]
entries.Required = append(entries.Required, module.xmlFileName())
@@ -362,7 +374,7 @@
// SDK version that the stubs library is built against. Note that this is always
// *current. Older stubs library built with a numberd SDK version is created from
// the prebuilt jar.
-func (module *SdkLibrary) sdkVersion(apiScope apiScope) string {
+func (module *SdkLibrary) sdkVersionForScope(apiScope apiScope) string {
switch apiScope {
case apiScopePublic:
return "current"
@@ -375,6 +387,18 @@
}
}
+// Get the sdk version for use when compiling the stubs library.
+func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.LoadHookContext, apiScope apiScope) string {
+ sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
+ if sdkDep.hasStandardLibs() {
+ // If building against a standard sdk then use the sdk version appropriate for the scope.
+ return module.sdkVersionForScope(apiScope)
+ } else {
+ // Otherwise, use no system module.
+ return "none"
+ }
+}
+
// $(INTERNAL_PLATFORM_<apiTagName>_API_FILE) points to the generated
// api file for the current source
// TODO: remove this when apicheck is done in soong
@@ -422,14 +446,15 @@
props := struct {
Name *string
Srcs []string
+ Installable *bool
Sdk_version *string
+ System_modules *string
Libs []string
Soc_specific *bool
Device_specific *bool
Product_specific *bool
System_ext_specific *bool
Compile_dex *bool
- System_modules *string
Java_version *string
Product_variables struct {
Unbundled_build struct {
@@ -445,23 +470,19 @@
}
}{}
- sdkVersion := module.sdkVersion(apiScope)
- sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
- if !sdkDep.hasStandardLibs() {
- sdkVersion = "none"
- }
-
props.Name = proptools.StringPtr(module.stubsName(apiScope))
// sources are generated from the droiddoc
props.Srcs = []string{":" + module.docsName(apiScope)}
+ sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
props.Sdk_version = proptools.StringPtr(sdkVersion)
+ props.System_modules = module.Library.Module.deviceProperties.System_modules
+ 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.System_modules = module.Library.Module.deviceProperties.System_modules
props.Openjdk9.Srcs = module.Library.Module.properties.Openjdk9.Srcs
props.Openjdk9.Javacflags = module.Library.Module.properties.Openjdk9.Javacflags
props.Java_version = module.Library.Module.properties.Java_version
@@ -484,12 +505,13 @@
// Creates a droiddoc module that creates stubs source files from the given full source
// files
-func (module *SdkLibrary) createDocs(mctx android.LoadHookContext, apiScope apiScope) {
+func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiScope apiScope) {
props := struct {
Name *string
Srcs []string
Installable *bool
Sdk_version *string
+ System_modules *string
Libs []string
Arg_files []string
Args *string
@@ -511,6 +533,8 @@
}{}
sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
+ // Use the platform API if standard libraries were requested, otherwise use
+ // no default libraries.
sdkVersion := ""
if !sdkDep.hasStandardLibs() {
sdkVersion = "none"
@@ -519,6 +543,7 @@
props.Name = proptools.StringPtr(module.docsName(apiScope))
props.Srcs = append(props.Srcs, module.Library.Module.properties.Srcs...)
props.Sdk_version = proptools.StringPtr(sdkVersion)
+ props.System_modules = module.Library.Module.deviceProperties.System_modules
props.Installable = proptools.BoolPtr(false)
// A droiddoc module has only one Libs property and doesn't distinguish between
// shared libs and static libs. So we need to add both of these libs to Libs property.
@@ -531,21 +556,36 @@
props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
- droiddocArgs := " --stub-packages " + strings.Join(module.sdkLibraryProperties.Api_packages, ":") +
- " " + android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package ") +
- " " + android.JoinWithPrefix(module.sdkLibraryProperties.Droiddoc_options, " ") +
- " --hide MissingPermission --hide BroadcastBehavior " +
- "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
- "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
+ droiddocArgs := []string{}
+ if len(module.sdkLibraryProperties.Api_packages) != 0 {
+ droiddocArgs = append(droiddocArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
+ }
+ if len(module.sdkLibraryProperties.Hidden_api_packages) != 0 {
+ droiddocArgs = append(droiddocArgs,
+ android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package "))
+ }
+ droiddocArgs = append(droiddocArgs, module.sdkLibraryProperties.Droiddoc_options...)
+ disabledWarnings := []string{
+ "MissingPermission",
+ "BroadcastBehavior",
+ "HiddenSuperclass",
+ "DeprecationMismatch",
+ "UnavailableSymbol",
+ "SdkConstant",
+ "HiddenTypeParameter",
+ "Todo",
+ "Typo",
+ }
+ droiddocArgs = append(droiddocArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
switch apiScope {
case apiScopeSystem:
- droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.SystemApi"
+ droiddocArgs = append(droiddocArgs, "-showAnnotation android.annotation.SystemApi")
case apiScopeTest:
- droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.TestApi"
+ droiddocArgs = append(droiddocArgs, " -showAnnotation android.annotation.TestApi")
}
props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
- props.Args = proptools.StringPtr(droiddocArgs)
+ props.Args = proptools.StringPtr(strings.Join(droiddocArgs, " "))
// List of APIs identified from the provided source files are created. They are later
// compared against to the not-yet-released (a.k.a current) list of APIs and to the
@@ -560,8 +600,9 @@
currentApiFileName = "test-" + currentApiFileName
removedApiFileName = "test-" + removedApiFileName
}
- currentApiFileName = path.Join("api", currentApiFileName)
- removedApiFileName = path.Join("api", removedApiFileName)
+ apiDir := module.getApiDir()
+ currentApiFileName = path.Join(apiDir, currentApiFileName)
+ removedApiFileName = path.Join(apiDir, removedApiFileName)
// TODO(jiyong): remove these three props
props.Api_tag_name = proptools.StringPtr(module.apiTagName(apiScope))
props.Api_filename = proptools.StringPtr(currentApiFileName)
@@ -626,7 +667,11 @@
jar := filepath.Join(dir, module.BaseModuleName()+".jar")
jarPath := android.ExistentPathForSource(ctx, jar)
if !jarPath.Valid() {
- ctx.PropertyErrorf("sdk_library", "invalid sdk version %q, %q does not exist", v, jar)
+ if ctx.Config().AllowMissingDependencies() {
+ return android.Paths{android.PathForSource(ctx, jar)}
+ } else {
+ ctx.PropertyErrorf("sdk_library", "invalid sdk version %q, %q does not exist", sdkVersion, jar)
+ }
return nil
}
return android.Paths{jarPath.Path()}
@@ -676,6 +721,10 @@
}).(*[]string)
}
+func (module *SdkLibrary) getApiDir() string {
+ return proptools.StringDefault(module.sdkLibraryProperties.Api_dir, "api")
+}
+
// For a java_sdk_library module, create internal modules for stubs, docs,
// runtime libs and xml file. If requested, the stubs and docs are created twice
// once for public API level and once for system API level
@@ -685,16 +734,25 @@
return
}
- if len(module.sdkLibraryProperties.Api_packages) == 0 {
- mctx.PropertyErrorf("api_packages", "java_sdk_library must specify api_packages")
- return
+ // If this builds against standard libraries (i.e. is not part of the core libraries)
+ // then assume it provides both system and test apis. Otherwise, assume it does not and
+ // also assume it does not contribute to the dist build.
+ sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
+ hasSystemAndTestApis := sdkDep.hasStandardLibs()
+ module.sdkLibraryProperties.Has_system_and_test_apis = hasSystemAndTestApis
+ module.sdkLibraryProperties.No_dist = proptools.BoolPtr(!hasSystemAndTestApis)
+
+ scopes := []string{""}
+ if hasSystemAndTestApis {
+ scopes = append(scopes, "system-", "test-")
}
missing_current_api := false
- for _, scope := range []string{"", "system-", "test-"} {
+ apiDir := module.getApiDir()
+ for _, scope := range scopes {
for _, api := range []string{"current.txt", "removed.txt"} {
- path := path.Join(mctx.ModuleDir(), "api", scope+api)
+ path := path.Join(mctx.ModuleDir(), apiDir, scope+api)
p := android.ExistentPathForSource(mctx, path)
if !p.Valid() {
mctx.ModuleErrorf("Current api file %#v doesn't exist", path)
@@ -713,33 +771,35 @@
mctx.ModuleErrorf("One or more current api files are missing. "+
"You can update them by:\n"+
- "%s %q && m update-api", script, mctx.ModuleDir())
+ "%s %q %s && m update-api",
+ script, filepath.Join(mctx.ModuleDir(), apiDir), strings.Join(scopes, " "))
return
}
// for public API stubs
module.createStubsLibrary(mctx, apiScopePublic)
- module.createDocs(mctx, apiScopePublic)
+ module.createStubsSources(mctx, apiScopePublic)
- sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
- if sdkDep.hasStandardLibs() {
+ if hasSystemAndTestApis {
// for system API stubs
module.createStubsLibrary(mctx, apiScopeSystem)
- module.createDocs(mctx, apiScopeSystem)
+ module.createStubsSources(mctx, apiScopeSystem)
// for test API stubs
module.createStubsLibrary(mctx, apiScopeTest)
- module.createDocs(mctx, apiScopeTest)
-
- // for runtime
- module.createXmlFile(mctx)
+ module.createStubsSources(mctx, apiScopeTest)
}
- // record java_sdk_library modules so that they are exported to make
- javaSdkLibraries := javaSdkLibraries(mctx.Config())
- javaSdkLibrariesLock.Lock()
- defer javaSdkLibrariesLock.Unlock()
- *javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
+ if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
+ // for runtime
+ module.createXmlFile(mctx)
+
+ // record java_sdk_library modules so that they are exported to make
+ javaSdkLibraries := javaSdkLibraries(mctx.Config())
+ javaSdkLibrariesLock.Lock()
+ defer javaSdkLibrariesLock.Unlock()
+ *javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
+ }
}
func (module *SdkLibrary) InitSdkLibraryProperties() {
diff --git a/java/testing.go b/java/testing.go
index e157dd0..08bae44 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -34,6 +34,7 @@
"GENRULE_NOTICE": nil,
"LIB_NOTICE": nil,
"TOOL_NOTICE": nil,
+ "AndroidTest.xml": nil,
"java-res/a/a": nil,
"java-res/b/b": nil,
"java-res2/a": nil,
@@ -204,9 +205,6 @@
systemModules := []string{
"core-current-stubs-system-modules",
"core-platform-api-stubs-system-modules",
- "android_stubs_current_system_modules",
- "android_system_stubs_current_system_modules",
- "android_test_stubs_current_system_modules",
}
for _, extra := range systemModules {
diff --git a/python/androidmk.go b/python/androidmk.go
index aae7ced..8e8e8ef 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -76,6 +76,10 @@
p.testConfig.String())
}
}
+
+ if !BoolDefault(p.binaryProperties.Auto_gen_config, true) {
+ fmt.Fprintln(w, "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG := true")
+ }
})
base.subAndroidMk(ret, p.binaryDecorator.pythonInstaller)
}
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 2636d97..0fba739 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -99,6 +99,9 @@
if test.testConfig != nil {
fmt.Fprintln(w, "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")
+ }
})
// TODO(chh): add test data with androidMkWriteTestData(test.data, ctx, ret)
}
diff --git a/rust/config/global.go b/rust/config/global.go
index 4d87780..ad8eb3a 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.37.0"
+ RustDefaultVersion = "1.40.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2018"
Stdlibs = []string{
diff --git a/scripts/gen-java-current-api-files.sh b/scripts/gen-java-current-api-files.sh
index 517d391..547387a 100755
--- a/scripts/gen-java-current-api-files.sh
+++ b/scripts/gen-java-current-api-files.sh
@@ -15,15 +15,16 @@
# limitations under the License.
if [[ -z "$1" ]]; then
- echo "usage: $0 <modulePath>" >&2
+ echo "usage: $0 <modulePath> scopes..." >&2
exit 1
fi
-api_dir=$1/api
+api_dir=$1
+shift
mkdir -p "$api_dir"
-scopes=("" system- test-)
+scopes=("" "$@")
apis=(current removed)
for scope in "${scopes[@]}"; do
@@ -31,3 +32,4 @@
touch "${api_dir}/${scope}${api}.txt"
done
done
+
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 8c72658..218a16a 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -321,6 +321,112 @@
)
}
+func TestSnapshotWithJavaTest(t *testing.T) {
+ result := testSdkWithJava(t, `
+ module_exports {
+ name: "myexports",
+ java_tests: ["myjavatests"],
+ }
+
+ java_test {
+ name: "myjavatests",
+ srcs: ["Test.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ host_supported: true,
+ }
+ `)
+
+ result.CheckSnapshot("myexports", "android_common", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_test_import {
+ name: "myexports_myjavatests@current",
+ sdk_member_name: "myjavatests",
+ jars: ["java/myjavatests.jar"],
+ test_config: "java/myjavatests-AndroidTest.xml",
+}
+
+java_test_import {
+ name: "myjavatests",
+ prefer: false,
+ jars: ["java/myjavatests.jar"],
+ test_config: "java/myjavatests-AndroidTest.xml",
+}
+
+module_exports_snapshot {
+ name: "myexports@current",
+ java_tests: ["myexports_myjavatests@current"],
+}
+`),
+ checkAllCopyRules(`
+.intermediates/myjavatests/android_common/javac/myjavatests.jar -> java/myjavatests.jar
+.intermediates/myjavatests/android_common/myjavatests.config -> java/myjavatests-AndroidTest.xml
+`),
+ )
+}
+
+func TestHostSnapshotWithJavaTest(t *testing.T) {
+ // b/145598135 - Generating host snapshots for anything other than linux is not supported.
+ SkipIfNotLinux(t)
+
+ result := testSdkWithJava(t, `
+ module_exports {
+ name: "myexports",
+ device_supported: false,
+ host_supported: true,
+ java_tests: ["myjavatests"],
+ }
+
+ java_test {
+ name: "myjavatests",
+ device_supported: false,
+ host_supported: true,
+ srcs: ["Test.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ }
+ `)
+
+ result.CheckSnapshot("myexports", "linux_glibc_common", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_test_import {
+ name: "myexports_myjavatests@current",
+ sdk_member_name: "myjavatests",
+ device_supported: false,
+ host_supported: true,
+ jars: ["java/myjavatests.jar"],
+ test_config: "java/myjavatests-AndroidTest.xml",
+}
+
+java_test_import {
+ name: "myjavatests",
+ prefer: false,
+ device_supported: false,
+ host_supported: true,
+ jars: ["java/myjavatests.jar"],
+ test_config: "java/myjavatests-AndroidTest.xml",
+}
+
+module_exports_snapshot {
+ name: "myexports@current",
+ device_supported: false,
+ host_supported: true,
+ java_tests: ["myexports_myjavatests@current"],
+}
+`),
+ checkAllCopyRules(`
+.intermediates/myjavatests/linux_glibc_common/javac/myjavatests.jar -> java/myjavatests.jar
+.intermediates/myjavatests/linux_glibc_common/myjavatests.config -> java/myjavatests-AndroidTest.xml
+`),
+ )
+}
+
func testSdkWithDroidstubs(t *testing.T, bp string) *testSdkResult {
t.Helper()
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index f212fb6..2a5a51a 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -59,6 +59,7 @@
"util.go",
],
testSrcs: [
+ "cleanbuild_test.go",
"config_test.go",
"environment_test.go",
"util_test.go",
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index 0b44b4d..1c4f574 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -15,10 +15,12 @@
package build
import (
+ "bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
+ "sort"
"strings"
"android/soong/ui/metrics"
@@ -177,3 +179,78 @@
writeConfig()
}
+
+// cleanOldFiles takes an input file (with all paths relative to basePath), and removes files from
+// the filesystem if they were removed from the input file since the last execution.
+func cleanOldFiles(ctx Context, basePath, file string) {
+ file = filepath.Join(basePath, file)
+ oldFile := file + ".previous"
+
+ if _, err := os.Stat(file); err != nil {
+ ctx.Fatalf("Expected %q to be readable", file)
+ }
+
+ if _, err := os.Stat(oldFile); os.IsNotExist(err) {
+ if err := os.Rename(file, oldFile); err != nil {
+ ctx.Fatalf("Failed to rename file list (%q->%q): %v", file, oldFile, err)
+ }
+ return
+ }
+
+ var newPaths, oldPaths []string
+ if newData, err := ioutil.ReadFile(file); err == nil {
+ if oldData, err := ioutil.ReadFile(oldFile); err == nil {
+ // Common case: nothing has changed
+ if bytes.Equal(newData, oldData) {
+ return
+ }
+ newPaths = strings.Fields(string(newData))
+ oldPaths = strings.Fields(string(oldData))
+ } else {
+ ctx.Fatalf("Failed to read list of installable files (%q): %v", oldFile, err)
+ }
+ } else {
+ ctx.Fatalf("Failed to read list of installable files (%q): %v", file, err)
+ }
+
+ // These should be mostly sorted by make already, but better make sure Go concurs
+ sort.Strings(newPaths)
+ sort.Strings(oldPaths)
+
+ for len(oldPaths) > 0 {
+ if len(newPaths) > 0 {
+ if oldPaths[0] == newPaths[0] {
+ // Same file; continue
+ newPaths = newPaths[1:]
+ oldPaths = oldPaths[1:]
+ continue
+ } else if oldPaths[0] > newPaths[0] {
+ // New file; ignore
+ newPaths = newPaths[1:]
+ continue
+ }
+ }
+ // File only exists in the old list; remove if it exists
+ old := filepath.Join(basePath, oldPaths[0])
+ oldPaths = oldPaths[1:]
+ if fi, err := os.Stat(old); err == nil {
+ if fi.IsDir() {
+ if err := os.Remove(old); err == nil {
+ ctx.Println("Removed directory that is no longer installed: ", 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`")
+ }
+ } else {
+ if err := os.Remove(old); err == nil {
+ ctx.Println("Removed file that is no longer installed: ", old)
+ } else if !os.IsNotExist(err) {
+ ctx.Fatalf("Failed to remove file that is no longer installed (%q): %v", old, err)
+ }
+ }
+ }
+ }
+
+ // Use the new list as the base for the next build
+ os.Rename(file, oldFile)
+}
diff --git a/ui/build/cleanbuild_test.go b/ui/build/cleanbuild_test.go
new file mode 100644
index 0000000..89f4ad9
--- /dev/null
+++ b/ui/build/cleanbuild_test.go
@@ -0,0 +1,100 @@
+// 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 build
+
+import (
+ "android/soong/ui/logger"
+ "bytes"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "reflect"
+ "sort"
+ "strings"
+ "testing"
+)
+
+func TestCleanOldFiles(t *testing.T) {
+ dir, err := ioutil.TempDir("", "testcleanoldfiles")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+
+ ctx := testContext()
+ logBuf := &bytes.Buffer{}
+ ctx.Logger = logger.New(logBuf)
+
+ touch := func(names ...string) {
+ for _, name := range names {
+ if f, err := os.Create(filepath.Join(dir, name)); err != nil {
+ t.Fatal(err)
+ } else {
+ f.Close()
+ }
+ }
+ }
+ runCleanOldFiles := func(names ...string) {
+ data := []byte(strings.Join(names, " "))
+ if err := ioutil.WriteFile(filepath.Join(dir, ".installed"), data, 0666); err != nil {
+ t.Fatal(err)
+ }
+
+ cleanOldFiles(ctx, dir, ".installed")
+ }
+
+ assertFileList := func(names ...string) {
+ t.Helper()
+
+ sort.Strings(names)
+
+ var foundNames []string
+ if foundFiles, err := ioutil.ReadDir(dir); err == nil {
+ for _, fi := range foundFiles {
+ foundNames = append(foundNames, fi.Name())
+ }
+ } else {
+ t.Fatal(err)
+ }
+
+ if !reflect.DeepEqual(names, foundNames) {
+ t.Errorf("Expected a different list of files:\nwant: %v\n got: %v", names, foundNames)
+ t.Error("Log: ", logBuf.String())
+ logBuf.Reset()
+ }
+ }
+
+ // Initial list of potential files
+ runCleanOldFiles("foo", "bar")
+ touch("foo", "bar", "baz")
+ assertFileList("foo", "bar", "baz", ".installed.previous")
+
+ // This should be a no-op, as the list hasn't changed
+ runCleanOldFiles("foo", "bar")
+ assertFileList("foo", "bar", "baz", ".installed", ".installed.previous")
+
+ // This should be a no-op, as only a file was added
+ runCleanOldFiles("foo", "bar", "foo2")
+ assertFileList("foo", "bar", "baz", ".installed.previous")
+
+ // "bar" should be removed, foo2 should be ignored as it was never there
+ runCleanOldFiles("foo")
+ assertFileList("foo", "baz", ".installed.previous")
+
+ // Recreate bar, and create foo2. Ensure that they aren't removed
+ touch("bar", "foo2")
+ runCleanOldFiles("foo", "baz")
+ assertFileList("foo", "bar", "baz", "foo2", ".installed.previous")
+}
diff --git a/ui/build/config.go b/ui/build/config.go
index fae569f..c084171 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -55,8 +55,9 @@
pdkBuild bool
- brokenDupRules bool
- brokenUsesNetwork bool
+ brokenDupRules bool
+ brokenUsesNetwork bool
+ brokenNinjaEnvVars []string
pathReplaced bool
}
@@ -907,6 +908,14 @@
return c.brokenUsesNetwork
}
+func (c *configImpl) SetBuildBrokenNinjaUsesEnvVars(val []string) {
+ c.brokenNinjaEnvVars = val
+}
+
+func (c *configImpl) BuildBrokenNinjaUsesEnvVars() []string {
+ return c.brokenNinjaEnvVars
+}
+
func (c *configImpl) SetTargetDeviceDir(dir string) {
c.targetDeviceDir = dir
}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 4270bb1..c3da38b 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -216,6 +216,9 @@
// Whether to enable the network during the build
"BUILD_BROKEN_USES_NETWORK",
+ // Extra environment variables to be exported to ninja
+ "BUILD_BROKEN_NINJA_USES_ENV_VARS",
+
// Not used, but useful to be in the soong.log
"BOARD_VNDK_VERSION",
@@ -284,4 +287,5 @@
config.SetPdkBuild(make_vars["TARGET_BUILD_PDK"] == "true")
config.SetBuildBrokenDupRules(make_vars["BUILD_BROKEN_DUP_RULES"] == "true")
config.SetBuildBrokenUsesNetwork(make_vars["BUILD_BROKEN_USES_NETWORK"] == "true")
+ config.SetBuildBrokenNinjaUsesEnvVars(strings.Fields(make_vars["BUILD_BROKEN_NINJA_USES_ENV_VARS"]))
}
diff --git a/ui/build/kati.go b/ui/build/kati.go
index ac09ce1..a845c5b 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -153,6 +153,7 @@
runKati(ctx, config, katiBuildSuffix, args, func(env *Environment) {})
cleanCopyHeaders(ctx, config)
+ cleanOldInstalledFiles(ctx, config)
}
func cleanCopyHeaders(ctx Context, config Config) {
@@ -192,6 +193,23 @@
})
}
+func cleanOldInstalledFiles(ctx Context, config Config) {
+ ctx.BeginTrace("clean", "clean old installed files")
+ defer ctx.EndTrace()
+
+ // We shouldn't be removing files from one side of the two-step asan builds
+ var suffix string
+ if v, ok := config.Environment().Get("SANITIZE_TARGET"); ok {
+ if sanitize := strings.Fields(v); inList("address", sanitize) {
+ suffix = "_asan"
+ }
+ }
+
+ cleanOldFiles(ctx, config.ProductOut(), ".installable_files"+suffix)
+
+ cleanOldFiles(ctx, config.HostOut(), ".installable_test_files")
+}
+
func runKatiPackage(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunKati, "kati package")
defer ctx.EndTrace()
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index d5baafe..8c6ebb8 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -18,6 +18,7 @@
"fmt"
"os"
"path/filepath"
+ "sort"
"strconv"
"strings"
"time"
@@ -65,8 +66,6 @@
cmd.Environment.AppendFromKati(config.KatiEnvFile())
}
- cmd.Environment.Set("DIST_DIR", config.DistDir())
-
// Allow both NINJA_ARGS and NINJA_EXTRA_ARGS, since both have been
// used in the past to specify extra ninja arguments.
if extra, ok := cmd.Environment.Get("NINJA_ARGS"); ok {
@@ -85,6 +84,74 @@
ninjaHeartbeatDuration = overrideDuration
}
}
+
+ // Filter the environment, as ninja does not rebuild files when environment variables change.
+ //
+ // Anything listed here must not change the output of rules/actions when the value changes,
+ // otherwise incremental builds may be unsafe. Vars explicitly set to stable values
+ // elsewhere in soong_ui are fine.
+ //
+ // For the majority of cases, either Soong or the makefiles should be replicating any
+ // necessary environment variables in the command line of each action that needs it.
+ if cmd.Environment.IsEnvTrue("ALLOW_NINJA_ENV") {
+ ctx.Println("Allowing all environment variables during ninja; incremental builds may be unsafe.")
+ } else {
+ cmd.Environment.Allow(append([]string{
+ "ASAN_SYMBOLIZER_PATH",
+ "HOME",
+ "JAVA_HOME",
+ "LANG",
+ "LC_MESSAGES",
+ "OUT_DIR",
+ "PATH",
+ "PWD",
+ "PYTHONDONTWRITEBYTECODE",
+ "TMPDIR",
+ "USER",
+
+ // TODO: remove these carefully
+ "ASAN_OPTIONS",
+ "TARGET_BUILD_APPS",
+ "TARGET_BUILD_VARIANT",
+ "TARGET_PRODUCT",
+ // b/147197813 - used by art-check-debug-apex-gen
+ "EMMA_INSTRUMENT_FRAMEWORK",
+
+ // Goma -- gomacc may not need all of these
+ "GOMA_DIR",
+ "GOMA_DISABLED",
+ "GOMA_FAIL_FAST",
+ "GOMA_FALLBACK",
+ "GOMA_GCE_SERVICE_ACCOUNT",
+ "GOMA_TMP_DIR",
+ "GOMA_USE_LOCAL",
+
+ // RBE client
+ "FLAG_exec_root",
+ "FLAG_exec_strategy",
+ "FLAG_invocation_id",
+ "FLAG_log_dir",
+ "FLAG_platform",
+ "FLAG_server_address",
+
+ // ccache settings
+ "CCACHE_COMPILERCHECK",
+ "CCACHE_SLOPPINESS",
+ "CCACHE_BASEDIR",
+ "CCACHE_CPP2",
+ }, config.BuildBrokenNinjaUsesEnvVars()...)...)
+ }
+
+ cmd.Environment.Set("DIST_DIR", config.DistDir())
+ cmd.Environment.Set("SHELL", "/bin/bash")
+
+ ctx.Verboseln("Ninja environment: ")
+ envVars := cmd.Environment.Environ()
+ sort.Strings(envVars)
+ for _, envVar := range envVars {
+ ctx.Verbosef(" %s", envVar)
+ }
+
// Poll the ninja log for updates; if it isn't updated enough, then we want to show some diagnostics
done := make(chan struct{})
defer close(done)
diff --git a/ui/status/critical_path.go b/ui/status/critical_path.go
index 444327b..8065c60 100644
--- a/ui/status/critical_path.go
+++ b/ui/status/critical_path.go
@@ -112,8 +112,10 @@
if !cp.start.IsZero() {
elapsedTime := cp.end.Sub(cp.start).Round(time.Second)
cp.log.Verbosef("elapsed time %s", elapsedTime.String())
- cp.log.Verbosef("perfect parallelism ratio %d%%",
- int(float64(criticalTime)/float64(elapsedTime)*100))
+ if elapsedTime > 0 {
+ cp.log.Verbosef("perfect parallelism ratio %d%%",
+ int(float64(criticalTime)/float64(elapsedTime)*100))
+ }
}
cp.log.Verbose("critical path:")
for i := len(criticalPath) - 1; i >= 0; i-- {