Merge "Do not set JavaInfoProvider in java_sdk_library" into main
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go
index d2a9622..b902f8b 100644
--- a/android/aconfig_providers.go
+++ b/android/aconfig_providers.go
@@ -107,7 +107,7 @@
mergedAconfigFiles := make(map[string]Paths)
mergedModeInfos := make(map[string]ModeInfo)
- ctx.VisitDirectDepsIgnoreBlueprint(func(module Module) {
+ ctx.VisitDirectDeps(func(module Module) {
if aconfig_dep, ok := OtherModuleProvider(ctx, module, CodegenInfoProvider); ok && len(aconfig_dep.ModeInfos) > 0 {
maps.Copy(mergedModeInfos, aconfig_dep.ModeInfos)
}
diff --git a/android/arch_list.go b/android/arch_list.go
index a47d5eb..389f194 100644
--- a/android/arch_list.go
+++ b/android/arch_list.go
@@ -112,9 +112,6 @@
}
var archFeatures = map[ArchType][]string{
- Arm: {
- "neon",
- },
Arm64: {
"dotprod",
},
@@ -144,17 +141,6 @@
}
var androidArchFeatureMap = map[ArchType]map[string][]string{
- Arm: {
- "armv7-a-neon": {
- "neon",
- },
- "armv8-a": {
- "neon",
- },
- "armv8-2a": {
- "neon",
- },
- },
Arm64: {
"armv8-2a-dotprod": {
"dotprod",
diff --git a/android/base_module_context.go b/android/base_module_context.go
index bb81377..c7d7573 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -113,31 +113,22 @@
// the first DependencyTag.
GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
- // VisitDirectDepsBlueprint calls visit for each direct dependency. If there are multiple
+ // VisitDirectDeps calls visit for each direct dependency. If there are multiple
+ // direct dependencies on the same module visit will be called multiple times on that module
+ // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
+ // dependencies are disabled.
+ //
+ // The Module passed to the visit function should not be retained outside of the visit
+ // function, it may be invalidated by future mutators.
+ VisitDirectDeps(visit func(Module))
+
+ // VisitDirectDeps calls visit for each direct dependency. If there are multiple
// direct dependencies on the same module visit will be called multiple times on that module
// and OtherModuleDependencyTag will return a different tag for each.
//
// The Module passed to the visit function should not be retained outside of the visit
// function, it may be invalidated by future mutators.
- VisitDirectDepsBlueprint(visit func(blueprint.Module))
-
- // VisitDirectDepsIgnoreBlueprint calls visit for each direct dependency. If there are multiple
- // direct dependencies on the same module visit will be called multiple times on that module
- // and OtherModuleDependencyTag will return a different tag for each. It silently ignores any
- // dependencies that are not an android.Module.
- //
- // The Module passed to the visit function should not be retained outside of the visit
- // function, it may be invalidated by future mutators.
- VisitDirectDepsIgnoreBlueprint(visit func(Module))
-
- // VisitDirectDeps calls visit for each direct dependency. If there are multiple
- // direct dependencies on the same module visit will be called multiple times on that module
- // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
- // dependencies are not an android.Module.
- //
- // The Module passed to the visit function should not be retained outside of the visit
- // function, it may be invalidated by future mutators.
- VisitDirectDeps(visit func(Module))
+ VisitDirectDepsAllowDisabled(visit func(Module))
VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
@@ -164,17 +155,6 @@
// invalidated by future mutators.
WalkDeps(visit func(child, parent Module) bool)
- // WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency
- // tree in top down order. visit may be called multiple times for the same (child, parent)
- // pair if there are multiple direct dependencies between the child and parent with different
- // tags. OtherModuleDependencyTag will return the tag for the currently visited
- // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down
- // to child.
- //
- // The Modules passed to the visit function should not be retained outside of the visit function, they may be
- // invalidated by future mutators.
- WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool)
-
// GetWalkPath is supposed to be called in visit function passed in WalkDeps()
// and returns a top-down dependency path from a start module to current child module.
GetWalkPath() []Module
@@ -220,10 +200,6 @@
// EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context
// can be used to evaluate the final value of Configurable properties.
EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue
-
- // HasMutatorFinished returns true if the given mutator has finished running.
- // It will panic if given an invalid mutator name.
- HasMutatorFinished(mutatorName string) bool
}
type baseModuleContext struct {
@@ -274,10 +250,6 @@
b.bp.SetProvider(provider, value)
}
-func (b *baseModuleContext) HasMutatorFinished(mutatorName string) bool {
- return b.bp.HasMutatorFinished(mutatorName)
-}
-
func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
return b.bp.GetDirectDepWithTag(name, tag)
}
@@ -319,7 +291,7 @@
return true
}
-func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool, ignoreBlueprint bool) Module {
+func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
aModule, _ := module.(Module)
if !strict {
@@ -327,10 +299,7 @@
}
if aModule == nil {
- if !ignoreBlueprint {
- b.ModuleErrorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag)
- }
- return nil
+ panic(fmt.Errorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag))
}
if !aModule.Enabled(b) {
@@ -353,15 +322,8 @@
func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
var deps []dep
- b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
- if aModule, _ := module.(Module); aModule != nil {
- if aModule.base().BaseModuleName() == name {
- returnedTag := b.bp.OtherModuleDependencyTag(aModule)
- if tag == nil || returnedTag == tag {
- deps = append(deps, dep{aModule, returnedTag})
- }
- }
- } else if b.bp.OtherModuleName(module) == name {
+ b.VisitDirectDeps(func(module Module) {
+ if module.base().BaseModuleName() == name {
returnedTag := b.bp.OtherModuleDependencyTag(module)
if tag == nil || returnedTag == tag {
deps = append(deps, dep{module, returnedTag})
@@ -404,11 +366,9 @@
func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
var deps []Module
- b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
- if aModule, _ := module.(Module); aModule != nil {
- if b.bp.OtherModuleDependencyTag(aModule) == tag {
- deps = append(deps, aModule)
- }
+ b.VisitDirectDeps(func(module Module) {
+ if b.bp.OtherModuleDependencyTag(module) == tag {
+ deps = append(deps, module)
}
})
return deps
@@ -421,30 +381,24 @@
return b.getDirectDepFirstTag(name)
}
-func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
- b.bp.VisitDirectDeps(visit)
-}
-
func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
- b.visitDirectDeps(visit, false)
-}
-
-func (b *baseModuleContext) VisitDirectDepsIgnoreBlueprint(visit func(Module)) {
- b.visitDirectDeps(visit, true)
-}
-
-func (b *baseModuleContext) visitDirectDeps(visit func(Module), ignoreBlueprint bool) {
b.bp.VisitDirectDeps(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, ignoreBlueprint); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
visit(aModule)
}
})
}
+func (b *baseModuleContext) VisitDirectDepsAllowDisabled(visit func(Module)) {
+ b.bp.VisitDirectDeps(func(module blueprint.Module) {
+ visit(module.(Module))
+ })
+}
+
func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
b.bp.VisitDirectDeps(func(module blueprint.Module) {
if b.bp.OtherModuleDependencyTag(module) == tag {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
visit(aModule)
}
}
@@ -455,7 +409,7 @@
b.bp.VisitDirectDepsIf(
// pred
func(module blueprint.Module) bool {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
return pred(aModule)
} else {
return false
@@ -469,7 +423,7 @@
func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
visit(aModule)
}
})
@@ -479,7 +433,7 @@
b.bp.VisitDepsDepthFirstIf(
// pred
func(module blueprint.Module) bool {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
return pred(aModule)
} else {
return false
@@ -491,10 +445,6 @@
})
}
-func (b *baseModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
- b.bp.WalkDeps(visit)
-}
-
func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
b.walkPath = []Module{b.Module()}
b.tagPath = []blueprint.DependencyTag{}
diff --git a/android/config.go b/android/config.go
index ca20012..9f92fff 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1278,6 +1278,7 @@
}
return false
}
+
func (c *config) EnforceRROExcludedOverlay(path string) bool {
excluded := c.productVariables.EnforceRROExcludedOverlays
if len(excluded) > 0 {
@@ -1286,6 +1287,11 @@
return false
}
+func (c *config) EnforceRROGlobally() bool {
+ enforceList := c.productVariables.EnforceRROTargets
+ return InList("*", enforceList)
+}
+
func (c *config) ExportedNamespaces() []string {
return append([]string(nil), c.productVariables.NamespacesToExport...)
}
diff --git a/android/container.go b/android/container.go
index c048d6c..2a3777b 100644
--- a/android/container.go
+++ b/android/container.go
@@ -479,7 +479,7 @@
func checkContainerViolations(ctx ModuleContext) {
if _, ok := ctx.Module().(InstallableModule); ok {
containersInfo, _ := getContainerModuleInfo(ctx, ctx.Module())
- ctx.VisitDirectDepsIgnoreBlueprint(func(dep Module) {
+ ctx.VisitDirectDeps(func(dep Module) {
if !dep.Enabled(ctx) {
return
}
diff --git a/android/early_module_context.go b/android/early_module_context.go
index 23f4c90..11de771 100644
--- a/android/early_module_context.go
+++ b/android/early_module_context.go
@@ -93,6 +93,10 @@
// Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the
// default SimpleNameInterface if Context.SetNameInterface was not called.
Namespace() *Namespace
+
+ // HasMutatorFinished returns true if the given mutator has finished running.
+ // It will panic if given an invalid mutator name.
+ HasMutatorFinished(mutatorName string) bool
}
// Deprecated: use EarlyModuleContext instead
@@ -175,3 +179,7 @@
func (e *earlyModuleContext) OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) {
e.EarlyModuleContext.OtherModulePropertyErrorf(module, property, fmt, args...)
}
+
+func (e *earlyModuleContext) HasMutatorFinished(mutatorName string) bool {
+ return e.EarlyModuleContext.HasMutatorFinished(mutatorName)
+}
diff --git a/android/hooks.go b/android/hooks.go
index 2ad3b5f..bd2fa5e 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -95,10 +95,17 @@
type createModuleContext interface {
Module() Module
+ HasMutatorFinished(mutatorName string) bool
createModule(blueprint.ModuleFactory, string, ...interface{}) blueprint.Module
}
func createModule(ctx createModuleContext, factory ModuleFactory, ext string, props ...interface{}) Module {
+ if ctx.HasMutatorFinished("defaults") {
+ // Creating modules late is oftentimes problematic, because they don't have earlier
+ // mutators run on them. Prevent making modules after the defaults mutator has run.
+ panic("Cannot create a module after the defaults mutator has finished")
+ }
+
inherited := []interface{}{&ctx.Module().base().commonProperties}
var typeName string
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 0ac975f..f925638 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -63,11 +63,7 @@
var allDepOutputFiles Paths
var allDepMetadataDepSets []*DepSet[Path]
- ctx.VisitDirectDepsBlueprint(func(bpdep blueprint.Module) {
- dep, _ := bpdep.(Module)
- if dep == nil {
- return
- }
+ ctx.VisitDirectDeps(func(dep Module) {
if !dep.Enabled(ctx) {
return
}
diff --git a/android/module.go b/android/module.go
index d6c129a..1866d7a 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1861,10 +1861,8 @@
if m.Enabled(ctx) {
// ensure all direct android.Module deps are enabled
- ctx.VisitDirectDepsBlueprint(func(bm blueprint.Module) {
- if m, ok := bm.(Module); ok {
- ctx.validateAndroidModule(bm, ctx.OtherModuleDependencyTag(m), ctx.baseModuleContext.strictVisitDeps, false)
- }
+ ctx.VisitDirectDeps(func(m Module) {
+ ctx.validateAndroidModule(m, ctx.OtherModuleDependencyTag(m), ctx.baseModuleContext.strictVisitDeps)
})
if m.Device() {
diff --git a/android/paths.go b/android/paths.go
index 0d94f03..1c8258e 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -92,7 +92,7 @@
type ModuleWithDepsPathContext interface {
EarlyModulePathContext
OtherModuleProviderContext
- VisitDirectDepsBlueprint(visit func(blueprint.Module))
+ VisitDirectDeps(visit func(Module))
OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
HasMutatorFinished(mutatorName string) bool
}
@@ -598,7 +598,7 @@
// create the tag here as was supplied to create the tag when the dependency was added so that
// this finds the matching dependency module.
expectedTag := sourceOrOutputDepTag(moduleName, tag)
- ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+ ctx.VisitDirectDeps(func(module Module) {
depTag := ctx.OtherModuleDependencyTag(module)
if depTag == expectedTag {
found = module
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 18bbcab..56de9cd 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -38,6 +38,9 @@
const sboxToolsSubDir = "tools"
const sboxOutDir = sboxSandboxBaseDir + "/" + sboxOutSubDir
+const nsjailToolsSubDir = "tools"
+const nsjailOutDir = "out"
+
// RuleBuilder provides an alternative to ModuleContext.Rule and ModuleContext.Build to add a command line to the build
// graph.
type RuleBuilder struct {
@@ -59,6 +62,9 @@
sboxManifestPath WritablePath
missingDeps []string
args map[string]string
+ nsjail bool
+ nsjailBasePath WritablePath
+ nsjailImplicits Paths
}
// NewRuleBuilder returns a newly created RuleBuilder.
@@ -165,12 +171,43 @@
if len(r.commands) > 0 {
panic("Sbox() may not be called after Command()")
}
+ if r.nsjail {
+ panic("Sbox() may not be called after Nsjail()")
+ }
r.sbox = true
r.outDir = outputDir
r.sboxManifestPath = manifestPath
return r
}
+// Nsjail marks the rule as needing to be wrapped by nsjail. The outputDir should point to the
+// output directory that nsjail will mount to out/. It should not be written to by any other rule.
+// baseDir should point to a location where nsjail will mount to /nsjail_build_sandbox, which will
+// be the working directory of the command.
+func (r *RuleBuilder) Nsjail(outputDir WritablePath, baseDir WritablePath) *RuleBuilder {
+ if len(r.commands) > 0 {
+ panic("Nsjail() may not be called after Command()")
+ }
+ if r.sbox {
+ panic("Nsjail() may not be called after Sbox()")
+ }
+ r.nsjail = true
+ r.outDir = outputDir
+ r.nsjailBasePath = baseDir
+ return r
+}
+
+// NsjailImplicits adds implicit inputs that are not directly mounted. This is useful when
+// the rule mounts directories, as files within those directories can be globbed and
+// tracked as dependencies with NsjailImplicits().
+func (r *RuleBuilder) NsjailImplicits(inputs Paths) *RuleBuilder {
+ if !r.nsjail {
+ panic("NsjailImplicits() must be called after Nsjail()")
+ }
+ r.nsjailImplicits = append(r.nsjailImplicits, inputs...)
+ return r
+}
+
// SandboxTools enables tool sandboxing for the rule by copying any referenced tools into the
// sandbox.
func (r *RuleBuilder) SandboxTools() *RuleBuilder {
@@ -514,7 +551,73 @@
commandString := strings.Join(commands, " && ")
- if r.sbox {
+ if !r.sbox {
+ // If not using sbox the rule will run the command directly, put the hash of the
+ // list of input files in a comment at the end of the command line to ensure ninja
+ // reruns the rule when the list of input files changes.
+ commandString += " # hash of input list: " + hashSrcFiles(inputs)
+ }
+
+ if r.nsjail {
+ var nsjailCmd strings.Builder
+ nsjailPath := r.ctx.Config().PrebuiltBuildTool(r.ctx, "nsjail")
+ nsjailCmd.WriteString("mkdir -p ")
+ nsjailCmd.WriteString(r.nsjailBasePath.String())
+ nsjailCmd.WriteString(" && ")
+ nsjailCmd.WriteString(nsjailPath.String())
+ nsjailCmd.WriteRune(' ')
+ nsjailCmd.WriteString("-B $PWD/")
+ nsjailCmd.WriteString(r.nsjailBasePath.String())
+ nsjailCmd.WriteString(":nsjail_build_sandbox")
+
+ // out is mounted to $(genDir).
+ nsjailCmd.WriteString(" -B $PWD/")
+ nsjailCmd.WriteString(r.outDir.String())
+ nsjailCmd.WriteString(":nsjail_build_sandbox/out")
+
+ for _, input := range inputs {
+ nsjailCmd.WriteString(" -R $PWD/")
+ nsjailCmd.WriteString(input.String())
+ nsjailCmd.WriteString(":nsjail_build_sandbox/")
+ nsjailCmd.WriteString(r.nsjailPathForInputRel(input))
+ }
+ for _, tool := range tools {
+ nsjailCmd.WriteString(" -R $PWD/")
+ nsjailCmd.WriteString(tool.String())
+ nsjailCmd.WriteString(":nsjail_build_sandbox/")
+ nsjailCmd.WriteString(nsjailPathForToolRel(r.ctx, tool))
+ }
+ inputs = append(inputs, tools...)
+ for _, c := range r.commands {
+ for _, tool := range c.packagedTools {
+ nsjailCmd.WriteString(" -R $PWD/")
+ nsjailCmd.WriteString(tool.srcPath.String())
+ nsjailCmd.WriteString(":nsjail_build_sandbox/")
+ nsjailCmd.WriteString(nsjailPathForPackagedToolRel(tool))
+ inputs = append(inputs, tool.srcPath)
+ }
+ }
+
+ // These five directories are necessary to run native host tools like /bin/bash and py3-cmd.
+ nsjailCmd.WriteString(" -R /bin")
+ nsjailCmd.WriteString(" -R /lib")
+ nsjailCmd.WriteString(" -R /lib64")
+ nsjailCmd.WriteString(" -R /dev")
+ nsjailCmd.WriteString(" -R /usr")
+
+ nsjailCmd.WriteString(" -m none:/tmp:tmpfs:size=1073741824") // 1GB, should be enough
+ nsjailCmd.WriteString(" -D nsjail_build_sandbox")
+ nsjailCmd.WriteString(" --disable_rlimits")
+ nsjailCmd.WriteString(" -q")
+ nsjailCmd.WriteString(" -- ")
+ nsjailCmd.WriteString("/bin/bash -c ")
+ nsjailCmd.WriteString(proptools.ShellEscape(commandString))
+
+ commandString = nsjailCmd.String()
+
+ inputs = append(inputs, nsjailPath)
+ inputs = append(inputs, r.nsjailImplicits...)
+ } else if r.sbox {
// If running the command inside sbox, write the rule data out to an sbox
// manifest.textproto.
manifest := sbox_proto.Manifest{}
@@ -734,11 +837,6 @@
rewrapperCommand := r.rbeParams.NoVarTemplate(r.ctx.Config().RBEWrapper())
commandString = rewrapperCommand + " bash -c '" + strings.ReplaceAll(commandString, `'`, `'\''`) + "'"
}
- } else {
- // If not using sbox the rule will run the command directly, put the hash of the
- // list of input files in a comment at the end of the command line to ensure ninja
- // reruns the rule when the list of input files changes.
- commandString += " # hash of input list: " + hashSrcFiles(inputs)
}
// Ninja doesn't like multiple outputs when depfiles are enabled, move all but the first output to
@@ -869,6 +967,8 @@
rel = filepath.Join(sboxSandboxBaseDir, rel)
}
return rel
+ } else if c.rule.nsjail {
+ return c.rule.nsjailPathForInputRel(path)
}
return path.String()
}
@@ -894,6 +994,10 @@
// Errors will be handled in RuleBuilder.Build where we have a context to report them
rel, _, _ := maybeRelErr(c.rule.outDir.String(), path.String())
return filepath.Join(sboxOutDir, rel)
+ } else if c.rule.nsjail {
+ // Errors will be handled in RuleBuilder.Build where we have a context to report them
+ rel, _, _ := maybeRelErr(c.rule.outDir.String(), path.String())
+ return filepath.Join(nsjailOutDir, rel)
}
return path.String()
}
@@ -945,15 +1049,49 @@
return filepath.Join(sboxToolsSubDir, "out", spec.relPathInPackage)
}
+func nsjailPathForToolRel(ctx BuilderContext, path Path) string {
+ // Errors will be handled in RuleBuilder.Build where we have a context to report them
+ toolDir := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "")
+ relOutSoong, isRelOutSoong, _ := maybeRelErr(toolDir.String(), path.String())
+ if isRelOutSoong {
+ // The tool is in the Soong output directory, it will be copied to __SBOX_OUT_DIR__/tools/out
+ return filepath.Join(nsjailToolsSubDir, "out", relOutSoong)
+ }
+ // The tool is in the source directory, it will be copied to __SBOX_OUT_DIR__/tools/src
+ return filepath.Join(nsjailToolsSubDir, "src", path.String())
+}
+
+func (r *RuleBuilder) nsjailPathForInputRel(path Path) string {
+ rel, isRelSboxOut, _ := maybeRelErr(r.outDir.String(), path.String())
+ if isRelSboxOut {
+ return filepath.Join(nsjailOutDir, rel)
+ }
+ return path.String()
+}
+
+func (r *RuleBuilder) nsjailPathsForInputsRel(paths Paths) []string {
+ ret := make([]string, len(paths))
+ for i, path := range paths {
+ ret[i] = r.nsjailPathForInputRel(path)
+ }
+ return ret
+}
+
+func nsjailPathForPackagedToolRel(spec PackagingSpec) string {
+ return filepath.Join(nsjailToolsSubDir, "out", spec.relPathInPackage)
+}
+
// PathForPackagedTool takes a PackageSpec for a tool and returns the corresponding path for the
// tool after copying it into the sandbox. This can be used on the RuleBuilder command line to
// reference the tool.
func (c *RuleBuilderCommand) PathForPackagedTool(spec PackagingSpec) string {
- if !c.rule.sboxTools {
- panic("PathForPackagedTool() requires SandboxTools()")
+ if c.rule.sboxTools {
+ return filepath.Join(sboxSandboxBaseDir, sboxPathForPackagedToolRel(spec))
+ } else if c.rule.nsjail {
+ return nsjailPathForPackagedToolRel(spec)
+ } else {
+ panic("PathForPackagedTool() requires SandboxTools() or Nsjail()")
}
-
- return filepath.Join(sboxSandboxBaseDir, sboxPathForPackagedToolRel(spec))
}
// PathForTool takes a path to a tool, which may be an output file or a source file, and returns
@@ -962,6 +1100,8 @@
func (c *RuleBuilderCommand) PathForTool(path Path) string {
if c.rule.sbox && c.rule.sboxTools {
return filepath.Join(sboxSandboxBaseDir, sboxPathForToolRel(c.rule.ctx, path))
+ } else if c.rule.nsjail {
+ return nsjailPathForToolRel(c.rule.ctx, path)
}
return path.String()
}
@@ -976,6 +1116,12 @@
ret = append(ret, filepath.Join(sboxSandboxBaseDir, sboxPathForToolRel(c.rule.ctx, path)))
}
return ret
+ } else if c.rule.nsjail {
+ var ret []string
+ for _, path := range paths {
+ ret = append(ret, nsjailPathForToolRel(c.rule.ctx, path))
+ }
+ return ret
}
return paths.Strings()
}
@@ -983,20 +1129,22 @@
// PackagedTool adds the specified tool path to the command line. It can only be used with tool
// sandboxing enabled by SandboxTools(), and will copy the tool into the sandbox.
func (c *RuleBuilderCommand) PackagedTool(spec PackagingSpec) *RuleBuilderCommand {
- if !c.rule.sboxTools {
- panic("PackagedTool() requires SandboxTools()")
- }
-
c.packagedTools = append(c.packagedTools, spec)
- c.Text(sboxPathForPackagedToolRel(spec))
+ if c.rule.sboxTools {
+ c.Text(sboxPathForPackagedToolRel(spec))
+ } else if c.rule.nsjail {
+ c.Text(nsjailPathForPackagedToolRel(spec))
+ } else {
+ panic("PackagedTool() requires SandboxTools() or Nsjail()")
+ }
return c
}
// ImplicitPackagedTool copies the specified tool into the sandbox without modifying the command
// line. It can only be used with tool sandboxing enabled by SandboxTools().
func (c *RuleBuilderCommand) ImplicitPackagedTool(spec PackagingSpec) *RuleBuilderCommand {
- if !c.rule.sboxTools {
- panic("ImplicitPackagedTool() requires SandboxTools()")
+ if !c.rule.sboxTools && !c.rule.nsjail {
+ panic("ImplicitPackagedTool() requires SandboxTools() or Nsjail()")
}
c.packagedTools = append(c.packagedTools, spec)
@@ -1006,8 +1154,8 @@
// ImplicitPackagedTools copies the specified tools into the sandbox without modifying the command
// line. It can only be used with tool sandboxing enabled by SandboxTools().
func (c *RuleBuilderCommand) ImplicitPackagedTools(specs []PackagingSpec) *RuleBuilderCommand {
- if !c.rule.sboxTools {
- panic("ImplicitPackagedTools() requires SandboxTools()")
+ if !c.rule.sboxTools && !c.rule.nsjail {
+ panic("ImplicitPackagedTools() requires SandboxTools() or Nsjail()")
}
c.packagedTools = append(c.packagedTools, specs...)
diff --git a/apex/apex.go b/apex/apex.go
index aff69c1..5f4d823 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -68,8 +68,6 @@
ctx.Transition("apex", &apexTransitionMutator{})
ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel()
ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel()
- // Register after apex_info mutator so that it can use ApexVariationName
- ctx.TopDown("apex_strict_updatability_lint", apexStrictUpdatibilityLintMutator).Parallel()
}
type apexBundleProperties struct {
@@ -1115,26 +1113,6 @@
enforceAppUpdatability(mctx)
}
-// apexStrictUpdatibilityLintMutator propagates strict_updatability_linting to transitive deps of a mainline module
-// This check is enforced for updatable modules
-func apexStrictUpdatibilityLintMutator(mctx android.TopDownMutatorContext) {
- if !mctx.Module().Enabled(mctx) {
- return
- }
- if apex, ok := mctx.Module().(*apexBundle); ok && apex.checkStrictUpdatabilityLinting(mctx) {
- apex.WalkPayloadDeps(mctx, func(mctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
- if externalDep {
- return false
- }
- if lintable, ok := to.(java.LintDepSetsIntf); ok {
- lintable.SetStrictUpdatabilityLinting(true)
- }
- // visit transitive deps
- return true
- })
- }
-}
-
// enforceAppUpdatability propagates updatable=true to apps of updatable apexes
func enforceAppUpdatability(mctx android.TopDownMutatorContext) {
if !mctx.Module().Enabled(mctx) {
@@ -1197,7 +1175,7 @@
}
)
-func (a *apexBundle) checkStrictUpdatabilityLinting(mctx android.TopDownMutatorContext) bool {
+func (a *apexBundle) checkStrictUpdatabilityLinting(mctx android.ModuleContext) bool {
// The allowlist contains the base apex name, so use that instead of the ApexVariationName
return a.Updatable() && !android.InList(mctx.ModuleName(), skipStrictUpdatabilityLintAllowlist)
}
@@ -1957,12 +1935,12 @@
})
}
-func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, child, parent blueprint.Module) bool {
+func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, child, parent android.Module) bool {
depTag := ctx.OtherModuleDependencyTag(child)
if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
return false
}
- if mod, ok := child.(android.Module); ok && !mod.Enabled(ctx) {
+ if !child.Enabled(ctx) {
return false
}
depName := ctx.OtherModuleName(child)
@@ -2306,7 +2284,7 @@
checkDuplicate: a.shouldCheckDuplicate(ctx),
unwantedTransitiveDeps: a.properties.Unwanted_transitive_deps,
}
- ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) })
+ ctx.WalkDeps(func(child, parent android.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) })
vctx.normalizeFileInfo(ctx)
if a.privateKeyFile == nil {
if ctx.Config().AllowMissingDependencies() {
@@ -2707,7 +2685,7 @@
func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) {
// Visit direct deps only. As long as we guarantee top-level deps are using stable SDKs,
// java's checkLinkType guarantees correct usage for transitive deps
- ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+ ctx.VisitDirectDeps(func(module android.Module) {
tag := ctx.OtherModuleDependencyTag(module)
switch tag {
case javaLibTag, androidAppTag:
@@ -2800,7 +2778,7 @@
// checkStaticExecutable ensures that executables in an APEX are not static.
func (a *apexBundle) checkStaticExecutables(ctx android.ModuleContext) {
- ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+ ctx.VisitDirectDeps(func(module android.Module) {
if ctx.OtherModuleDependencyTag(module) != executableTag {
return
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ed49266..7465f40 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -9693,59 +9693,84 @@
}
testCases := []struct {
- testCaseName string
- apexUpdatable bool
- javaStrictUpdtabilityLint bool
- lintFileExists bool
- disallowedFlagExpected bool
+ testCaseName string
+ apexUpdatable bool
+ javaStrictUpdtabilityLint bool
+ lintFileExists bool
+ disallowedFlagExpectedOnApex bool
+ disallowedFlagExpectedOnJavalib bool
}{
{
- testCaseName: "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd",
- apexUpdatable: true,
- javaStrictUpdtabilityLint: true,
- lintFileExists: false,
- disallowedFlagExpected: false,
+ testCaseName: "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd",
+ apexUpdatable: true,
+ javaStrictUpdtabilityLint: true,
+ lintFileExists: false,
+ disallowedFlagExpectedOnApex: false,
+ disallowedFlagExpectedOnJavalib: false,
},
{
- testCaseName: "non-updatable apex respects strict_updatability of javalib",
- apexUpdatable: false,
- javaStrictUpdtabilityLint: false,
- lintFileExists: true,
- disallowedFlagExpected: false,
+ testCaseName: "non-updatable apex respects strict_updatability of javalib",
+ apexUpdatable: false,
+ javaStrictUpdtabilityLint: false,
+ lintFileExists: true,
+ disallowedFlagExpectedOnApex: false,
+ disallowedFlagExpectedOnJavalib: false,
},
{
- testCaseName: "non-updatable apex respects strict updatability of javalib",
- apexUpdatable: false,
- javaStrictUpdtabilityLint: true,
- lintFileExists: true,
- disallowedFlagExpected: true,
+ testCaseName: "non-updatable apex respects strict updatability of javalib",
+ apexUpdatable: false,
+ javaStrictUpdtabilityLint: true,
+ lintFileExists: true,
+ disallowedFlagExpectedOnApex: false,
+ disallowedFlagExpectedOnJavalib: true,
},
{
- testCaseName: "updatable apex sets strict updatability of javalib to true",
- apexUpdatable: true,
- javaStrictUpdtabilityLint: false, // will be set to true by mutator
- lintFileExists: true,
- disallowedFlagExpected: true,
+ testCaseName: "updatable apex checks strict updatability of javalib",
+ apexUpdatable: true,
+ javaStrictUpdtabilityLint: false,
+ lintFileExists: true,
+ disallowedFlagExpectedOnApex: true,
+ disallowedFlagExpectedOnJavalib: false,
},
}
for _, testCase := range testCases {
- fixtures := []android.FixturePreparer{}
- baselineProperty := ""
- if testCase.lintFileExists {
- fixtures = append(fixtures, fs.AddToFixture())
- baselineProperty = "baseline_filename: \"lint-baseline.xml\""
- }
- bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty)
+ t.Run(testCase.testCaseName, func(t *testing.T) {
+ fixtures := []android.FixturePreparer{}
+ baselineProperty := ""
+ if testCase.lintFileExists {
+ fixtures = append(fixtures, fs.AddToFixture())
+ baselineProperty = "baseline_filename: \"lint-baseline.xml\""
+ }
+ bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty)
- result := testApex(t, bp, fixtures...)
- myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto"))
- disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi")
+ result := testApex(t, bp, fixtures...)
- if disallowedFlagActual != testCase.disallowedFlagExpected {
- t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command)
- }
+ checkModule := func(m android.TestingBuildParams, name string, expectStrictUpdatability bool) {
+ if expectStrictUpdatability {
+ if m.Rule == nil {
+ t.Errorf("expected strict updatability check rule on %s", name)
+ } else {
+ android.AssertStringDoesContain(t, fmt.Sprintf("strict updatability check rule for %s", name),
+ m.RuleParams.Command, "--disallowed_issues NewApi")
+ android.AssertStringListContains(t, fmt.Sprintf("strict updatability check baselines for %s", name),
+ m.Inputs.Strings(), "lint-baseline.xml")
+ }
+ } else {
+ if m.Rule != nil {
+ t.Errorf("expected no strict updatability check rule on %s", name)
+ }
+ }
+ }
+
+ myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
+ apex := result.ModuleForTests("myapex", "android_common_myapex")
+ apexStrictUpdatabilityCheck := apex.MaybeOutput("lint_strict_updatability_check.stamp")
+ javalibStrictUpdatabilityCheck := myjavalib.MaybeOutput("lint_strict_updatability_check.stamp")
+
+ checkModule(apexStrictUpdatabilityCheck, "myapex", testCase.disallowedFlagExpectedOnApex)
+ checkModule(javalibStrictUpdatabilityCheck, "myjavalib", testCase.disallowedFlagExpectedOnJavalib)
+ })
}
}
@@ -9787,11 +9812,12 @@
}
result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture())
- myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto"))
- if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") {
- t.Errorf("Strict updabality lint missing in myjavalib coming from bootclasspath_fragment mybootclasspath-fragment\nActual lint cmd: %v", *sboxProto.Commands[0].Command)
- }
+ apex := result.ModuleForTests("myapex", "android_common_myapex")
+ apexStrictUpdatabilityCheck := apex.Output("lint_strict_updatability_check.stamp")
+ android.AssertStringDoesContain(t, "strict updatability check rule for myapex",
+ apexStrictUpdatabilityCheck.RuleParams.Command, "--disallowed_issues NewApi")
+ android.AssertStringListContains(t, "strict updatability check baselines for myapex",
+ apexStrictUpdatabilityCheck.Inputs.Strings(), "lint-baseline.xml")
}
func TestApexLintBcpFragmentSdkLibDeps(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index 244119b..bf3ba9f 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -1164,7 +1164,18 @@
}
}
- a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build())
+ depSets := depSetsBuilder.Build()
+ var validations android.Paths
+
+ if a.checkStrictUpdatabilityLinting(ctx) {
+ baselines := depSets.Baseline.ToList()
+ if len(baselines) > 0 {
+ outputFile := java.VerifyStrictUpdatabilityChecks(ctx, baselines)
+ validations = append(validations, outputFile)
+ }
+ }
+
+ a.lintReports = java.BuildModuleLintReportZips(ctx, depSets, validations)
}
func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath {
diff --git a/bazel/configurability.go b/bazel/configurability.go
index 2c9a536..3a65614 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -100,9 +100,7 @@
// Copy of archFeatures from android/arch_list.go because the bazel
// package can't access the android package
archFeatures := map[string][]string{
- "arm": {
- "neon",
- },
+ "arm": {},
"arm64": {
"dotprod",
},
diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go
index 5c047bc..8af2ffa 100644
--- a/filesystem/aconfig_files.go
+++ b/filesystem/aconfig_files.go
@@ -79,6 +79,7 @@
generatePartitionAconfigStorageFile("package_map", "package.map")
generatePartitionAconfigStorageFile("flag_map", "flag.map")
generatePartitionAconfigStorageFile("flag_val", "flag.val")
+ generatePartitionAconfigStorageFile("flag_info", "flag.info")
android.WriteExecutableFileRuleVerbatim(ctx, aconfigFlagsBuilderPath, sb.String())
}
diff --git a/genrule/Android.bp b/genrule/Android.bp
index f4197e6..49df480 100644
--- a/genrule/Android.bp
+++ b/genrule/Android.bp
@@ -25,3 +25,53 @@
// Used by plugins
visibility: ["//visibility:public"],
}
+
+genrule {
+ name: "nsjail_genrule_test_input",
+ cmd: "echo nsjail_genrule_test_input > $(out)",
+ out: ["nsjail_genrule_test_input.txt"],
+}
+
+// Pseudo-test that's run on checkbuilds to verify consistent directory
+// structure for genrules using sbox or nsjail.
+genrule_defaults {
+ name: "nsjail_genrule_test_gen_defaults",
+ // verify both relative paths and its contents
+ cmd: "(echo $(out) $(genDir) && sha256sum " +
+ "$(location get_clang_version) " +
+ "$(location py3-cmd) " +
+ "$(location genrule.go) " +
+ "$(location :nsjail_genrule_test_input) " +
+ "$(locations *.go)) | sed 's@\\./@@g' > $(out)",
+ tools: [
+ "get_clang_version", // random tool
+ "py3-cmd", // random prebuilt tool
+ ],
+ tool_files: ["genrule.go"], // random local file
+ srcs: [
+ ":nsjail_genrule_test_input", // random OutputFileProducer
+ "*.go", // random glob
+ ],
+ out: ["nsjail_genrule_test.txt"],
+}
+
+genrule {
+ name: "nsjail_genrule_test_gen_without_nsjail",
+ defaults: ["nsjail_genrule_test_gen_defaults"],
+}
+
+genrule {
+ name: "nsjail_genrule_test_gen_with_nsjail",
+ defaults: ["nsjail_genrule_test_gen_defaults"],
+ use_nsjail: true,
+}
+
+genrule {
+ name: "nsjail_genrule_test",
+ srcs: [
+ ":nsjail_genrule_test_gen_without_nsjail",
+ ":nsjail_genrule_test_gen_with_nsjail",
+ ],
+ cmd: "diff $(in) > $(out)",
+ out: ["nsjail_genrule_test"],
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index a48038b..e5222a4 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -21,6 +21,7 @@
import (
"fmt"
"io"
+ "path/filepath"
"strconv"
"strings"
@@ -210,6 +211,9 @@
// For gensrsc sharding.
shard int
shards int
+
+ // For nsjail tasks
+ useNsjail bool
}
func (g *Module) GeneratedSourceFiles() android.Paths {
@@ -313,16 +317,14 @@
if len(g.properties.Tools) > 0 {
seenTools := make(map[string]bool)
- ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+ ctx.VisitDirectDepsAllowDisabled(func(module android.Module) {
switch tag := ctx.OtherModuleDependencyTag(module).(type) {
case hostToolDependencyTag:
tool := ctx.OtherModuleName(module)
- if m, ok := module.(android.Module); ok {
- // Necessary to retrieve any prebuilt replacement for the tool, since
- // toolDepsMutator runs too late for the prebuilt mutators to have
- // replaced the dependency.
- module = android.PrebuiltGetPreferred(ctx, m)
- }
+ // Necessary to retrieve any prebuilt replacement for the tool, since
+ // toolDepsMutator runs too late for the prebuilt mutators to have
+ // replaced the dependency.
+ module = android.PrebuiltGetPreferred(ctx, module)
switch t := module.(type) {
case android.HostToolProvider:
@@ -454,21 +456,26 @@
// Pick a unique path outside the task.genDir for the sbox manifest textproto,
// a unique rule name, and the user-visible description.
- manifestName := "genrule.sbox.textproto"
+ var rule *android.RuleBuilder
desc := "generate"
name := "generator"
- if task.shards > 0 {
- manifestName = "genrule_" + strconv.Itoa(task.shard) + ".sbox.textproto"
- desc += " " + strconv.Itoa(task.shard)
- name += strconv.Itoa(task.shard)
- } else if len(task.out) == 1 {
- desc += " " + task.out[0].Base()
+ if task.useNsjail {
+ rule = android.NewRuleBuilder(pctx, ctx).Nsjail(task.genDir, android.PathForModuleOut(ctx, "nsjail_build_sandbox"))
+ } else {
+ manifestName := "genrule.sbox.textproto"
+ if task.shards > 0 {
+ manifestName = "genrule_" + strconv.Itoa(task.shard) + ".sbox.textproto"
+ desc += " " + strconv.Itoa(task.shard)
+ name += strconv.Itoa(task.shard)
+ } else if len(task.out) == 1 {
+ desc += " " + task.out[0].Base()
+ }
+
+ manifestPath := android.PathForModuleOut(ctx, manifestName)
+
+ // Use a RuleBuilder to create a rule that runs the command inside an sbox sandbox.
+ rule = getSandboxedRuleBuilder(ctx, android.NewRuleBuilder(pctx, ctx).Sbox(task.genDir, manifestPath))
}
-
- manifestPath := android.PathForModuleOut(ctx, manifestName)
-
- // Use a RuleBuilder to create a rule that runs the command inside an sbox sandbox.
- rule := getSandboxedRuleBuilder(ctx, android.NewRuleBuilder(pctx, ctx).Sbox(task.genDir, manifestPath))
if Bool(g.properties.Write_if_changed) {
rule.Restat()
}
@@ -569,6 +576,15 @@
cmd.OrderOnly(ctx.Config().BuildNumberFile(ctx))
}
+ if task.useNsjail {
+ for _, input := range task.in {
+ // can fail if input is a file.
+ if paths, err := ctx.GlobWithDeps(filepath.Join(input.String(), "**/*"), nil); err == nil {
+ rule.NsjailImplicits(android.PathsForSource(ctx, paths))
+ }
+ }
+ }
+
// Create the rule to run the genrule command inside sbox.
rule.Build(name, desc)
@@ -832,15 +848,18 @@
properties := &genRuleProperties{}
taskGenerator := func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask {
+ useNsjail := Bool(properties.Use_nsjail)
+
outs := make(android.WritablePaths, len(properties.Out))
for i, out := range properties.Out {
outs[i] = android.PathForModuleGen(ctx, out)
}
return []generateTask{{
- in: srcFiles,
- out: outs,
- genDir: android.PathForModuleGen(ctx),
- cmd: rawCommand,
+ in: srcFiles,
+ out: outs,
+ genDir: android.PathForModuleGen(ctx),
+ cmd: rawCommand,
+ useNsjail: useNsjail,
}}
}
@@ -855,6 +874,8 @@
}
type genRuleProperties struct {
+ Use_nsjail *bool
+
// names of the output files that will be generated
Out []string `android:"arch_variant"`
}
diff --git a/java/aar.go b/java/aar.go
index b5e24c4..7d73b03 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -45,7 +45,7 @@
ctx.RegisterModuleType("android_library_import", AARImportFactory)
ctx.RegisterModuleType("android_library", AndroidLibraryFactory)
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator)
+ ctx.Transition("propagate_rro_enforcement", &propagateRROEnforcementTransitionMutator{})
})
}
@@ -151,15 +151,67 @@
path android.Path
}
-// Propagate RRO enforcement flag to static lib dependencies transitively.
-func propagateRROEnforcementMutator(ctx android.TopDownMutatorContext) {
+// Propagate RRO enforcement flag to static lib dependencies transitively. If EnforceRROGlobally is set then
+// all modules will use the "" variant. If specific modules have RRO enforced, then modules (usually apps) with
+// RRO enabled will use the "" variation for themselves, but use the "rro" variant of direct and transitive static
+// android_library dependencies.
+type propagateRROEnforcementTransitionMutator struct{}
+
+func (p propagateRROEnforcementTransitionMutator) Split(ctx android.BaseModuleContext) []string {
+ // Never split modules, apps with or without RRO enabled use the "" variant, static android_library dependencies
+ // will use create the "rro" variant from incoming tranisitons.
+ return []string{""}
+}
+
+func (p propagateRROEnforcementTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ // Non-static dependencies are not involved in RRO and always use the empty variant.
+ if ctx.DepTag() != staticLibTag {
+ return ""
+ }
+
m := ctx.Module()
- if d, ok := m.(AndroidLibraryDependency); ok && d.IsRROEnforced(ctx) {
- ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) {
- if a, ok := d.(AndroidLibraryDependency); ok {
- a.SetRROEnforcedForDependent(true)
- }
- })
+ if _, ok := m.(AndroidLibraryDependency); ok {
+ // If RRO is enforced globally don't bother using "rro" variants, the empty variant will have RRO enabled.
+ if ctx.Config().EnforceRROGlobally() {
+ return ""
+ }
+
+ // If RRO is enabled for this module use the "rro" variants of static dependencies. IncomingTransition will
+ // rewrite this back to "" if the dependency is not an android_library.
+ if ctx.Config().EnforceRROForModule(ctx.Module().Name()) {
+ return "rro"
+ }
+ }
+
+ return sourceVariation
+}
+
+func (p propagateRROEnforcementTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ // Propagate the "rro" variant to android_library modules, but use the empty variant for everything else.
+ if incomingVariation == "rro" {
+ m := ctx.Module()
+ if _, ok := m.(AndroidLibraryDependency); ok {
+ return "rro"
+ }
+ return ""
+ }
+
+ return ""
+}
+
+func (p propagateRROEnforcementTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ m := ctx.Module()
+ if d, ok := m.(AndroidLibraryDependency); ok {
+ if variation == "rro" {
+ // This is the "rro" variant of a module that has both variants, mark this one as RRO enabled and
+ // hide it from make to avoid collisions with the non-RRO empty variant.
+ d.SetRROEnforcedForDependent(true)
+ m.HideFromMake()
+ } else if ctx.Config().EnforceRROGlobally() {
+ // RRO is enabled globally, mark it enabled for this module, but there is only one variant so no
+ // need to hide it from make.
+ d.SetRROEnforcedForDependent(true)
+ }
}
}
diff --git a/java/app_test.go b/java/app_test.go
index d7f5f0c..2a2611d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1419,26 +1419,31 @@
}
func TestAndroidResourceOverlays(t *testing.T) {
+ type moduleAndVariant struct {
+ module string
+ variant string
+ }
+
testCases := []struct {
name string
enforceRROTargets []string
enforceRROExcludedOverlays []string
- resourceFiles map[string][]string
- overlayFiles map[string][]string
- rroDirs map[string][]string
+ resourceFiles map[moduleAndVariant][]string
+ overlayFiles map[moduleAndVariant][]string
+ rroDirs map[moduleAndVariant][]string
}{
{
name: "no RRO",
enforceRROTargets: nil,
enforceRROExcludedOverlays: nil,
- resourceFiles: map[string][]string{
- "foo": nil,
- "bar": {"bar/res/res/values/strings.xml"},
- "lib": nil,
- "lib2": {"lib2/res/res/values/strings.xml"},
+ resourceFiles: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: nil,
+ {"bar", "android_common"}: {"bar/res/res/values/strings.xml"},
+ {"lib", "android_common"}: nil,
+ {"lib2", "android_common"}: {"lib2/res/res/values/strings.xml"},
},
- overlayFiles: map[string][]string{
- "foo": {
+ overlayFiles: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: {
"out/soong/.intermediates/lib2/android_common/package-res.apk",
"out/soong/.intermediates/lib/android_common/package-res.apk",
"out/soong/.intermediates/lib3/android_common/package-res.apk",
@@ -1447,57 +1452,65 @@
"device/vendor/blah/overlay/foo/res/values/strings.xml",
"product/vendor/blah/overlay/foo/res/values/strings.xml",
},
- "bar": {
+ {"bar", "android_common"}: {
"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
"device/vendor/blah/overlay/bar/res/values/strings.xml",
},
- "lib": {
+ {"lib", "android_common"}: {
"out/soong/.intermediates/lib2/android_common/package-res.apk",
"lib/res/res/values/strings.xml",
"device/vendor/blah/overlay/lib/res/values/strings.xml",
},
},
- rroDirs: map[string][]string{
- "foo": nil,
- "bar": nil,
+ rroDirs: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: nil,
+ {"bar", "android_common"}: nil,
},
},
{
name: "enforce RRO on foo",
enforceRROTargets: []string{"foo"},
enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
- resourceFiles: map[string][]string{
- "foo": nil,
- "bar": {"bar/res/res/values/strings.xml"},
- "lib": nil,
- "lib2": {"lib2/res/res/values/strings.xml"},
+ resourceFiles: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: nil,
+ {"bar", "android_common"}: {"bar/res/res/values/strings.xml"},
+ {"lib", "android_common"}: nil,
+ {"lib", "android_common_rro"}: nil,
+ {"lib2", "android_common"}: {"lib2/res/res/values/strings.xml"},
+ {"lib2", "android_common_rro"}: {"lib2/res/res/values/strings.xml"},
},
- overlayFiles: map[string][]string{
- "foo": {
- "out/soong/.intermediates/lib2/android_common/package-res.apk",
- "out/soong/.intermediates/lib/android_common/package-res.apk",
- "out/soong/.intermediates/lib3/android_common/package-res.apk",
+ overlayFiles: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: {
+ "out/soong/.intermediates/lib2/android_common_rro/package-res.apk",
+ "out/soong/.intermediates/lib/android_common_rro/package-res.apk",
+ "out/soong/.intermediates/lib3/android_common_rro/package-res.apk",
"foo/res/res/values/strings.xml",
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
},
- "bar": {
+ {"bar", "android_common"}: {
"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
"device/vendor/blah/overlay/bar/res/values/strings.xml",
},
- "lib": {
+ {"lib", "android_common"}: {
"out/soong/.intermediates/lib2/android_common/package-res.apk",
"lib/res/res/values/strings.xml",
+ "device/vendor/blah/overlay/lib/res/values/strings.xml",
+ },
+ {"lib", "android_common_rro"}: {
+ "out/soong/.intermediates/lib2/android_common_rro/package-res.apk",
+ "lib/res/res/values/strings.xml",
},
},
- rroDirs: map[string][]string{
- "foo": {
+ rroDirs: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: {
"device:device/vendor/blah/overlay/foo/res",
"product:product/vendor/blah/overlay/foo/res",
"device:device/vendor/blah/overlay/lib/res",
},
- "bar": nil,
- "lib": {"device:device/vendor/blah/overlay/lib/res"},
+ {"bar", "android_common"}: nil,
+ {"lib", "android_common"}: nil,
+ {"lib", "android_common_rro"}: {"device:device/vendor/blah/overlay/lib/res"},
},
},
{
@@ -1508,35 +1521,35 @@
"device/vendor/blah/static_overlay/foo",
"device/vendor/blah/static_overlay/bar/res",
},
- resourceFiles: map[string][]string{
- "foo": nil,
- "bar": {"bar/res/res/values/strings.xml"},
- "lib": nil,
- "lib2": {"lib2/res/res/values/strings.xml"},
+ resourceFiles: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: nil,
+ {"bar", "android_common"}: {"bar/res/res/values/strings.xml"},
+ {"lib", "android_common"}: nil,
+ {"lib2", "android_common"}: {"lib2/res/res/values/strings.xml"},
},
- overlayFiles: map[string][]string{
- "foo": {
+ overlayFiles: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: {
"out/soong/.intermediates/lib2/android_common/package-res.apk",
"out/soong/.intermediates/lib/android_common/package-res.apk",
"out/soong/.intermediates/lib3/android_common/package-res.apk",
"foo/res/res/values/strings.xml",
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
},
- "bar": {"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
- "lib": {
+ {"bar", "android_common"}: {"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
+ {"lib", "android_common"}: {
"out/soong/.intermediates/lib2/android_common/package-res.apk",
"lib/res/res/values/strings.xml",
},
},
- rroDirs: map[string][]string{
- "foo": {
+ rroDirs: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: {
"device:device/vendor/blah/overlay/foo/res",
"product:product/vendor/blah/overlay/foo/res",
// Lib dep comes after the direct deps
"device:device/vendor/blah/overlay/lib/res",
},
- "bar": {"device:device/vendor/blah/overlay/bar/res"},
- "lib": {"device:device/vendor/blah/overlay/lib/res"},
+ {"bar", "android_common"}: {"device:device/vendor/blah/overlay/bar/res"},
+ {"lib", "android_common"}: {"device:device/vendor/blah/overlay/lib/res"},
},
},
}
@@ -1621,19 +1634,19 @@
for _, o := range list {
res := module.MaybeOutput(o)
if res.Rule != nil {
- // If the overlay is compiled as part of this module (i.e. a .arsc.flat file),
+ // If the overlay is compiled as part of this moduleAndVariant (i.e. a .arsc.flat file),
// verify the inputs to the .arsc.flat rule.
files = append(files, res.Inputs.Strings()...)
} else {
- // Otherwise, verify the full path to the output of the other module
+ // Otherwise, verify the full path to the output of the other moduleAndVariant
files = append(files, o)
}
}
return files
}
- getResources := func(moduleName string) (resourceFiles, overlayFiles, rroDirs []string) {
- module := result.ModuleForTests(moduleName, "android_common")
+ getResources := func(moduleName, variantName string) (resourceFiles, overlayFiles, rroDirs []string) {
+ module := result.ModuleForTests(moduleName, variantName)
resourceList := module.MaybeOutput("aapt2/res.list")
if resourceList.Rule != nil {
resourceFiles = resourceListToFiles(module, android.PathsRelativeToTop(resourceList.Inputs))
@@ -1658,21 +1671,33 @@
return resourceFiles, overlayFiles, rroDirs
}
- modules := []string{"foo", "bar", "lib", "lib2"}
- for _, module := range modules {
- resourceFiles, overlayFiles, rroDirs := getResources(module)
+ modules := []moduleAndVariant{
+ {"foo", "android_common"},
+ {"foo", "android_common_rro"},
+ {"bar", "android_common"},
+ {"bar", "android_common_rro"},
+ {"lib", "android_common"},
+ {"lib", "android_common_rro"},
+ {"lib2", "android_common"},
+ {"lib2", "android_common_rro"},
+ }
+ for _, moduleAndVariant := range modules {
+ if _, exists := testCase.resourceFiles[moduleAndVariant]; !exists {
+ continue
+ }
+ resourceFiles, overlayFiles, rroDirs := getResources(moduleAndVariant.module, moduleAndVariant.variant)
- if !reflect.DeepEqual(resourceFiles, testCase.resourceFiles[module]) {
+ if !reflect.DeepEqual(resourceFiles, testCase.resourceFiles[moduleAndVariant]) {
t.Errorf("expected %s resource files:\n %#v\n got:\n %#v",
- module, testCase.resourceFiles[module], resourceFiles)
+ moduleAndVariant, testCase.resourceFiles[moduleAndVariant], resourceFiles)
}
- if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[module]) {
+ if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[moduleAndVariant]) {
t.Errorf("expected %s overlay files:\n %#v\n got:\n %#v",
- module, testCase.overlayFiles[module], overlayFiles)
+ moduleAndVariant, testCase.overlayFiles[moduleAndVariant], overlayFiles)
}
- if !reflect.DeepEqual(rroDirs, testCase.rroDirs[module]) {
+ if !reflect.DeepEqual(rroDirs, testCase.rroDirs[moduleAndVariant]) {
t.Errorf("expected %s rroDirs: %#v\n got:\n %#v",
- module, testCase.rroDirs[module], rroDirs)
+ moduleAndVariant, testCase.rroDirs[moduleAndVariant], rroDirs)
}
}
})
diff --git a/java/base.go b/java/base.go
index ed9c3f4..7c26cc3 100644
--- a/java/base.go
+++ b/java/base.go
@@ -2699,7 +2699,7 @@
module := ctx.Module()
moduleName := module.Name()
- ctx.VisitDirectDepsIgnoreBlueprint(func(m android.Module) {
+ ctx.VisitDirectDeps(func(m android.Module) {
tag := ctx.OtherModuleDependencyTag(m)
// This logic mirrors that in (*Module).collectDeps above. There are several places
// where we explicitly return RenameUseExclude, even though it is the default, to
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index ad0e0a7..7a77b15 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -1375,18 +1375,7 @@
}
image := d.defaultBootImage
- if image != nil {
- if profileInstallInfo, ok := android.OtherModuleProvider(ctx, d, profileInstallInfoProvider); ok {
- ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", profileInstallInfo.profileInstalls.String())
- if profileInstallInfo.profileLicenseMetadataFile.Valid() {
- ctx.Strict("DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA", profileInstallInfo.profileLicenseMetadataFile.String())
- }
- }
-
- if SkipDexpreoptBootJars(ctx) {
- return
- }
-
+ if image != nil && !SkipDexpreoptBootJars(ctx) {
global := dexpreopt.GetGlobalConfig(ctx)
dexPaths, dexLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp)
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(dexPaths.Strings(), " "))
diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go
index 37c54b9..33c682b 100644
--- a/java/dexpreopt_config_testing.go
+++ b/java/dexpreopt_config_testing.go
@@ -1335,8 +1335,6 @@
DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTboot=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot.art
DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTmainline=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot.art:out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/boot-framework-foo.art
DEXPREOPT_IMAGE_NAMES=art boot mainline
-DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof:/system/etc/boot-image.prof out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof
-DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-extra1.oat:/apex/art_boot_images/javalib/arm/boot-extra1.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat:/apex/art_boot_images/javalib/arm64/boot-extra1.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat:/apex/art_boot_images/javalib/x86/boot-extra1.oat
diff --git a/java/java.go b/java/java.go
index ab11363..92dcc63 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2612,13 +2612,6 @@
return nil
}
-func (j *Import) getStrictUpdatabilityLinting() bool {
- return false
-}
-
-func (j *Import) setStrictUpdatabilityLinting(bool) {
-}
-
func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs.GetOrDefault(ctx, nil)...)
@@ -3098,13 +3091,6 @@
return true
}
-func (j *DexImport) getStrictUpdatabilityLinting() bool {
- return false
-}
-
-func (j *DexImport) setStrictUpdatabilityLinting(bool) {
-}
-
func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if len(j.properties.Jars) != 1 {
ctx.PropertyErrorf("jars", "exactly one jar must be provided")
diff --git a/java/lint.go b/java/lint.go
index 5cd49a8..2cbefc3 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -100,32 +100,30 @@
buildModuleReportZip bool
}
-type LintDepSetsIntf interface {
- // Methods used to propagate strict_updatability_linting values.
- GetStrictUpdatabilityLinting() bool
- SetStrictUpdatabilityLinting(bool)
-}
-
type LintDepSets struct {
- HTML, Text, XML *android.DepSet[android.Path]
+ HTML, Text, XML, Baseline *android.DepSet[android.Path]
}
type LintDepSetsBuilder struct {
- HTML, Text, XML *android.DepSetBuilder[android.Path]
+ HTML, Text, XML, Baseline *android.DepSetBuilder[android.Path]
}
func NewLintDepSetBuilder() LintDepSetsBuilder {
return LintDepSetsBuilder{
- HTML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
- Text: android.NewDepSetBuilder[android.Path](android.POSTORDER),
- XML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ HTML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ Text: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ XML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ Baseline: android.NewDepSetBuilder[android.Path](android.POSTORDER),
}
}
-func (l LintDepSetsBuilder) Direct(html, text, xml android.Path) LintDepSetsBuilder {
+func (l LintDepSetsBuilder) Direct(html, text, xml android.Path, baseline android.OptionalPath) LintDepSetsBuilder {
l.HTML.Direct(html)
l.Text.Direct(text)
l.XML.Direct(xml)
+ if baseline.Valid() {
+ l.Baseline.Direct(baseline.Path())
+ }
return l
}
@@ -139,14 +137,18 @@
if info.TransitiveXML != nil {
l.XML.Transitive(info.TransitiveXML)
}
+ if info.TransitiveBaseline != nil {
+ l.Baseline.Transitive(info.TransitiveBaseline)
+ }
return l
}
func (l LintDepSetsBuilder) Build() LintDepSets {
return LintDepSets{
- HTML: l.HTML.Build(),
- Text: l.Text.Build(),
- XML: l.XML.Build(),
+ HTML: l.HTML.Build(),
+ Text: l.Text.Build(),
+ XML: l.XML.Build(),
+ Baseline: l.Baseline.Build(),
}
}
@@ -194,16 +196,6 @@
},
}
-func (l *linter) GetStrictUpdatabilityLinting() bool {
- return BoolDefault(l.properties.Lint.Strict_updatability_linting, false)
-}
-
-func (l *linter) SetStrictUpdatabilityLinting(strictLinting bool) {
- l.properties.Lint.Strict_updatability_linting = &strictLinting
-}
-
-var _ LintDepSetsIntf = (*linter)(nil)
-
var LintProvider = blueprint.NewProvider[*LintInfo]()
type LintInfo struct {
@@ -212,9 +204,10 @@
XML android.Path
ReferenceBaseline android.Path
- TransitiveHTML *android.DepSet[android.Path]
- TransitiveText *android.DepSet[android.Path]
- TransitiveXML *android.DepSet[android.Path]
+ TransitiveHTML *android.DepSet[android.Path]
+ TransitiveText *android.DepSet[android.Path]
+ TransitiveXML *android.DepSet[android.Path]
+ TransitiveBaseline *android.DepSet[android.Path]
}
func (l *linter) enabled() bool {
@@ -250,7 +243,9 @@
return ctx.Config().GetenvWithDefault("RBE_LINT_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
}
-func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder, srcsList android.Path) lintPaths {
+func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder, srcsList android.Path,
+ baselines android.Paths) lintPaths {
+
projectXMLPath := android.PathForModuleOut(ctx, "lint", "project.xml")
// Lint looks for a lint.xml file next to the project.xml file, give it one.
configXMLPath := android.PathForModuleOut(ctx, "lint", "lint.xml")
@@ -313,12 +308,10 @@
cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
- if l.GetStrictUpdatabilityLinting() {
+ if Bool(l.properties.Lint.Strict_updatability_linting) && len(baselines) > 0 {
// Verify the module does not baseline issues that endanger safe updatability.
- if l.properties.Lint.Baseline_filename != nil {
- cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
- cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks)
- }
+ strictUpdatabilityChecksOutputFile := VerifyStrictUpdatabilityChecks(ctx, baselines)
+ cmd.Validation(strictUpdatabilityChecksOutputFile)
}
return lintPaths{
@@ -330,6 +323,22 @@
}
+func VerifyStrictUpdatabilityChecks(ctx android.ModuleContext, baselines android.Paths) android.Path {
+ rule := android.NewRuleBuilder(pctx, ctx)
+ baselineRspFile := android.PathForModuleOut(ctx, "lint_strict_updatability_check_baselines.rsp")
+ outputFile := android.PathForModuleOut(ctx, "lint_strict_updatability_check.stamp")
+ rule.Command().Text("rm -f").Output(outputFile)
+ rule.Command().
+ BuiltTool("lint_strict_updatability_checks").
+ FlagWithArg("--name ", ctx.ModuleName()).
+ FlagWithRspFileInputList("--baselines ", baselineRspFile, baselines).
+ FlagForEachArg("--disallowed_issues ", updatabilityChecks)
+ rule.Command().Text("touch").Output(outputFile)
+ rule.Build("lint_strict_updatability_checks", "lint strict updatability checks")
+
+ return outputFile
+}
+
// generateManifest adds a command to the rule to write a simple manifest that contains the
// minSdkVersion and targetSdkVersion for modules (like java_library) that don't have a manifest.
func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.WritablePath {
@@ -399,6 +408,26 @@
l.extraLintCheckJars = append(l.extraLintCheckJars, android.PathForSource(ctx,
"prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar"))
+ var baseline android.OptionalPath
+ if l.properties.Lint.Baseline_filename != nil {
+ baseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
+ }
+
+ html := android.PathForModuleOut(ctx, "lint", "lint-report.html")
+ text := android.PathForModuleOut(ctx, "lint", "lint-report.txt")
+ xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml")
+ referenceBaseline := android.PathForModuleOut(ctx, "lint", "lint-baseline.xml")
+
+ depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml, baseline)
+
+ ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
+ if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok {
+ depSetsBuilder.Transitive(info)
+ }
+ })
+
+ depSets := depSetsBuilder.Build()
+
rule := android.NewRuleBuilder(pctx, ctx).
Sbox(android.PathForModuleOut(ctx, "lint"),
android.PathForModuleOut(ctx, "lint.sbox.textproto")).
@@ -425,22 +454,9 @@
srcsListRsp := android.PathForModuleOut(ctx, "lint-srcs.list.rsp")
rule.Command().Text("cp").FlagWithRspFileInputList("", srcsListRsp, l.srcs).Output(srcsList).Implicits(l.compile_data)
- lintPaths := l.writeLintProjectXML(ctx, rule, srcsList)
+ baselines := depSets.Baseline.ToList()
- html := android.PathForModuleOut(ctx, "lint", "lint-report.html")
- text := android.PathForModuleOut(ctx, "lint", "lint-report.txt")
- xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml")
- referenceBaseline := android.PathForModuleOut(ctx, "lint", "lint-baseline.xml")
-
- depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml)
-
- ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
- if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok {
- depSetsBuilder.Transitive(info)
- }
- })
-
- depSets := depSetsBuilder.Build()
+ lintPaths := l.writeLintProjectXML(ctx, rule, srcsList, baselines)
rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
rule.Command().Text("mkdir -p").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
@@ -495,8 +511,8 @@
cmd.FlagWithArg("--check ", checkOnly)
}
- if l.properties.Lint.Baseline_filename != nil {
- cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
+ if baseline.Valid() {
+ cmd.FlagWithInput("--baseline ", baseline.Path())
}
cmd.FlagWithOutput("--write-reference-baseline ", referenceBaseline)
@@ -526,13 +542,14 @@
XML: xml,
ReferenceBaseline: referenceBaseline,
- TransitiveHTML: depSets.HTML,
- TransitiveText: depSets.Text,
- TransitiveXML: depSets.XML,
+ TransitiveHTML: depSets.HTML,
+ TransitiveText: depSets.Text,
+ TransitiveXML: depSets.XML,
+ TransitiveBaseline: depSets.Baseline,
})
if l.buildModuleReportZip {
- l.reports = BuildModuleLintReportZips(ctx, depSets)
+ l.reports = BuildModuleLintReportZips(ctx, depSets, nil)
}
// Create a per-module phony target to run the lint check.
@@ -542,7 +559,7 @@
ctx.SetOutputFiles(android.Paths{xml}, ".lint")
}
-func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) android.Paths {
+func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets, validations android.Paths) android.Paths {
htmlList := android.SortedUniquePaths(depSets.HTML.ToList())
textList := android.SortedUniquePaths(depSets.Text.ToList())
xmlList := android.SortedUniquePaths(depSets.XML.ToList())
@@ -552,13 +569,13 @@
}
htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip")
- lintZip(ctx, htmlList, htmlZip)
+ lintZip(ctx, htmlList, htmlZip, validations)
textZip := android.PathForModuleOut(ctx, "lint-report-text.zip")
- lintZip(ctx, textList, textZip)
+ lintZip(ctx, textList, textZip, validations)
xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip")
- lintZip(ctx, xmlList, xmlZip)
+ lintZip(ctx, xmlList, xmlZip, validations)
return android.Paths{htmlZip, textZip, xmlZip}
}
@@ -668,7 +685,7 @@
}
}
- lintZip(ctx, paths, outputPath)
+ lintZip(ctx, paths, outputPath, nil)
}
l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip")
@@ -697,17 +714,9 @@
func init() {
android.RegisterParallelSingletonType("lint",
func() android.Singleton { return &lintSingleton{} })
-
- registerLintBuildComponents(android.InitRegistrationContext)
}
-func registerLintBuildComponents(ctx android.RegistrationContext) {
- ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("enforce_strict_updatability_linting", enforceStrictUpdatabilityLintingMutator).Parallel()
- })
-}
-
-func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath) {
+func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath, validations android.Paths) {
paths = android.SortedUniquePaths(android.CopyOfPaths(paths))
sort.Slice(paths, func(i, j int) bool {
@@ -719,19 +728,8 @@
rule.Command().BuiltTool("soong_zip").
FlagWithOutput("-o ", outputPath).
FlagWithArg("-C ", android.PathForIntermediates(ctx).String()).
- FlagWithRspFileInputList("-r ", outputPath.ReplaceExtension(ctx, "rsp"), paths)
+ FlagWithRspFileInputList("-r ", outputPath.ReplaceExtension(ctx, "rsp"), paths).
+ Validations(validations)
rule.Build(outputPath.Base(), outputPath.Base())
}
-
-// Enforce the strict updatability linting to all applicable transitive dependencies.
-func enforceStrictUpdatabilityLintingMutator(ctx android.TopDownMutatorContext) {
- m := ctx.Module()
- if d, ok := m.(LintDepSetsIntf); ok && d.GetStrictUpdatabilityLinting() {
- ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) {
- if a, ok := d.(LintDepSetsIntf); ok {
- a.SetStrictUpdatabilityLinting(true)
- }
- })
- }
-}
diff --git a/java/lint_test.go b/java/lint_test.go
index b51753f..afe3914 100644
--- a/java/lint_test.go
+++ b/java/lint_test.go
@@ -164,7 +164,7 @@
sdk_version: "current",
lint: {
strict_updatability_linting: true,
- baseline_filename: "lint-baseline.xml",
+ baseline_filename: "foo_lint_baseline.xml",
},
}
@@ -176,7 +176,7 @@
min_sdk_version: "29",
sdk_version: "current",
lint: {
- baseline_filename: "lint-baseline.xml",
+ baseline_filename: "bar_lint_baseline.xml",
}
}
`
@@ -188,18 +188,13 @@
RunTestWithBp(t, bp)
foo := result.ModuleForTests("foo", "android_common")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, foo.Output("lint.sbox.textproto"))
- if !strings.Contains(*sboxProto.Commands[0].Command,
- "--baseline lint-baseline.xml --disallowed_issues NewApi") {
+ strictUpdatabilityCheck := foo.Output("lint_strict_updatability_check.stamp")
+ if !strings.Contains(strictUpdatabilityCheck.RuleParams.Command,
+ "--disallowed_issues NewApi") {
t.Error("did not restrict baselining NewApi")
}
-
- bar := result.ModuleForTests("bar", "android_common")
- sboxProto = android.RuleBuilderSboxProtoForTests(t, result.TestContext, bar.Output("lint.sbox.textproto"))
- if !strings.Contains(*sboxProto.Commands[0].Command,
- "--baseline lint-baseline.xml --disallowed_issues NewApi") {
- t.Error("did not restrict baselining NewApi")
- }
+ android.AssertStringListContains(t, "strict updatability check baseline inputs", strictUpdatabilityCheck.Inputs.Strings(), "foo_lint_baseline.xml")
+ android.AssertStringListContains(t, "strict updatability check baseline inputs", strictUpdatabilityCheck.Inputs.Strings(), "bar_lint_baseline.xml")
}
func TestJavaLintDatabaseSelectionFull(t *testing.T) {
diff --git a/java/rro_test.go b/java/rro_test.go
index 742c839..4d79130 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -282,7 +282,7 @@
enforceRROTargets: []string{"foo"},
rroDirs: map[string][]string{
"foo": {"product/vendor/blah/overlay/lib2/res"},
- "bar": {"product/vendor/blah/overlay/lib2/res"},
+ "bar": nil,
},
},
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index c0242a0..f308772 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2209,21 +2209,6 @@
}
// to satisfy apex.javaDependency interface
-func (module *SdkLibraryImport) GetStrictUpdatabilityLinting() bool {
- if module.implLibraryModule == nil {
- return false
- } else {
- return module.implLibraryModule.GetStrictUpdatabilityLinting()
- }
-}
-
-func (module *SdkLibraryImport) SetStrictUpdatabilityLinting(strictLinting bool) {
- if module.implLibraryModule != nil {
- module.implLibraryModule.SetStrictUpdatabilityLinting(strictLinting)
- }
-}
-
-// to satisfy apex.javaDependency interface
func (module *SdkLibraryImport) Stem() string {
return module.BaseModuleName()
}
diff --git a/java/testing.go b/java/testing.go
index 6cc9fd1..d5a19e9 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -388,7 +388,6 @@
RegisterStubsBuildComponents(ctx)
RegisterSystemModulesBuildComponents(ctx)
registerSystemserverClasspathBuildComponents(ctx)
- registerLintBuildComponents(ctx)
android.RegisterApexContributionsBuildComponents(ctx)
}
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 3d81b83..00b3ca5 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -184,12 +184,21 @@
libs: ["ninja_rsp"],
}
-python_test_host {
- name: "lint_project_xml_test",
- main: "lint_project_xml_test.py",
+python_binary_host {
+ name: "lint_strict_updatability_checks",
+ main: "lint_strict_updatability_checks.py",
srcs: [
- "lint_project_xml_test.py",
- "lint_project_xml.py",
+ "lint_strict_updatability_checks.py",
+ ],
+ libs: ["ninja_rsp"],
+}
+
+python_test_host {
+ name: "lint_strict_updatability_checks_test",
+ main: "lint_strict_updatability_checks_test.py",
+ srcs: [
+ "lint_strict_updatability_checks_test.py",
+ "lint_strict_updatability_checks.py",
],
libs: ["ninja_rsp"],
test_suites: ["general-tests"],
diff --git a/scripts/lint_project_xml.py b/scripts/lint_project_xml.py
index c40b07d..ce6aa21 100755
--- a/scripts/lint_project_xml.py
+++ b/scripts/lint_project_xml.py
@@ -75,8 +75,6 @@
help='file containing the module\'s manifest.')
parser.add_argument('--merged_manifest', dest='merged_manifest',
help='file containing merged manifest for the module and its dependencies.')
- parser.add_argument('--baseline', dest='baseline_path',
- help='file containing baseline lint issues.')
parser.add_argument('--library', dest='library', action='store_true',
help='mark the module as a library.')
parser.add_argument('--test', dest='test', action='store_true',
@@ -94,8 +92,6 @@
help='treat a lint issue as a warning.')
group.add_argument('--disable_check', dest='checks', action=check_action('ignore'), default=[],
help='disable a lint issue.')
- group.add_argument('--disallowed_issues', dest='disallowed_issues', default=[],
- help='lint issues disallowed in the baseline file')
return parser.parse_args()
@@ -140,30 +136,10 @@
f.write("</lint>\n")
-def check_baseline_for_disallowed_issues(baseline, forced_checks):
- issues_element = baseline.documentElement
- if issues_element.tagName != 'issues':
- raise RuntimeError('expected issues tag at root')
- issues = issues_element.getElementsByTagName('issue')
- disallowed = set()
- for issue in issues:
- id = issue.getAttribute('id')
- if id in forced_checks:
- disallowed.add(id)
- return disallowed
-
-
def main():
"""Program entry point."""
args = parse_args()
- if args.baseline_path:
- baseline = minidom.parse(args.baseline_path)
- disallowed_issues = check_baseline_for_disallowed_issues(baseline, args.disallowed_issues)
- if disallowed_issues:
- sys.exit('disallowed issues %s found in lint baseline file %s for module %s'
- % (disallowed_issues, args.baseline_path, args.name))
-
if args.project_out:
with open(args.project_out, 'w') as f:
write_project_xml(f, args)
diff --git a/scripts/lint_strict_updatability_checks.py b/scripts/lint_strict_updatability_checks.py
new file mode 100755
index 0000000..5b5dfd8
--- /dev/null
+++ b/scripts/lint_strict_updatability_checks.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""This file checks baselines passed to Android Lint for checks that must not be baselined."""
+
+import argparse
+import sys
+from xml.dom import minidom
+
+from ninja_rsp import NinjaRspFileReader
+
+
+def parse_args():
+ """Parse commandline arguments."""
+
+ def convert_arg_line_to_args(arg_line):
+ for arg in arg_line.split():
+ if arg.startswith('#'):
+ return
+ if not arg.strip():
+ continue
+ yield arg
+
+ parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
+ parser.convert_arg_line_to_args = convert_arg_line_to_args
+ parser.add_argument('--name', dest='name',
+ help='name of the module.')
+ parser.add_argument('--baselines', dest='baselines', action='append', default=[],
+ help='file containing whitespace separated list of baseline files.')
+ parser.add_argument('--disallowed_issues', dest='disallowed_issues', default=[],
+ help='lint issues disallowed in the baseline file')
+ return parser.parse_args()
+
+
+def check_baseline_for_disallowed_issues(baseline, forced_checks):
+ issues_element = baseline.documentElement
+ if issues_element.tagName != 'issues':
+ raise RuntimeError('expected issues tag at root')
+ issues = issues_element.getElementsByTagName('issue')
+ disallowed = set()
+ for issue in issues:
+ id = issue.getAttribute('id')
+ if id in forced_checks:
+ disallowed.add(id)
+ return disallowed
+
+
+def main():
+ """Program entry point."""
+ args = parse_args()
+
+ error = False
+ for baseline_rsp_file in args.baselines:
+ for baseline_path in NinjaRspFileReader(baseline_rsp_file):
+ baseline = minidom.parse(baseline_path)
+ disallowed_issues = check_baseline_for_disallowed_issues(baseline, args.disallowed_issues)
+ if disallowed_issues:
+ print('disallowed issues %s found in lint baseline file %s for module %s'
+ % (disallowed_issues, baseline_path, args.name))
+ error = True
+
+ if error:
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/lint_project_xml_test.py b/scripts/lint_strict_updatability_checks_test.py
old mode 100644
new mode 100755
similarity index 88%
rename from scripts/lint_project_xml_test.py
rename to scripts/lint_strict_updatability_checks_test.py
index 344691d..fd8610f
--- a/scripts/lint_project_xml_test.py
+++ b/scripts/lint_strict_updatability_checks_test.py
@@ -15,12 +15,12 @@
# limitations under the License.
#
-"""Unit tests for lint_project_xml.py."""
+"""Unit tests for lint_strict_updatability_checks.py."""
import unittest
from xml.dom import minidom
-import lint_project_xml
+import lint_strict_updatability_checks
class CheckBaselineForDisallowedIssuesTest(unittest.TestCase):
@@ -44,7 +44,7 @@
'</issues>\n')
def test_check_baseline_for_disallowed_issues(self):
- disallowed_issues = lint_project_xml.check_baseline_for_disallowed_issues(self.baseline_xml, ["foo", "bar", "qux"])
+ disallowed_issues = lint_strict_updatability_checks.check_baseline_for_disallowed_issues(self.baseline_xml, ["foo", "bar", "qux"])
self.assertEqual({"foo", "bar"}, disallowed_issues)