Merge "Give flag to R8 if we explicity opted for optimized shrinking" into main
diff --git a/Android.bp b/Android.bp
index d71bcec..d0f97db 100644
--- a/Android.bp
+++ b/Android.bp
@@ -142,6 +142,24 @@
visibility: ["//visibility:public"],
}
+// Defaults to share configs between "baremetal" Soong modules, currently only
+// used for code running in kernel context within Android Virtualization
+// Framework guests.
+cc_defaults {
+ name: "cc_baremetal_defaults",
+ arch: {
+ arm64: {
+ cflags: [
+ // Prevent the compiler from optimizing code using SVE, as the
+ // baremetal environment might not have configured the hardware.
+ "-Xclang -target-feature",
+ "-Xclang -sve",
+ ],
+ },
+ },
+ defaults_visibility: ["//visibility:public"],
+}
+
product_config {
name: "product_config",
visibility: [
@@ -153,10 +171,11 @@
name: "system-build.prop",
stem: "build.prop",
product_config: ":product_config",
- // Currently, only microdroid and cf system image can refer to system-build.prop
+ // Currently, only microdroid, Ravenwood, and cf system image can refer to system-build.prop
visibility: [
"//build/make/target/product/generic",
"//packages/modules/Virtualization/build/microdroid",
+ "//frameworks/base/ravenwood",
],
}
diff --git a/aconfig/codegen/aconfig_declarations_group.go b/aconfig/codegen/aconfig_declarations_group.go
index 13daf47..6811d06 100644
--- a/aconfig/codegen/aconfig_declarations_group.go
+++ b/aconfig/codegen/aconfig_declarations_group.go
@@ -59,7 +59,7 @@
func AconfigDeclarationsGroupFactory() android.Module {
module := &AconfigDeclarationsGroup{}
module.AddProperties(&module.properties)
- android.InitAndroidModule(module)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
return module
}
diff --git a/aconfig/codegen/aconfig_declarations_group_test.go b/aconfig/codegen/aconfig_declarations_group_test.go
index c69d21f..ef954ce 100644
--- a/aconfig/codegen/aconfig_declarations_group_test.go
+++ b/aconfig/codegen/aconfig_declarations_group_test.go
@@ -67,7 +67,7 @@
`)
// Check if aconfig_declarations_group module depends on the aconfig_library modules
- java.CheckModuleDependencies(t, result.TestContext, "my_group", "", []string{
+ java.CheckModuleDependencies(t, result.TestContext, "my_group", "android_common", []string{
`bar-java`,
`foo-java`,
})
diff --git a/android/Android.bp b/android/Android.bp
index eb8c64d..3b54326 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -52,6 +52,7 @@
"defs.go",
"depset_generic.go",
"deptag.go",
+ "dirgroup.go",
"early_module_context.go",
"expand.go",
"filegroup.go",
@@ -89,7 +90,6 @@
"prebuilt.go",
"prebuilt_build_tool.go",
"product_config.go",
- "product_config_to_bp.go",
"proto.go",
"provider.go",
"raw_files.go",
diff --git a/android/arch.go b/android/arch.go
index 1ec971d..3cd6e4b 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -567,10 +567,6 @@
// "32": compile for only a single 32-bit Target supported by the OsClass.
// "64": compile for only a single 64-bit Target supported by the OsClass.
// "common": compile a for a single Target that will work on all Targets supported by the OsClass (for example Java).
-// "common_first": compile a for a Target that will work on all Targets supported by the OsClass
-// (same as "common"), plus a second Target for the preferred Target supported by the OsClass
-// (same as "first"). This is used for java_binary that produces a common .jar and a wrapper
-// executable script.
//
// Once the list of Targets is determined, the module is split into a variant for each Target.
//
@@ -702,11 +698,9 @@
return ""
}
- if incomingVariation == "" {
- multilib, _ := decodeMultilib(ctx, base)
- if multilib == "common" {
- return "common"
- }
+ multilib, _ := decodeMultilib(ctx, base)
+ if multilib == "common" {
+ return "common"
}
return incomingVariation
}
@@ -756,8 +750,7 @@
// Create a dependency for Darwin Universal binaries from the primary to secondary
// architecture. The module itself will be responsible for calling lipo to merge the outputs.
if os == Darwin {
- isUniversalBinary := (allArchInfo.Multilib == "darwin_universal" && len(allArchInfo.Targets) == 2) ||
- allArchInfo.Multilib == "darwin_universal_common_first" && len(allArchInfo.Targets) == 3
+ isUniversalBinary := allArchInfo.Multilib == "darwin_universal" && len(allArchInfo.Targets) == 2
isPrimary := variation == ctx.Config().BuildArch.String()
hasSecondaryConfigured := len(ctx.Config().Targets[Darwin]) > 1
if isUniversalBinary && isPrimary && hasSecondaryConfigured {
@@ -825,11 +818,7 @@
// !UseTargetVariants, as the module has opted into handling the arch-specific logic on
// its own.
if os == Darwin && multilib != "common" && multilib != "32" {
- if multilib == "common_first" {
- multilib = "darwin_universal_common_first"
- } else {
- multilib = "darwin_universal"
- }
+ multilib = "darwin_universal"
}
return multilib, ""
@@ -1369,7 +1358,7 @@
// Returns the structs corresponding to the properties specific to the given
// architecture and OS in archProperties.
-func getArchProperties(ctx BaseMutatorContext, archProperties interface{}, arch Arch, os OsType, nativeBridgeEnabled bool) []reflect.Value {
+func getArchProperties(ctx BaseModuleContext, archProperties interface{}, arch Arch, os OsType, nativeBridgeEnabled bool) []reflect.Value {
result := make([]reflect.Value, 0)
archPropValues := reflect.ValueOf(archProperties).Elem()
@@ -1941,13 +1930,6 @@
switch multilib {
case "common":
buildTargets = getCommonTargets(targets)
- case "common_first":
- buildTargets = getCommonTargets(targets)
- if prefer32 {
- buildTargets = append(buildTargets, FirstTarget(targets, "lib32", "lib64")...)
- } else {
- buildTargets = append(buildTargets, FirstTarget(targets, "lib64", "lib32")...)
- }
case "both":
if prefer32 {
buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...)
@@ -1978,10 +1960,6 @@
// Reverse the targets so that the first architecture can depend on the second
// architecture module in order to merge the outputs.
ReverseSliceInPlace(buildTargets)
- case "darwin_universal_common_first":
- archTargets := filterMultilibTargets(targets, "lib64")
- ReverseSliceInPlace(archTargets)
- buildTargets = append(getCommonTargets(targets), archTargets...)
default:
return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", "prefer32" or "first_prefer32" found %q`,
multilib)
diff --git a/android/base_module_context.go b/android/base_module_context.go
index 670537f..e24ce9d 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -136,12 +136,14 @@
// 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
+ // The ModuleProxy passed to the visit function should not be retained outside of the visit function, it may be
// invalidated by future mutators.
- VisitDirectDepsProxyAllowDisabled(visit func(proxy Module))
+ VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy))
VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
+ VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy))
+
// VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
// multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
// OtherModuleDependencyTag will return a different tag for each. It skips any
@@ -173,7 +175,7 @@
//
// The Modules passed to the visit function should not be retained outside of the visit function, they may be
// invalidated by future mutators.
- WalkDepsProxy(visit func(child, parent Module) bool)
+ WalkDepsProxy(visit func(child, parent ModuleProxy) 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.
@@ -314,6 +316,7 @@
type AllowDisabledModuleDependency interface {
blueprint.DependencyTag
AllowDisabledModuleDependency(target Module) bool
+ AllowDisabledModuleDependencyProxy(ctx OtherModuleProviderContext, target ModuleProxy) bool
}
type AlwaysAllowDisabledModuleDependencyTag struct{}
@@ -322,6 +325,10 @@
return true
}
+func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependencyProxy(OtherModuleProviderContext, ModuleProxy) bool {
+ return true
+}
+
func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
aModule, _ := module.(Module)
@@ -346,6 +353,28 @@
return aModule
}
+func (b *baseModuleContext) validateAndroidModuleProxy(
+ module blueprint.ModuleProxy, tag blueprint.DependencyTag, strict bool) *ModuleProxy {
+ aModule := ModuleProxy{module: module}
+
+ if !strict {
+ return &aModule
+ }
+
+ if !OtherModuleProviderOrDefault(b, module, CommonPropertiesProviderKey).Enabled {
+ if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependencyProxy(b, aModule) {
+ if b.Config().AllowMissingDependencies() {
+ b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
+ } else {
+ b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
+ }
+ }
+ return nil
+ }
+
+ return &aModule
+}
+
type dep struct {
mod blueprint.Module
tag blueprint.DependencyTag
@@ -426,7 +455,7 @@
})
}
-func (b *baseModuleContext) VisitDirectDepsProxyAllowDisabled(visit func(proxy Module)) {
+func (b *baseModuleContext) VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy)) {
b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
visit(ModuleProxy{
module: module,
@@ -437,13 +466,23 @@
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); aModule != nil {
+ if aModule := b.validateAndroidModule(module, tag, b.strictVisitDeps); aModule != nil {
visit(aModule)
}
}
})
}
+func (b *baseModuleContext) VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy)) {
+ b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
+ if b.bp.OtherModuleDependencyTag(module) == tag {
+ if aModule := b.validateAndroidModuleProxy(module, tag, b.strictVisitDeps); aModule != nil {
+ visit(*aModule)
+ }
+ }
+ })
+}
+
func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
b.bp.VisitDirectDepsIf(
// pred
@@ -505,7 +544,7 @@
})
}
-func (b *baseModuleContext) WalkDepsProxy(visit func(Module, Module) bool) {
+func (b *baseModuleContext) WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool) {
b.walkPath = []Module{ModuleProxy{blueprint.CreateModuleProxy(b.Module())}}
b.tagPath = []blueprint.DependencyTag{}
b.bp.WalkDepsProxy(func(child, parent blueprint.ModuleProxy) bool {
diff --git a/android/config.go b/android/config.go
index 06d71c0..686e861 100644
--- a/android/config.go
+++ b/android/config.go
@@ -324,6 +324,9 @@
AndroidCommonTarget Target // the Target for common modules for the Android device
AndroidFirstDeviceTarget Target // the first Target for modules for the Android device
+ // Flags for Partial Compile, derived from SOONG_PARTIAL_COMPILE.
+ partialCompileFlags partialCompileFlags
+
// multilibConflicts for an ArchType is true if there is earlier configured
// device architecture with the same multilib value.
multilibConflicts map[ArchType]bool
@@ -373,6 +376,16 @@
ensureAllowlistIntegrity bool
}
+type partialCompileFlags struct {
+ // Is partial compilation enabled at all?
+ enabled bool
+
+ // Whether to use d8 instead of r8
+ use_d8 bool
+
+ // Add others as needed.
+}
+
type deviceConfig struct {
config *config
OncePer
@@ -382,6 +395,88 @@
SetDefaultConfig()
}
+// Parse SOONG_PARTIAL_COMPILE.
+//
+// SOONG_PARTIAL_COMPILE determines which features are enabled or disabled in
+// rule generation. Changing this environment variable causes reanalysis.
+//
+// SOONG_USE_PARTIAL_COMPILE determines whether or not we **use** PARTIAL_COMPILE.
+// Rule generation must support both cases, since changing it does not cause
+// reanalysis.
+//
+// The user-facing documentation shows:
+//
+// - empty or not set: "The current default state"
+// - "true" or "on": enable all stable partial compile features.
+// - "false" or "off": disable partial compile completely.
+//
+// What we actually allow is a comma separated list of tokens, whose first
+// character may be "+" (enable) or "-" (disable). If neither is present, "+"
+// is assumed. For example, "on,+use_d8" will enable partial compilation, and
+// additionally set the use_d8 flag (regardless of whether it is opt-in or
+// opt-out).
+//
+// To add a new feature to the list, add the field in the struct
+// `partialCompileFlags` above, and then add the name of the field in the
+// switch statement below.
+func (c *config) parsePartialCompileFlags() (partialCompileFlags, error) {
+ defaultFlags := partialCompileFlags{
+ // Set any opt-out flags here. Opt-in flags are off by default.
+ enabled: false,
+ }
+ value := c.Getenv("SOONG_PARTIAL_COMPILE")
+
+ if value == "" {
+ return defaultFlags, nil
+ }
+
+ ret := defaultFlags
+ tokens := strings.Split(strings.ToLower(value), ",")
+ makeVal := func(state string, defaultValue bool) bool {
+ switch state {
+ case "":
+ return defaultValue
+ case "-":
+ return false
+ case "+":
+ return true
+ }
+ return false
+ }
+ for _, tok := range tokens {
+ var state string
+ if len(tok) == 0 {
+ continue
+ }
+ switch tok[0:1] {
+ case "":
+ // Ignore empty tokens.
+ continue
+ case "-", "+":
+ state = tok[0:1]
+ tok = tok[1:]
+ default:
+ // Treat `feature` as `+feature`.
+ state = "+"
+ }
+ switch tok {
+ case "true":
+ ret = defaultFlags
+ ret.enabled = true
+ case "false":
+ // Set everything to false.
+ ret = partialCompileFlags{}
+ case "enabled":
+ ret.enabled = makeVal(state, defaultFlags.enabled)
+ case "use_d8":
+ ret.use_d8 = makeVal(state, defaultFlags.use_d8)
+ default:
+ return partialCompileFlags{}, fmt.Errorf("Unknown SOONG_PARTIAL_COMPILE value: %v", value)
+ }
+ }
+ return ret, nil
+}
+
func loadConfig(config *config) error {
return loadFromConfigFile(&config.productVariables, absolutePath(config.ProductVariablesFileName))
}
@@ -568,6 +663,11 @@
return Config{}, err
}
+ config.partialCompileFlags, err = config.parsePartialCompileFlags()
+ if err != nil {
+ return Config{}, err
+ }
+
// Make the CommonOS OsType available for all products.
targets[CommonOS] = []Target{commonTargetMap[CommonOS.Name]}
@@ -999,6 +1099,10 @@
return ApiLevelOrPanic(ctx, codename)
}
+func (c *config) PartialCompileFlags() partialCompileFlags {
+ return c.partialCompileFlags
+}
+
func (c *config) AppsDefaultVersionName() string {
return String(c.productVariables.AppsDefaultVersionName)
}
@@ -1420,6 +1524,10 @@
return "vendor"
}
+func (c *deviceConfig) BuildingVendorImage() bool {
+ return proptools.Bool(c.config.productVariables.BuildingVendorImage)
+}
+
func (c *deviceConfig) CurrentApiLevelForVendorModules() string {
return StringDefault(c.config.productVariables.DeviceCurrentApiLevelForVendorModules, "current")
}
@@ -1450,6 +1558,10 @@
return "product"
}
+func (c *deviceConfig) BuildingProductImage() bool {
+ return proptools.Bool(c.config.productVariables.BuildingProductImage)
+}
+
func (c *deviceConfig) SystemExtPath() string {
if c.config.productVariables.SystemExtPath != nil {
return *c.config.productVariables.SystemExtPath
diff --git a/android/defaults.go b/android/defaults.go
index 3d06c69..510ebe0 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -273,8 +273,8 @@
}
func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
- ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
- ctx.BottomUp("defaults", defaultsMutator).Parallel()
+ ctx.BottomUp("defaults_deps", defaultsDepsMutator)
+ ctx.BottomUp("defaults", defaultsMutator).UsesCreateModule()
}
func defaultsDepsMutator(ctx BottomUpMutatorContext) {
diff --git a/android/dirgroup.go b/android/dirgroup.go
new file mode 100644
index 0000000..20c4d13
--- /dev/null
+++ b/android/dirgroup.go
@@ -0,0 +1,63 @@
+// Copyright 2024 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 android
+
+import (
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ RegisterDirgroupBuildComponents(InitRegistrationContext)
+}
+
+func RegisterDirgroupBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("dirgroup", DirGroupFactory)
+}
+
+type dirGroupProperties struct {
+ // dirs lists directories that will be included in this dirgroup
+ Dirs proptools.Configurable[[]string] `android:"path"`
+}
+
+type dirGroup struct {
+ ModuleBase
+ DefaultableModuleBase
+ properties dirGroupProperties
+}
+
+type DirInfo struct {
+ // TODO(b/358302178): Use DirectoryPaths instead of Paths
+ Dirs Paths
+}
+
+var DirProvider = blueprint.NewProvider[DirInfo]()
+
+// dirgroup contains a list of dirs that are referenced by other modules
+// properties using the syntax ":<name>". dirgroup are also be used to export
+// dirs across package boundaries. Currently the only allowed usage is genrule's
+// dir_srcs property.
+func DirGroupFactory() Module {
+ module := &dirGroup{}
+ module.AddProperties(&module.properties)
+ InitAndroidModule(module)
+ InitDefaultableModule(module)
+ return module
+}
+
+func (fg *dirGroup) GenerateAndroidBuildActions(ctx ModuleContext) {
+ dirs := DirectoryPathsForModuleSrc(ctx, fg.properties.Dirs.GetOrDefault(ctx, nil))
+ SetProvider(ctx, DirProvider, DirInfo{Dirs: dirs})
+}
diff --git a/android/early_module_context.go b/android/early_module_context.go
index 11de771..9b1a9ea 100644
--- a/android/early_module_context.go
+++ b/android/early_module_context.go
@@ -29,7 +29,7 @@
Module() Module
// ModuleName returns the name of the module. This is generally the value that was returned by Module.Name() when
- // the module was created, but may have been modified by calls to BaseMutatorContext.Rename.
+ // the module was created, but may have been modified by calls to BottomUpMutatorContext.Rename.
ModuleName() string
// ModuleDir returns the path to the directory that contains the definition of the module.
diff --git a/android/filegroup.go b/android/filegroup.go
index ff0f74e..67e5add1f 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -41,6 +41,14 @@
Exclude_srcs proptools.Configurable[[]string] `android:"path"`
+ // Sources the will be included in the filegroup, but any module dependencies will be added
+ // using the device os and the device's first architecture's variant.
+ Device_first_srcs proptools.Configurable[[]string] `android:"path_device_first"`
+
+ // Sources the will be included in the filegroup, but any module dependencies will be added
+ // using the device os and the common architecture's variant.
+ Device_common_srcs proptools.Configurable[[]string] `android:"path_device_common"`
+
// The base path to the files. May be used by other modules to determine which portion
// of the path to use. For example, when a filegroup is used as data in a cc_test rule,
// the base path is stripped off the path and the remaining path is used as the
@@ -90,11 +98,13 @@
}
func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) {
- fg.srcs = PathsForModuleSrcExcludes(ctx, fg.properties.Srcs.GetOrDefault(ctx, nil), fg.properties.Exclude_srcs.GetOrDefault(ctx, nil))
+ srcs := PathsForModuleSrcExcludes(ctx, fg.properties.Srcs.GetOrDefault(ctx, nil), fg.properties.Exclude_srcs.GetOrDefault(ctx, nil))
+ srcs = append(srcs, PathsForModuleSrc(ctx, fg.properties.Device_first_srcs.GetOrDefault(ctx, nil))...)
+ srcs = append(srcs, PathsForModuleSrc(ctx, fg.properties.Device_common_srcs.GetOrDefault(ctx, nil))...)
if fg.properties.Path != nil {
- fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path))
+ srcs = PathsWithModuleSrcSubDir(ctx, srcs, String(fg.properties.Path))
}
- SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: fg.srcs.Strings()})
+ SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
var aconfigDeclarations []string
var intermediateCacheOutputPaths Paths
@@ -108,6 +118,8 @@
maps.Copy(modeInfos, dep.ModeInfos)
}
})
+
+ fg.srcs = srcs
SetProvider(ctx, CodegenInfoProvider, CodegenInfo{
AconfigDeclarations: aconfigDeclarations,
IntermediateCacheOutputPaths: intermediateCacheOutputPaths,
@@ -139,3 +151,15 @@
return module
}
+
+// Collect information for opening IDE project files in java/jdeps.go.
+// Copied from build/soong/genrule/genrule.go
+func (fg *fileGroup) IDEInfo(ctx BaseModuleContext, dpInfo *IdeInfo) {
+ dpInfo.Srcs = append(dpInfo.Srcs, fg.Srcs().Strings()...)
+ for _, src := range fg.properties.Srcs.GetOrDefault(ctx, nil) {
+ if mod, _ := SrcIsModuleWithTag(src); mod != "" {
+ // Register the module name without any tags in `Deps`
+ dpInfo.Deps = append(dpInfo.Deps, mod)
+ }
+ }
+}
diff --git a/android/image.go b/android/image.go
index 6e5a551..012267a 100644
--- a/android/image.go
+++ b/android/image.go
@@ -14,44 +14,61 @@
package android
+type ImageInterfaceContext interface {
+ ArchModuleContext
+
+ Module() Module
+
+ ModuleErrorf(fmt string, args ...interface{})
+ PropertyErrorf(property, fmt string, args ...interface{})
+
+ DeviceSpecific() bool
+ SocSpecific() bool
+ ProductSpecific() bool
+ SystemExtSpecific() bool
+ Platform() bool
+
+ Config() Config
+}
+
// ImageInterface is implemented by modules that need to be split by the imageTransitionMutator.
type ImageInterface interface {
// ImageMutatorBegin is called before any other method in the ImageInterface.
- ImageMutatorBegin(ctx BaseModuleContext)
+ ImageMutatorBegin(ctx ImageInterfaceContext)
// VendorVariantNeeded should return true if the module needs a vendor variant (installed on the vendor image).
- VendorVariantNeeded(ctx BaseModuleContext) bool
+ VendorVariantNeeded(ctx ImageInterfaceContext) bool
// ProductVariantNeeded should return true if the module needs a product variant (installed on the product image).
- ProductVariantNeeded(ctx BaseModuleContext) bool
+ ProductVariantNeeded(ctx ImageInterfaceContext) bool
// CoreVariantNeeded should return true if the module needs a core variant (installed on the system image).
- CoreVariantNeeded(ctx BaseModuleContext) bool
+ CoreVariantNeeded(ctx ImageInterfaceContext) bool
// RamdiskVariantNeeded should return true if the module needs a ramdisk variant (installed on the
// ramdisk partition).
- RamdiskVariantNeeded(ctx BaseModuleContext) bool
+ RamdiskVariantNeeded(ctx ImageInterfaceContext) bool
// VendorRamdiskVariantNeeded should return true if the module needs a vendor ramdisk variant (installed on the
// vendor ramdisk partition).
- VendorRamdiskVariantNeeded(ctx BaseModuleContext) bool
+ VendorRamdiskVariantNeeded(ctx ImageInterfaceContext) bool
// DebugRamdiskVariantNeeded should return true if the module needs a debug ramdisk variant (installed on the
// debug ramdisk partition: $(PRODUCT_OUT)/debug_ramdisk).
- DebugRamdiskVariantNeeded(ctx BaseModuleContext) bool
+ DebugRamdiskVariantNeeded(ctx ImageInterfaceContext) bool
// RecoveryVariantNeeded should return true if the module needs a recovery variant (installed on the
// recovery partition).
- RecoveryVariantNeeded(ctx BaseModuleContext) bool
+ RecoveryVariantNeeded(ctx ImageInterfaceContext) bool
// ExtraImageVariations should return a list of the additional variations needed for the module. After the
// variants are created the SetImageVariation method will be called on each newly created variant with the
// its variation.
- ExtraImageVariations(ctx BaseModuleContext) []string
+ ExtraImageVariations(ctx ImageInterfaceContext) []string
// SetImageVariation is called for each newly created image variant. The receiver is the original
// module, "variation" is the name of the newly created variant. "variation" is set on the receiver.
- SetImageVariation(ctx BaseModuleContext, variation string)
+ SetImageVariation(ctx ImageInterfaceContext, variation string)
}
const (
diff --git a/android/licenses.go b/android/licenses.go
index be1eede..949d678 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -106,19 +106,19 @@
//
// This goes before defaults expansion so the defaults can pick up the package default.
func RegisterLicensesPackageMapper(ctx RegisterMutatorsContext) {
- ctx.BottomUp("licensesPackageMapper", licensesPackageMapper).Parallel()
+ ctx.BottomUp("licensesPackageMapper", licensesPackageMapper)
}
// Registers the function that gathers the license dependencies for each module.
//
// This goes after defaults expansion so that it can pick up default licenses and before visibility enforcement.
func RegisterLicensesPropertyGatherer(ctx RegisterMutatorsContext) {
- ctx.BottomUp("licensesPropertyGatherer", licensesPropertyGatherer).Parallel()
+ ctx.BottomUp("licensesPropertyGatherer", licensesPropertyGatherer)
}
// Registers the function that verifies the licenses and license_kinds dependency types for each module.
func RegisterLicensesDependencyChecker(ctx RegisterMutatorsContext) {
- ctx.BottomUp("licensesPropertyChecker", licensesDependencyChecker).Parallel()
+ ctx.BottomUp("licensesPropertyChecker", licensesDependencyChecker)
}
// Maps each package to its default applicable licenses.
diff --git a/android/module.go b/android/module.go
index 44f7583..e3dabcc 100644
--- a/android/module.go
+++ b/android/module.go
@@ -113,6 +113,10 @@
VintfFragmentModuleNames(ctx ConfigurableEvaluatorContext) []string
ConfigurableEvaluator(ctx ConfigurableEvaluatorContext) proptools.ConfigurableEvaluator
+
+ // The usage of this method is experimental and should not be used outside of fsgen package.
+ // This will be removed once product packaging migration to Soong is complete.
+ DecodeMultilib(ctx ConfigContext) (string, string)
}
// Qualified id for a module
@@ -605,10 +609,9 @@
type Multilib string
const (
- MultilibBoth Multilib = "both"
- MultilibFirst Multilib = "first"
- MultilibCommon Multilib = "common"
- MultilibCommonFirst Multilib = "common_first"
+ MultilibBoth Multilib = "both"
+ MultilibFirst Multilib = "first"
+ MultilibCommon Multilib = "common"
)
type HostOrDeviceSupported int
@@ -1067,6 +1070,11 @@
modPartition := mod.PartitionTag(deviceConfig)
for _, vintf := range vintfModules {
+ if vintf == nil {
+ // TODO(b/372091092): Remove this. Having it gives us missing dependency errors instead
+ // of nil pointer dereference errors, but we should resolve the missing dependencies.
+ continue
+ }
if vintfModule, ok := vintf.(*vintfFragmentModule); ok {
vintfPartition := vintfModule.PartitionTag(deviceConfig)
if modPartition != vintfPartition {
@@ -2278,6 +2286,10 @@
return proptools.Bool(m.commonProperties.Native_bridge_supported)
}
+func (m *ModuleBase) DecodeMultilib(ctx ConfigContext) (string, string) {
+ return decodeMultilib(ctx, m)
+}
+
type ConfigContext interface {
Config() Config
}
@@ -2348,6 +2360,8 @@
case "use_debug_art":
// TODO(b/234351700): Remove once ART does not have separated debug APEX
return proptools.ConfigurableValueBool(ctx.Config().UseDebugArt())
+ case "selinux_ignore_neverallows":
+ return proptools.ConfigurableValueBool(ctx.Config().SelinuxIgnoreNeverallows())
default:
// TODO(b/323382414): Might add these on a case-by-case basis
ctx.OtherModulePropertyErrorf(m, property, fmt.Sprintf("TODO(b/323382414): Product variable %q is not yet supported in selects", variable))
diff --git a/android/module_proxy.go b/android/module_proxy.go
index bc5090e..0f552dd 100644
--- a/android/module_proxy.go
+++ b/android/module_proxy.go
@@ -201,3 +201,7 @@
func (m ModuleProxy) ConfigurableEvaluator(ctx ConfigurableEvaluatorContext) proptools.ConfigurableEvaluator {
panic("method is not implemented on ModuleProxy")
}
+
+func (m ModuleProxy) DecodeMultilib(ctx ConfigContext) (string, string) {
+ panic("method is not implemented on ModuleProxy")
+}
diff --git a/android/mutator.go b/android/mutator.go
index 8265458..6bd2e60 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -192,25 +192,10 @@
finalDeps = append(finalDeps, f)
}
-type BaseMutatorContext interface {
- BaseModuleContext
-
- // MutatorName returns the name that this mutator was registered with.
- MutatorName() string
-
- // Rename all variants of a module. The new name is not visible to calls to ModuleName,
- // AddDependency or OtherModuleName until after this mutator pass is complete.
- Rename(name string)
-
- // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
- // the specified property structs to it as if the properties were set in a blueprint file.
- CreateModule(ModuleFactory, ...interface{}) Module
-}
-
type TopDownMutator func(TopDownMutatorContext)
type TopDownMutatorContext interface {
- BaseMutatorContext
+ BaseModuleContext
}
type topDownMutatorContext struct {
@@ -221,22 +206,20 @@
type BottomUpMutator func(BottomUpMutatorContext)
type BottomUpMutatorContext interface {
- BaseMutatorContext
+ BaseModuleContext
// AddDependency adds a dependency to the given module. It returns a slice of modules for each
// dependency (some entries may be nil).
//
- // If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
- // new dependencies have had the current mutator called on them. If the mutator is not
- // parallel this method does not affect the ordering of the current mutator pass, but will
- // be ordered correctly for all future mutator passes.
+ // This method will pause until the new dependencies have had the current mutator called on them.
AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module
// AddReverseDependency adds a dependency from the destination to the given module.
// Does not affect the ordering of the current mutator pass, but will be ordered
// correctly for all future mutator passes. All reverse dependencies for a destination module are
// collected until the end of the mutator pass, sorted by name, and then appended to the destination
- // module's dependency list.
+ // module's dependency list. May only be called by mutators that were marked with
+ // UsesReverseDependencies during registration.
AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string)
// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations
@@ -244,20 +227,18 @@
// each dependency (some entries may be nil). A variant of the dependency must exist that matches
// all the non-local variations of the current module, plus the variations argument.
//
- // If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
- // new dependencies have had the current mutator called on them. If the mutator is not
- // parallel this method does not affect the ordering of the current mutator pass, but will
- // be ordered correctly for all future mutator passes.
+ // This method will pause until the new dependencies have had the current mutator called on them.
AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag, names ...string) []blueprint.Module
- // AddReverseVariationDependencies adds a dependency from the named module to the current
+ // AddReverseVariationDependency adds a dependency from the named module to the current
// module. The given variations will be added to the current module's varations, and then the
// result will be used to find the correct variation of the depending module, which must exist.
//
// Does not affect the ordering of the current mutator pass, but will be ordered
// correctly for all future mutator passes. All reverse dependencies for a destination module are
// collected until the end of the mutator pass, sorted by name, and then appended to the destination
- // module's dependency list.
+ // module's dependency list. May only be called by mutators that were marked with
+ // UsesReverseDependencies during registration.
AddReverseVariationDependency([]blueprint.Variation, blueprint.DependencyTag, string)
// AddFarVariationDependencies adds deps as dependencies of the current module, but uses the
@@ -269,22 +250,31 @@
// Unlike AddVariationDependencies, the variations of the current module are ignored - the
// dependency only needs to match the supplied variations.
//
- // If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
- // new dependencies have had the current mutator called on them. If the mutator is not
- // parallel this method does not affect the ordering of the current mutator pass, but will
- // be ordered correctly for all future mutator passes.
+ // This method will pause until the new dependencies have had the current mutator called on them.
AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) []blueprint.Module
// ReplaceDependencies finds all the variants of the module with the specified name, then
// replaces all dependencies onto those variants with the current variant of this module.
- // Replacements don't take effect until after the mutator pass is finished.
+ // Replacements don't take effect until after the mutator pass is finished. May only
+ // be called by mutators that were marked with UsesReplaceDependencies during registration.
ReplaceDependencies(string)
// ReplaceDependenciesIf finds all the variants of the module with the specified name, then
// replaces all dependencies onto those variants with the current variant of this module
// as long as the supplied predicate returns true.
- // Replacements don't take effect until after the mutator pass is finished.
+ // Replacements don't take effect until after the mutator pass is finished. May only
+ // be called by mutators that were marked with UsesReplaceDependencies during registration.
ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate)
+
+ // Rename all variants of a module. The new name is not visible to calls to ModuleName,
+ // AddDependency or OtherModuleName until after this mutator pass is complete. May only be called
+ // by mutators that were marked with UsesRename during registration.
+ Rename(name string)
+
+ // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
+ // the specified property structs to it as if the properties were set in a blueprint file. May only
+ // be called by mutators that were marked with UsesCreateModule during registration.
+ CreateModule(ModuleFactory, ...interface{}) Module
}
// An outgoingTransitionContextImpl and incomingTransitionContextImpl is created for every dependency of every module
@@ -627,22 +617,96 @@
} else if mutator.transitionMutator != nil {
blueprintCtx.RegisterTransitionMutator(mutator.name, mutator.transitionMutator)
}
- if mutator.parallel {
- handle.Parallel()
+
+ // Forward booleans set on the MutatorHandle to the blueprint.MutatorHandle.
+ if mutator.usesRename {
+ handle.UsesRename()
+ }
+ if mutator.usesReverseDependencies {
+ handle.UsesReverseDependencies()
+ }
+ if mutator.usesReplaceDependencies {
+ handle.UsesReplaceDependencies()
+ }
+ if mutator.usesCreateModule {
+ handle.UsesCreateModule()
+ }
+ if mutator.mutatesDependencies {
+ handle.MutatesDependencies()
+ }
+ if mutator.mutatesGlobalState {
+ handle.MutatesGlobalState()
}
}
type MutatorHandle interface {
+ // Parallel sets the mutator to visit modules in parallel while maintaining ordering. Calling any
+ // method on the mutator context is thread-safe, but the mutator must handle synchronization
+ // for any modifications to global state or any modules outside the one it was invoked on.
+ // Deprecated: all Mutators are parallel by default.
Parallel() MutatorHandle
+
+ // UsesRename marks the mutator as using the BottomUpMutatorContext.Rename method, which prevents
+ // coalescing adjacent mutators into a single mutator pass.
+ UsesRename() MutatorHandle
+
+ // UsesReverseDependencies marks the mutator as using the BottomUpMutatorContext.AddReverseDependency
+ // method, which prevents coalescing adjacent mutators into a single mutator pass.
+ UsesReverseDependencies() MutatorHandle
+
+ // UsesReplaceDependencies marks the mutator as using the BottomUpMutatorContext.ReplaceDependencies
+ // method, which prevents coalescing adjacent mutators into a single mutator pass.
+ UsesReplaceDependencies() MutatorHandle
+
+ // UsesCreateModule marks the mutator as using the BottomUpMutatorContext.CreateModule method,
+ // which prevents coalescing adjacent mutators into a single mutator pass.
+ UsesCreateModule() MutatorHandle
+
+ // MutatesDependencies marks the mutator as modifying properties in dependencies, which prevents
+ // coalescing adjacent mutators into a single mutator pass.
+ MutatesDependencies() MutatorHandle
+
+ // MutatesGlobalState marks the mutator as modifying global state, which prevents coalescing
+ // adjacent mutators into a single mutator pass.
+ MutatesGlobalState() MutatorHandle
}
func (mutator *mutator) Parallel() MutatorHandle {
- mutator.parallel = true
+ return mutator
+}
+
+func (mutator *mutator) UsesRename() MutatorHandle {
+ mutator.usesRename = true
+ return mutator
+}
+
+func (mutator *mutator) UsesReverseDependencies() MutatorHandle {
+ mutator.usesReverseDependencies = true
+ return mutator
+}
+
+func (mutator *mutator) UsesReplaceDependencies() MutatorHandle {
+ mutator.usesReplaceDependencies = true
+ return mutator
+}
+
+func (mutator *mutator) UsesCreateModule() MutatorHandle {
+ mutator.usesCreateModule = true
+ return mutator
+}
+
+func (mutator *mutator) MutatesDependencies() MutatorHandle {
+ mutator.mutatesDependencies = true
+ return mutator
+}
+
+func (mutator *mutator) MutatesGlobalState() MutatorHandle {
+ mutator.mutatesGlobalState = true
return mutator
}
func RegisterComponentsMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("component-deps", componentDepsMutator).Parallel()
+ ctx.BottomUp("component-deps", componentDepsMutator)
}
// A special mutator that runs just prior to the deps mutator to allow the dependencies
@@ -660,7 +724,7 @@
}
func registerDepsMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("deps", depsMutator).Parallel()
+ ctx.BottomUp("deps", depsMutator).UsesReverseDependencies()
}
// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that
@@ -669,32 +733,6 @@
// non-overridden method has to be forwarded. There are fewer non-overridden methods, so use the latter. The following
// methods forward to the identical blueprint versions for topDownMutatorContext and bottomUpMutatorContext.
-func (t *topDownMutatorContext) MutatorName() string {
- return t.bp.MutatorName()
-}
-
-func (t *topDownMutatorContext) Rename(name string) {
- t.bp.Rename(name)
- t.Module().base().commonProperties.DebugName = name
-}
-
-func (t *topDownMutatorContext) createModule(factory blueprint.ModuleFactory, name string, props ...interface{}) blueprint.Module {
- return t.bp.CreateModule(factory, name, props...)
-}
-
-func (t *topDownMutatorContext) CreateModule(factory ModuleFactory, props ...interface{}) Module {
- return createModule(t, factory, "_topDownMutatorModule", props...)
-}
-
-func (t *topDownMutatorContext) createModuleWithoutInheritance(factory ModuleFactory, props ...interface{}) Module {
- module := t.bp.CreateModule(ModuleFactoryAdaptor(factory), "", props...).(Module)
- return module
-}
-
-func (b *bottomUpMutatorContext) MutatorName() string {
- return b.bp.MutatorName()
-}
-
func (b *bottomUpMutatorContext) Rename(name string) {
b.bp.Rename(name)
b.Module().base().commonProperties.DebugName = name
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 5d4074a..1d5f890 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -17,6 +17,8 @@
import (
"fmt"
"strings"
+ "sync"
+ "sync/atomic"
"testing"
"github.com/google/blueprint"
@@ -134,10 +136,6 @@
return []string{"a", "b"}
},
})
- ctx.TopDown("rename_top_down", func(ctx TopDownMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.Rename(ctx.Module().base().Name() + "_renamed1")
- })
})
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
@@ -161,8 +159,8 @@
})
ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.Rename(ctx.Module().base().Name() + "_renamed2")
- })
+ ctx.Rename(ctx.Module().base().Name() + "_renamed1")
+ }).UsesRename()
ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
moduleStrings = append(moduleStrings, ctx.Module().String())
})
@@ -181,17 +179,23 @@
"foo{pre_arch:b}",
"foo{pre_arch:a}",
- // After rename_top_down (reversed because pre_deps TransitionMutator.Split is TopDown).
- "foo_renamed1{pre_arch:b}",
- "foo_renamed1{pre_arch:a}",
-
// After pre_deps (reversed because post_deps TransitionMutator.Split is TopDown).
- "foo_renamed1{pre_arch:b,pre_deps:d}",
- "foo_renamed1{pre_arch:b,pre_deps:c}",
- "foo_renamed1{pre_arch:a,pre_deps:d}",
- "foo_renamed1{pre_arch:a,pre_deps:c}",
+ "foo{pre_arch:b,pre_deps:d}",
+ "foo{pre_arch:b,pre_deps:c}",
+ "foo{pre_arch:a,pre_deps:d}",
+ "foo{pre_arch:a,pre_deps:c}",
// After post_deps.
+ "foo{pre_arch:a,pre_deps:c,post_deps:e}",
+ "foo{pre_arch:a,pre_deps:c,post_deps:f}",
+ "foo{pre_arch:a,pre_deps:d,post_deps:e}",
+ "foo{pre_arch:a,pre_deps:d,post_deps:f}",
+ "foo{pre_arch:b,pre_deps:c,post_deps:e}",
+ "foo{pre_arch:b,pre_deps:c,post_deps:f}",
+ "foo{pre_arch:b,pre_deps:d,post_deps:e}",
+ "foo{pre_arch:b,pre_deps:d,post_deps:f}",
+
+ // After rename_bottom_up.
"foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}",
"foo_renamed1{pre_arch:a,pre_deps:c,post_deps:f}",
"foo_renamed1{pre_arch:a,pre_deps:d,post_deps:e}",
@@ -200,16 +204,6 @@
"foo_renamed1{pre_arch:b,pre_deps:c,post_deps:f}",
"foo_renamed1{pre_arch:b,pre_deps:d,post_deps:e}",
"foo_renamed1{pre_arch:b,pre_deps:d,post_deps:f}",
-
- // After rename_bottom_up.
- "foo_renamed2{pre_arch:a,pre_deps:c,post_deps:e}",
- "foo_renamed2{pre_arch:a,pre_deps:c,post_deps:f}",
- "foo_renamed2{pre_arch:a,pre_deps:d,post_deps:e}",
- "foo_renamed2{pre_arch:a,pre_deps:d,post_deps:f}",
- "foo_renamed2{pre_arch:b,pre_deps:c,post_deps:e}",
- "foo_renamed2{pre_arch:b,pre_deps:c,post_deps:f}",
- "foo_renamed2{pre_arch:b,pre_deps:d,post_deps:e}",
- "foo_renamed2{pre_arch:b,pre_deps:d,post_deps:f}",
}
AssertDeepEquals(t, "module String() values", want, moduleStrings)
@@ -228,7 +222,7 @@
}
`
- finalGot := map[string]int{}
+ finalGot := sync.Map{}
GroupFixturePreparers(
FixtureRegisterWithContext(func(ctx RegistrationContext) {
@@ -259,9 +253,11 @@
}
})
ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
- finalGot[ctx.Module().String()] += 1
+ counter, _ := finalGot.LoadOrStore(ctx.Module().String(), &atomic.Int64{})
+ counter.(*atomic.Int64).Add(1)
ctx.VisitDirectDeps(func(mod Module) {
- finalGot[fmt.Sprintf("%s -> %s", ctx.Module().String(), mod)] += 1
+ counter, _ := finalGot.LoadOrStore(fmt.Sprintf("%s -> %s", ctx.Module().String(), mod), &atomic.Int64{})
+ counter.(*atomic.Int64).Add(1)
})
})
})
@@ -284,7 +280,13 @@
"foo{variant:b} -> common_dep_2{variant:a}": 1,
}
- AssertDeepEquals(t, "final", finalWant, finalGot)
+ finalGotMap := make(map[string]int)
+ finalGot.Range(func(k, v any) bool {
+ finalGotMap[k.(string)] = int(v.(*atomic.Int64).Load())
+ return true
+ })
+
+ AssertDeepEquals(t, "final", finalWant, finalGotMap)
}
func TestTransitionMutatorInFinalDeps(t *testing.T) {
diff --git a/android/namespace.go b/android/namespace.go
index ebf85a1..8b3ebc4 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -457,7 +457,7 @@
}
func RegisterNamespaceMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("namespace_deps", namespaceMutator).Parallel()
+ ctx.BottomUp("namespace_deps", namespaceMutator).MutatesGlobalState()
}
func namespaceMutator(ctx BottomUpMutatorContext) {
diff --git a/android/namespace_test.go b/android/namespace_test.go
index ea51c6e..0327e78 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -646,7 +646,7 @@
ctx.RegisterModuleType("test_module", newTestModule)
ctx.Context.RegisterModuleType("blueprint_test_module", newBlueprintTestModule)
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("rename", renameMutator)
+ ctx.BottomUp("rename", renameMutator).UsesRename()
})
}),
)
@@ -709,9 +709,6 @@
}
func (m *testModule) DepsMutator(ctx BottomUpMutatorContext) {
- if m.properties.Rename != "" {
- ctx.Rename(m.properties.Rename)
- }
for _, d := range m.properties.Deps {
ctx.AddDependency(ctx.Module(), nil, d)
}
diff --git a/android/neverallow.go b/android/neverallow.go
index e135f57..57373d5 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -44,7 +44,7 @@
// - it has none of the "Without" properties matched (same rules as above)
func registerNeverallowMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("neverallow", neverallowMutator).Parallel()
+ ctx.BottomUp("neverallow", neverallowMutator)
}
var neverallows = []Rule{}
@@ -60,6 +60,9 @@
AddNeverAllowRules(createCcStubsRule())
AddNeverAllowRules(createProhibitHeaderOnlyRule())
AddNeverAllowRules(createLimitNdkExportRule()...)
+ AddNeverAllowRules(createLimitDirgroupRule()...)
+ AddNeverAllowRules(createFilesystemIsAutoGeneratedRule())
+ AddNeverAllowRules(createKotlinPluginRule()...)
}
// Add a NeverAllow rule to the set of rules to apply.
@@ -275,6 +278,47 @@
}
}
+func createLimitDirgroupRule() []Rule {
+ reason := "dirgroup module and dir_srcs property of genrule is allowed only to Trusty build rule."
+ return []Rule{
+ NeverAllow().
+ ModuleType("dirgroup").
+ WithMatcher("visibility", NotInList([]string{"//trusty/vendor/google/aosp/scripts"})).Because(reason),
+ NeverAllow().
+ ModuleType("dirgroup").
+ Without("visibility", "//trusty/vendor/google/aosp/scripts").Because(reason),
+ NeverAllow().
+ ModuleType("genrule").
+ Without("name", "lk.elf.arm64").
+ Without("name", "lk.elf.x86_64").
+ WithMatcher("dir_srcs", isSetMatcherInstance).Because(reason),
+ }
+}
+
+func createFilesystemIsAutoGeneratedRule() Rule {
+ return NeverAllow().
+ NotIn("build/soong/fsgen").
+ ModuleType("filesystem", "android_system_image").
+ WithMatcher("is_auto_generated", isSetMatcherInstance).
+ Because("is_auto_generated property is only allowed for filesystem modules in build/soong/fsgen directory")
+}
+
+func createKotlinPluginRule() []Rule {
+ kotlinPluginProjectsAllowedList := []string{
+ // TODO: Migrate compose plugin to the bundled compiler plugin
+ // Actual path prebuilts/sdk/current/androidx/m2repository/androidx/compose/compiler/compiler-hosted
+ "prebuilts/sdk/current/androidx",
+ "external/kotlinc",
+ }
+
+ return []Rule{
+ NeverAllow().
+ NotIn(kotlinPluginProjectsAllowedList...).
+ ModuleType("kotlin_plugin").
+ Because("kotlin_plugin can only be used in allowed projects"),
+ }
+}
+
func neverallowMutator(ctx BottomUpMutatorContext) {
m, ok := ctx.Module().(Module)
if !ok {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 192c924..caec8c7 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -359,6 +359,21 @@
`headers_only can only be used for generating framework-minus-apex headers for non-updatable modules`,
},
},
+ // Test for the rule restricting use of is_auto_generated
+ {
+ name: `"is_auto_generated" outside allowed directory`,
+ fs: map[string][]byte{
+ "a/b/Android.bp": []byte(`
+ filesystem {
+ name: "baaz",
+ is_auto_generated: true,
+ }
+ `),
+ },
+ expectedErrors: []string{
+ `is_auto_generated property is only allowed for filesystem modules in build/soong/fsgen directory`,
+ },
+ },
}
var prepareForNeverAllowTest = GroupFixturePreparers(
@@ -367,6 +382,7 @@
ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
+ ctx.RegisterModuleType("filesystem", newMockFilesystemModule)
}),
)
diff --git a/android/override_module.go b/android/override_module.go
index f69f963..50ddc9b 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -234,17 +234,18 @@
// Mutators for override/overridable modules. All the fun happens in these functions. It is critical
// to keep them in this order and not put any order mutators between them.
func RegisterOverridePostDepsMutators(ctx RegisterMutatorsContext) {
- ctx.BottomUp("override_deps", overrideModuleDepsMutator).Parallel()
+ ctx.BottomUp("override_deps", overrideModuleDepsMutator).MutatesDependencies() // modifies deps via addOverride
ctx.Transition("override", &overrideTransitionMutator{})
+ ctx.BottomUp("override_apply", overrideApplyMutator).MutatesDependencies()
// overridableModuleDepsMutator calls OverridablePropertiesDepsMutator so that overridable modules can
// add deps from overridable properties.
- ctx.BottomUp("overridable_deps", overridableModuleDepsMutator).Parallel()
+ ctx.BottomUp("overridable_deps", overridableModuleDepsMutator)
// Because overridableModuleDepsMutator is run after PrebuiltPostDepsMutator,
// prebuilt's ReplaceDependencies doesn't affect to those deps added by overridable properties.
// By running PrebuiltPostDepsMutator again after overridableModuleDepsMutator, deps via overridable properties
// can be replaced with prebuilts.
- ctx.BottomUp("replace_deps_on_prebuilts_for_overridable_deps_again", PrebuiltPostDepsMutator).Parallel()
- ctx.BottomUp("replace_deps_on_override", replaceDepsOnOverridingModuleMutator).Parallel()
+ ctx.BottomUp("replace_deps_on_prebuilts_for_overridable_deps_again", PrebuiltPostDepsMutator).UsesReplaceDependencies()
+ ctx.BottomUp("replace_deps_on_override", replaceDepsOnOverridingModuleMutator).UsesReplaceDependencies()
}
type overrideBaseDependencyTag struct {
@@ -330,6 +331,9 @@
}
func (overrideTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
+}
+
+func overrideApplyMutator(ctx BottomUpMutatorContext) {
if o, ok := ctx.Module().(OverrideModule); ok {
overridableDeps := ctx.GetDirectDepsWithTag(overrideBaseDepTag)
if len(overridableDeps) > 1 {
diff --git a/android/packaging.go b/android/packaging.go
index 3c64d56..b505964 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -65,30 +65,32 @@
}
type packagingSpecGob struct {
- RelPathInPackage string
- SrcPath Path
- SymlinkTarget string
- Executable bool
- Partition string
- SkipInstall bool
- AconfigPaths *Paths
- ArchType ArchType
- Overrides *[]string
- Owner string
+ RelPathInPackage string
+ SrcPath Path
+ SymlinkTarget string
+ Executable bool
+ EffectiveLicenseFiles *Paths
+ Partition string
+ SkipInstall bool
+ AconfigPaths *Paths
+ ArchType ArchType
+ Overrides *[]string
+ Owner string
}
func (p *PackagingSpec) ToGob() *packagingSpecGob {
return &packagingSpecGob{
- RelPathInPackage: p.relPathInPackage,
- SrcPath: p.srcPath,
- SymlinkTarget: p.symlinkTarget,
- Executable: p.executable,
- Partition: p.partition,
- SkipInstall: p.skipInstall,
- AconfigPaths: p.aconfigPaths,
- ArchType: p.archType,
- Overrides: p.overrides,
- Owner: p.owner,
+ RelPathInPackage: p.relPathInPackage,
+ SrcPath: p.srcPath,
+ SymlinkTarget: p.symlinkTarget,
+ Executable: p.executable,
+ EffectiveLicenseFiles: p.effectiveLicenseFiles,
+ Partition: p.partition,
+ SkipInstall: p.skipInstall,
+ AconfigPaths: p.aconfigPaths,
+ ArchType: p.archType,
+ Overrides: p.overrides,
+ Owner: p.owner,
}
}
@@ -97,6 +99,7 @@
p.srcPath = data.SrcPath
p.symlinkTarget = data.SymlinkTarget
p.executable = data.Executable
+ p.effectiveLicenseFiles = data.EffectiveLicenseFiles
p.partition = data.Partition
p.skipInstall = data.SkipInstall
p.aconfigPaths = data.AconfigPaths
@@ -374,7 +377,17 @@
if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
continue
}
- ctx.AddFarVariationDependencies(t.Variations(), depTag, dep)
+ targetVariation := t.Variations()
+ sharedVariation := blueprint.Variation{
+ Mutator: "link",
+ Variation: "shared",
+ }
+ // If a shared variation exists, use that. Static variants do not provide any standalone files
+ // for packaging.
+ if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) {
+ targetVariation = append(targetVariation, sharedVariation)
+ }
+ ctx.AddFarVariationDependencies(targetVariation, depTag, dep)
}
}
}
diff --git a/android/packaging_test.go b/android/packaging_test.go
index f5b1020..9c6760c 100644
--- a/android/packaging_test.go
+++ b/android/packaging_test.go
@@ -64,7 +64,7 @@
ModuleBase
PackagingBase
properties struct {
- Install_deps []string `android:`
+ Install_deps []string
}
entries []string
}
diff --git a/android/path_properties.go b/android/path_properties.go
index 6210aee..8ada133 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -18,6 +18,7 @@
"fmt"
"reflect"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -27,7 +28,7 @@
// to the output file of the referenced module.
func registerPathDepsMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("pathdeps", pathDepsMutator).Parallel()
+ ctx.BottomUp("pathdeps", pathDepsMutator)
}
// The pathDepsMutator automatically adds dependencies on any module that is listed with the
@@ -38,20 +39,32 @@
// squashed into the real modules.
return
}
+ if !ctx.Module().Enabled(ctx) {
+ return
+ }
props := ctx.Module().base().GetProperties()
addPathDepsForProps(ctx, props)
}
func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) {
// Iterate through each property struct of the module extracting the contents of all properties
- // tagged with `android:"path"`.
+ // tagged with `android:"path"` or one of the variant-specifying tags.
var pathProperties []string
+ var pathDeviceFirstProperties []string
+ var pathDeviceCommonProperties []string
+ var pathCommonOsProperties []string
for _, ps := range props {
- pathProperties = append(pathProperties, pathPropertiesForPropertyStruct(ctx, ps)...)
+ pathProperties = append(pathProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path")...)
+ pathDeviceFirstProperties = append(pathDeviceFirstProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first")...)
+ pathDeviceCommonProperties = append(pathDeviceCommonProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_common")...)
+ pathCommonOsProperties = append(pathCommonOsProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_common_os")...)
}
// Remove duplicates to avoid multiple dependencies.
pathProperties = FirstUniqueStrings(pathProperties)
+ pathDeviceFirstProperties = FirstUniqueStrings(pathDeviceFirstProperties)
+ pathDeviceCommonProperties = FirstUniqueStrings(pathDeviceCommonProperties)
+ pathCommonOsProperties = FirstUniqueStrings(pathCommonOsProperties)
// Add dependencies to anything that is a module reference.
for _, s := range pathProperties {
@@ -59,12 +72,35 @@
ctx.AddDependency(ctx.Module(), sourceOrOutputDepTag(m, t), m)
}
}
+ // For properties tagged "path_device_first", use the first arch device variant when adding
+ // dependencies. This allows host modules to have some properties that add dependencies on
+ // device modules.
+ for _, s := range pathDeviceFirstProperties {
+ if m, t := SrcIsModuleWithTag(s); m != "" {
+ ctx.AddVariationDependencies(ctx.Config().AndroidFirstDeviceTarget.Variations(), sourceOrOutputDepTag(m, t), m)
+ }
+ }
+ // properties tagged "path_device_common" get the device common variant
+ for _, s := range pathDeviceCommonProperties {
+ if m, t := SrcIsModuleWithTag(s); m != "" {
+ ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), sourceOrOutputDepTag(m, t), m)
+ }
+ }
+ // properties tagged "path_device_common" get the device common variant
+ for _, s := range pathCommonOsProperties {
+ if m, t := SrcIsModuleWithTag(s); m != "" {
+ ctx.AddVariationDependencies([]blueprint.Variation{
+ {Mutator: "os", Variation: "common_os"},
+ {Mutator: "arch", Variation: ""},
+ }, sourceOrOutputDepTag(m, t), m)
+ }
+ }
}
-// pathPropertiesForPropertyStruct uses the indexes of properties that are tagged with
-// android:"path" to extract all their values from a property struct, returning them as a single
+// taggedPropertiesForPropertyStruct uses the indexes of properties that are tagged with
+// android:"tagValue" to extract all their values from a property struct, returning them as a single
// slice of strings.
-func pathPropertiesForPropertyStruct(ctx BottomUpMutatorContext, ps interface{}) []string {
+func taggedPropertiesForPropertyStruct(ctx BottomUpMutatorContext, ps interface{}, tagValue string) []string {
v := reflect.ValueOf(ps)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
panic(fmt.Errorf("type %s is not a pointer to a struct", v.Type()))
@@ -79,7 +115,7 @@
v = v.Elem()
// Get or create the list of indexes of properties that are tagged with `android:"path"`.
- pathPropertyIndexes := pathPropertyIndexesForPropertyStruct(ps)
+ pathPropertyIndexes := taggedPropertyIndexesForPropertyStruct(ps, tagValue)
var ret []string
@@ -172,12 +208,20 @@
var pathPropertyIndexesCache OncePer
-// pathPropertyIndexesForPropertyStruct returns a list of all of the indexes of properties in
-// property struct type that are tagged with `android:"path"`. Each index is a []int suitable for
-// passing to reflect.Value.FieldByIndex. The value is cached in a global cache by type.
-func pathPropertyIndexesForPropertyStruct(ps interface{}) [][]int {
- key := NewCustomOnceKey(reflect.TypeOf(ps))
+// taggedPropertyIndexesForPropertyStruct returns a list of all of the indexes of properties in
+// property struct type that are tagged with `android:"tagValue"`. Each index is a []int suitable
+// for passing to reflect.Value.FieldByIndex. The value is cached in a global cache by type and
+// tagValue.
+func taggedPropertyIndexesForPropertyStruct(ps interface{}, tagValue string) [][]int {
+ type pathPropertyIndexesOnceKey struct {
+ propStructType reflect.Type
+ tagValue string
+ }
+ key := NewCustomOnceKey(pathPropertyIndexesOnceKey{
+ propStructType: reflect.TypeOf(ps),
+ tagValue: tagValue,
+ })
return pathPropertyIndexesCache.Once(key, func() interface{} {
- return proptools.PropertyIndexesWithTag(ps, "android", "path")
+ return proptools.PropertyIndexesWithTag(ps, "android", tagValue)
}).([][]int)
}
diff --git a/android/paths.go b/android/paths.go
index 9c2df65..371aed8 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -550,6 +550,58 @@
return ret
}
+// DirectoryPathsForModuleSrcExcludes returns a Paths{} containing the resolved references in
+// directory paths. Elements of paths are resolved as:
+// - filepath, relative to local module directory, resolves as a filepath relative to the local
+// source directory
+// - other modules using the ":name" syntax. These modules must implement DirProvider.
+//
+// TODO(b/358302178): Implement DirectoryPath and change the return type.
+func DirectoryPathsForModuleSrc(ctx ModuleMissingDepsPathContext, paths []string) Paths {
+ var ret Paths
+
+ for _, path := range paths {
+ if m, t := SrcIsModuleWithTag(path); m != "" {
+ module := GetModuleFromPathDep(ctx, m, t)
+ if module == nil {
+ ctx.ModuleErrorf(`missing dependency on %q, is the property annotated with android:"path"?`, m)
+ continue
+ }
+ if t != "" {
+ ctx.ModuleErrorf("DirProvider dependency %q does not support the tag %q", module, t)
+ continue
+ }
+ mctx, ok := ctx.(OtherModuleProviderContext)
+ if !ok {
+ panic(fmt.Errorf("%s is not an OtherModuleProviderContext", ctx))
+ }
+ if dirProvider, ok := OtherModuleProvider(mctx, module, DirProvider); ok {
+ ret = append(ret, dirProvider.Dirs...)
+ } else {
+ ReportPathErrorf(ctx, "module %q does not implement DirProvider", module)
+ }
+ } else {
+ p := pathForModuleSrc(ctx, path)
+ if isDir, err := ctx.Config().fs.IsDir(p.String()); err != nil {
+ ReportPathErrorf(ctx, "%s: %s", p, err.Error())
+ } else if !isDir {
+ ReportPathErrorf(ctx, "module directory path %q is not a directory", p)
+ } else {
+ ret = append(ret, p)
+ }
+ }
+ }
+
+ seen := make(map[Path]bool, len(ret))
+ for _, path := range ret {
+ if seen[path] {
+ ReportPathErrorf(ctx, "duplicated path %q", path)
+ }
+ seen[path] = true
+ }
+ return ret
+}
+
// OutputPaths is a slice of OutputPath objects, with helpers to operate on the collection.
type OutputPaths []OutputPath
@@ -1363,21 +1415,21 @@
}
type outputPathGob struct {
- basePath
+ BasePath basePath
OutDir string
FullPath string
}
func (p *OutputPath) ToGob() *outputPathGob {
return &outputPathGob{
- basePath: p.basePath,
+ BasePath: p.basePath,
OutDir: p.outDir,
FullPath: p.fullPath,
}
}
func (p *OutputPath) FromGob(data *outputPathGob) {
- p.basePath = data.basePath
+ p.basePath = data.BasePath
p.outDir = data.OutDir
p.fullPath = data.FullPath
}
@@ -1788,7 +1840,7 @@
}
type installPathGob struct {
- basePath
+ BasePath basePath
SoongOutDir string
PartitionDir string
Partition string
@@ -1798,7 +1850,7 @@
func (p *InstallPath) ToGob() *installPathGob {
return &installPathGob{
- basePath: p.basePath,
+ BasePath: p.basePath,
SoongOutDir: p.soongOutDir,
PartitionDir: p.partitionDir,
Partition: p.partition,
@@ -1808,7 +1860,7 @@
}
func (p *InstallPath) FromGob(data *installPathGob) {
- p.basePath = data.basePath
+ p.basePath = data.BasePath
p.soongOutDir = data.SoongOutDir
p.partitionDir = data.PartitionDir
p.partition = data.Partition
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 4f04d05..5d75b62 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -272,6 +272,25 @@
InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
}
+// InitConfigurablePrebuiltModuleString is the same as InitPrebuiltModule, but uses a
+// Configurable string property instead of a regular list of strings. It only produces a single
+// source file.
+func InitConfigurablePrebuiltModuleString(module PrebuiltInterface, srcs *proptools.Configurable[string], propertyName string) {
+ if srcs == nil {
+ panic(fmt.Errorf("%s must not be nil", propertyName))
+ }
+
+ srcsSupplier := func(ctx BaseModuleContext, _ Module) []string {
+ src := srcs.GetOrDefault(ctx, "")
+ if src == "" {
+ return nil
+ }
+ return []string{src}
+ }
+
+ InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, propertyName)
+}
+
func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) {
srcPropsValue := reflect.ValueOf(srcProps).Elem()
srcStructField, _ := srcPropsValue.Type().FieldByName(srcField)
@@ -362,10 +381,10 @@
// the right module. This function is only safe to call after all TransitionMutators
// have run, e.g. in GenerateAndroidBuildActions.
func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module {
- if !module.IsReplacedByPrebuilt() {
+ if !OtherModuleProviderOrDefault(ctx, module, CommonPropertiesProviderKey).ReplacedByPrebuilt {
return module
}
- if IsModulePrebuilt(module) {
+ if _, ok := OtherModuleProvider(ctx, module, PrebuiltModuleProviderKey); ok {
// If we're given a prebuilt then assume there's no source module around.
return module
}
@@ -373,11 +392,11 @@
sourceModDepFound := false
var prebuiltMod Module
- ctx.WalkDeps(func(child, parent Module) bool {
+ ctx.WalkDepsProxy(func(child, parent ModuleProxy) bool {
if prebuiltMod != nil {
return false
}
- if parent == ctx.Module() {
+ if ctx.EqualModules(parent, ctx.Module()) {
// First level: Only recurse if the module is found as a direct dependency.
sourceModDepFound = child == module
return sourceModDepFound
@@ -400,13 +419,13 @@
}
func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
- ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).Parallel()
+ ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).UsesRename()
}
func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
- ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).Parallel()
- ctx.BottomUp("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
- ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel()
+ ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).UsesReverseDependencies()
+ ctx.BottomUp("prebuilt_select", PrebuiltSelectModuleMutator)
+ ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).UsesReplaceDependencies()
}
// Returns the name of the source module corresponding to a prebuilt module
@@ -677,7 +696,7 @@
//
// Even though this is a cc_prebuilt_library_shared, we create both the variants today
// https://source.corp.google.com/h/googleplex-android/platform/build/soong/+/e08e32b45a18a77bc3c3e751f730539b1b374f1b:cc/library.go;l=2113-2116;drc=2c4a9779cd1921d0397a12b3d3521f4c9b30d747;bpv=1;bpt=0
-func (p *Prebuilt) variantIsDisabled(ctx BaseMutatorContext, prebuilt Module) bool {
+func (p *Prebuilt) variantIsDisabled(ctx BaseModuleContext, prebuilt Module) bool {
return p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0
}
@@ -687,7 +706,7 @@
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt
// will be used if it is marked "prefer" or if the source module is disabled.
-func (p *Prebuilt) usePrebuilt(ctx BaseMutatorContext, source Module, prebuilt Module) bool {
+func (p *Prebuilt) usePrebuilt(ctx BaseModuleContext, source Module, prebuilt Module) bool {
isMainlinePrebuilt := func(prebuilt Module) bool {
apex, ok := prebuilt.(apexVariationName)
if !ok {
diff --git a/android/product_config_to_bp.go b/android/product_config_to_bp.go
deleted file mode 100644
index 680328f..0000000
--- a/android/product_config_to_bp.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2024 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 android
-
-func init() {
- ctx := InitRegistrationContext
- ctx.RegisterParallelSingletonType("product_config_to_bp_singleton", productConfigToBpSingletonFactory)
-}
-
-type productConfigToBpSingleton struct{}
-
-func (s *productConfigToBpSingleton) GenerateBuildActions(ctx SingletonContext) {
- // TODO: update content from make-based product config
- var content string
- generatedBp := PathForOutput(ctx, "soong_generated_product_config.bp")
- WriteFileRule(ctx, generatedBp, content)
- ctx.Phony("product_config_to_bp", generatedBp)
-}
-
-// productConfigToBpSingleton generates a bp file from make-based product config
-func productConfigToBpSingletonFactory() Singleton {
- return &productConfigToBpSingleton{}
-}
diff --git a/android/proto.go b/android/proto.go
index 0d8e097..66faa20 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -74,14 +74,14 @@
flags = append(flags, JoinWithPrefix(rootProtoIncludeDirs.Strings(), "-I"))
}
- ctx.VisitDirectDepsWithTag(ProtoPluginDepTag, func(dep Module) {
- if hostTool, ok := dep.(HostToolProvider); !ok || !hostTool.HostToolPath().Valid() {
+ ctx.VisitDirectDepsProxyWithTag(ProtoPluginDepTag, func(dep ModuleProxy) {
+ if h, ok := OtherModuleProvider(ctx, dep, HostToolProviderKey); !ok || !h.HostToolPath.Valid() {
ctx.PropertyErrorf("proto.plugin", "module %q is not a host tool provider",
ctx.OtherModuleName(dep))
} else {
plugin := String(p.Proto.Plugin)
- deps = append(deps, hostTool.HostToolPath().Path())
- flags = append(flags, "--plugin=protoc-gen-"+plugin+"="+hostTool.HostToolPath().String())
+ deps = append(deps, h.HostToolPath.Path())
+ flags = append(flags, "--plugin=protoc-gen-"+plugin+"="+h.HostToolPath.String())
}
})
diff --git a/android/register.go b/android/register.go
index 2ce6025..bb1ead7 100644
--- a/android/register.go
+++ b/android/register.go
@@ -91,7 +91,13 @@
bottomUpMutator blueprint.BottomUpMutator
topDownMutator blueprint.TopDownMutator
transitionMutator blueprint.TransitionMutator
- parallel bool
+
+ usesRename bool
+ usesReverseDependencies bool
+ usesReplaceDependencies bool
+ usesCreateModule bool
+ mutatesDependencies bool
+ mutatesGlobalState bool
}
var _ sortableComponent = &mutator{}
diff --git a/android/variable.go b/android/variable.go
index 417ba89..13d5f05 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -29,7 +29,7 @@
func registerVariableBuildComponents(ctx RegistrationContext) {
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("variable", VariableMutator).Parallel()
+ ctx.BottomUp("variable", VariableMutator)
})
}
@@ -193,6 +193,9 @@
Required []string
Vintf_fragment_modules []string
}
+ SelinuxIgnoreNeverallows struct {
+ Required []string
+ }
} `android:"arch_variant"`
}
@@ -334,10 +337,12 @@
HWASanIncludePaths []string `json:",omitempty"`
HWASanExcludePaths []string `json:",omitempty"`
- VendorPath *string `json:",omitempty"`
- OdmPath *string `json:",omitempty"`
- ProductPath *string `json:",omitempty"`
- SystemExtPath *string `json:",omitempty"`
+ VendorPath *string `json:",omitempty"`
+ BuildingVendorImage *bool `json:",omitempty"`
+ OdmPath *string `json:",omitempty"`
+ ProductPath *string `json:",omitempty"`
+ BuildingProductImage *bool `json:",omitempty"`
+ SystemExtPath *string `json:",omitempty"`
ClangTidy *bool `json:",omitempty"`
TidyChecks *string `json:",omitempty"`
@@ -475,6 +480,8 @@
ProductManufacturer string `json:",omitempty"`
ProductBrand string `json:",omitempty"`
+ ProductDevice string `json:",omitempty"`
+ ProductModel string `json:",omitempty"`
ReleaseVersion string `json:",omitempty"`
ReleaseAconfigValueSets []string `json:",omitempty"`
diff --git a/android/vintf_fragment.go b/android/vintf_fragment.go
index 329eac9..42eaaf0 100644
--- a/android/vintf_fragment.go
+++ b/android/vintf_fragment.go
@@ -44,7 +44,7 @@
m.AddProperties(
&m.properties,
)
- InitAndroidArchModule(m, DeviceSupported, MultilibFirst)
+ InitAndroidArchModule(m, DeviceSupported, MultilibCommon)
return m
}
diff --git a/android/vintf_fragment_test.go b/android/vintf_fragment_test.go
index 8be534c..cd90b98 100644
--- a/android/vintf_fragment_test.go
+++ b/android/vintf_fragment_test.go
@@ -29,7 +29,7 @@
testResult := PrepareForTestWithAndroidBuildComponents.RunTestWithBp(t, bp)
- vintfFragmentBuild := testResult.TestContext.ModuleForTests("test_vintf_fragment", "android_arm64_armv8-a").Rule("assemble_vintf")
+ vintfFragmentBuild := testResult.TestContext.ModuleForTests("test_vintf_fragment", "android_common").Rule("assemble_vintf")
if !strings.Contains(vintfFragmentBuild.RuleParams.Command, "assemble_vintf") {
t.Errorf("Vintf_manifest build command does not process with assemble_vintf : " + vintfFragmentBuild.RuleParams.Command)
}
diff --git a/android/visibility.go b/android/visibility.go
index 61f2200..cee465e 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -268,7 +268,7 @@
// The rule checker needs to be registered before defaults expansion to correctly check that
// //visibility:xxx isn't combined with other packages in the same list in any one module.
func RegisterVisibilityRuleChecker(ctx RegisterMutatorsContext) {
- ctx.BottomUp("visibilityRuleChecker", visibilityRuleChecker).Parallel()
+ ctx.BottomUp("visibilityRuleChecker", visibilityRuleChecker)
}
// Registers the function that gathers the visibility rules for each module.
@@ -278,12 +278,12 @@
// the complete visibility lists from flat lists and after the package info is gathered to ensure
// that default_visibility is available.
func RegisterVisibilityRuleGatherer(ctx RegisterMutatorsContext) {
- ctx.BottomUp("visibilityRuleGatherer", visibilityRuleGatherer).Parallel()
+ ctx.BottomUp("visibilityRuleGatherer", visibilityRuleGatherer)
}
// This must be registered after the deps have been resolved.
func RegisterVisibilityRuleEnforcer(ctx RegisterMutatorsContext) {
- ctx.BottomUp("visibilityRuleEnforcer", visibilityRuleEnforcer).Parallel()
+ ctx.BottomUp("visibilityRuleEnforcer", visibilityRuleEnforcer)
}
// Checks the per-module visibility rule lists before defaults expansion.
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 1a2eeca..277be0f 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -2098,8 +2098,9 @@
}
type mockFilesystemModuleProperties struct {
- Partition_type *string
- Deps []string
+ Partition_type *string
+ Deps []string
+ Is_auto_generated *bool
}
type mockFilesystemModule struct {
diff --git a/androidmk/parser/parser_test.go b/androidmk/parser/parser_test.go
index e238f8b..21baf6b 100644
--- a/androidmk/parser/parser_test.go
+++ b/androidmk/parser/parser_test.go
@@ -142,7 +142,7 @@
t.Fatalf("Unexpected errors while parsing: %v", errs)
}
- if got[0].End() < got[len(got) -1].Pos() {
- t.Errorf("Rule's end (%d) is smaller than directive that inside of rule's start (%v)\n", got[0].End(), got[len(got) -1].Pos())
+ if got[0].End() < got[len(got)-1].Pos() {
+ t.Errorf("Rule's end (%d) is smaller than directive that inside of rule's start (%v)\n", got[0].End(), got[len(got)-1].Pos())
}
}
diff --git a/apex/apex.go b/apex/apex.go
index d3e7eee..30b16ee 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -55,20 +55,20 @@
}
func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
+ ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).UsesReverseDependencies()
}
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_info", apexInfoMutator).Parallel()
- ctx.BottomUp("apex_unique", apexUniqueVariationsMutator).Parallel()
- ctx.BottomUp("apex_test_for_deps", apexTestForDepsMutator).Parallel()
- ctx.BottomUp("apex_test_for", apexTestForMutator).Parallel()
+ ctx.TopDown("apex_info", apexInfoMutator)
+ ctx.BottomUp("apex_unique", apexUniqueVariationsMutator)
+ ctx.BottomUp("apex_test_for_deps", apexTestForDepsMutator)
+ ctx.BottomUp("apex_test_for", apexTestForMutator)
// Run mark_platform_availability before the apexMutator as the apexMutator needs to know whether
// it should create a platform variant.
- ctx.BottomUp("mark_platform_availability", markPlatformAvailability).Parallel()
+ ctx.BottomUp("mark_platform_availability", markPlatformAvailability)
ctx.Transition("apex", &apexTransitionMutator{})
- ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel()
- ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel()
+ ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).MutatesDependencies()
+ ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator)
}
type apexBundleProperties struct {
@@ -292,7 +292,7 @@
}
// Merge combines another ApexNativeDependencies into this one
-func (a *ResolvedApexNativeDependencies) Merge(ctx android.BaseMutatorContext, b ApexNativeDependencies) {
+func (a *ResolvedApexNativeDependencies) Merge(ctx android.BaseModuleContext, b ApexNativeDependencies) {
a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs.GetOrDefault(ctx, nil)...)
a.Jni_libs = append(a.Jni_libs, b.Jni_libs.GetOrDefault(ctx, nil)...)
a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 1d2f3fb..bf4158c 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -82,14 +82,6 @@
return files.AddToFixture()
}
-func withTargets(targets map[android.OsType][]android.Target) android.FixturePreparer {
- return android.FixtureModifyConfig(func(config android.Config) {
- for k, v := range targets {
- config.Targets[k] = v
- }
- })
-}
-
// withNativeBridgeTargets sets configuration with targets including:
// - X86_64 (primary)
// - X86 (secondary)
@@ -4051,11 +4043,20 @@
"libvndk27binder32.so": nil,
}),
withBinder32bit,
- withTargets(map[android.OsType][]android.Target{
- android.Android: {
- {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}},
- NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
- },
+ android.FixtureModifyConfig(func(config android.Config) {
+ target := android.Target{
+ Os: android.Android,
+ Arch: android.Arch{
+ ArchType: android.Arm,
+ ArchVariant: "armv7-a-neon",
+ Abi: []string{"armeabi-v7a"},
+ },
+ NativeBridge: android.NativeBridgeDisabled,
+ NativeBridgeHostArchName: "",
+ NativeBridgeRelativePath: "",
+ }
+ config.Targets[android.Android] = []android.Target{target}
+ config.AndroidFirstDeviceTarget = target
}),
)
@@ -11341,7 +11342,7 @@
}
filegroup {
name: "qux-filegroup",
- srcs: [
+ device_common_srcs: [
":qux-lib{.generated_srcjars}",
],
}
@@ -11860,3 +11861,42 @@
dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
)
}
+
+// partitions should not package the artifacts that are included inside the apex.
+func TestFilesystemWithApexDeps(t *testing.T) {
+ t.Parallel()
+ result := testApex(t, `
+ android_filesystem {
+ name: "myfilesystem",
+ deps: ["myapex"],
+ }
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ binaries: ["binfoo"],
+ native_shared_libs: ["libfoo"],
+ apps: ["appfoo"],
+ updatable: false,
+ }
+ apex_key {
+ name: "myapex.key",
+ }
+ cc_binary {
+ name: "binfoo",
+ apex_available: ["myapex"],
+ }
+ cc_library {
+ name: "libfoo",
+ apex_available: ["myapex"],
+ }
+ android_app {
+ name: "appfoo",
+ sdk_version: "current",
+ apex_available: ["myapex"],
+ }
+ `, filesystem.PrepareForTestWithFilesystemBuildComponents)
+
+ partition := result.ModuleForTests("myfilesystem", "android_common")
+ fileList := android.ContentFromFileRuleForTests(t, result, partition.Output("fileList"))
+ android.AssertDeepEquals(t, "filesystem with apex", "apex/myapex.apex\n", fileList)
+}
diff --git a/apex/builder.go b/apex/builder.go
index 371d7d5..20b4dbe 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -253,10 +253,10 @@
apexHostVerifierRule = pctx.StaticRule("apexHostVerifierRule", blueprint.RuleParams{
Command: `${host_apex_verifier} --deapexer=${deapexer} --debugfs=${debugfs_static} ` +
- `--fsckerofs=${fsck_erofs} --apex=${in} && touch ${out}`,
+ `--fsckerofs=${fsck_erofs} --apex=${in} --partition_tag=${partition_tag} && touch ${out}`,
CommandDeps: []string{"${host_apex_verifier}", "${deapexer}", "${debugfs_static}", "${fsck_erofs}"},
Description: "run host_apex_verifier",
- })
+ }, "partition_tag")
assembleVintfRule = pctx.StaticRule("assembleVintfRule", blueprint.RuleParams{
Command: `rm -f $out && VINTF_IGNORE_TARGET_FCM_VERSION=true ${assemble_vintf} -i $in -o $out`,
@@ -621,7 +621,8 @@
}
} else {
if installSymbolFiles {
- installedPath = ctx.InstallFile(apexDir.Join(ctx, fi.installDir), fi.stem(), fi.builtFile)
+ // store installedPath. symlinks might be created if required.
+ installedPath = apexDir.Join(ctx, fi.installDir, fi.stem())
}
}
@@ -976,7 +977,7 @@
runApexElfCheckerUnwanted(ctx, unsignedOutputFile.OutputPath, a.properties.Unwanted_transitive_deps))
}
if !a.testApex && android.InList(a.payloadFsType, []fsType{ext4, erofs}) {
- validations = append(validations, runApexHostVerifier(ctx, unsignedOutputFile.OutputPath))
+ validations = append(validations, runApexHostVerifier(ctx, a, unsignedOutputFile.OutputPath))
}
ctx.Build(pctx, android.BuildParams{
Rule: rule,
@@ -1287,12 +1288,15 @@
return timestamp
}
-func runApexHostVerifier(ctx android.ModuleContext, apexFile android.OutputPath) android.Path {
+func runApexHostVerifier(ctx android.ModuleContext, a *apexBundle, apexFile android.OutputPath) android.Path {
timestamp := android.PathForModuleOut(ctx, "host_apex_verifier.timestamp")
ctx.Build(pctx, android.BuildParams{
Rule: apexHostVerifierRule,
Input: apexFile,
Output: timestamp,
+ Args: map[string]string{
+ "partition_tag": a.PartitionTag(ctx.DeviceConfig()),
+ },
})
return timestamp
}
diff --git a/apex/vndk.go b/apex/vndk.go
index 5e630c0..d88808b 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -95,7 +95,11 @@
// level for the primary architecture.
a.Disable()
} else {
- mctx.AddDependency(mctx.Module(), prebuiltTag, cc.VndkLibrariesTxtModules(vndkVersion, mctx)...)
+ mctx.AddVariationDependencies(
+ mctx.Config().AndroidFirstDeviceTarget.Variations(),
+ prebuiltTag,
+ cc.VndkLibrariesTxtModules(vndkVersion, mctx)...,
+ )
}
}
}
diff --git a/bin/soongdbg b/bin/soongdbg
index 98d31eb..0807291 100755
--- a/bin/soongdbg
+++ b/bin/soongdbg
@@ -393,12 +393,42 @@
print(f" dep: {d.id}")
+class StarCommand:
+ help = "Print the dependencies and reverse dependencies of a module"
+
+ def args(self, parser):
+ parser.add_argument("module", nargs="+",
+ help="Module to print dependencies of")
+ parser.add_argument("--depth", type=int, required=True,
+ help="max depth of dependencies")
+ print_args(parser)
+
+ def run(self, args):
+ graph = load_graph()
+ nodes = set()
+ err = False
+ for id in args.module:
+ root = graph.nodes.get(id)
+ if not root:
+ sys.stderr.write(f"error: Can't find root: {id}\n")
+ err = True
+ continue
+ get_deps(nodes, root, args.depth, False, set(args.tag))
+ nodes.remove(root) # Remove it so get_deps doesn't bail out
+ get_deps(nodes, root, args.depth, True, set(args.tag))
+ if err:
+ sys.exit(1)
+ print_nodes(args, nodes, new_module_formatter(args))
+
+
+
COMMANDS = {
"between": BetweenCommand(),
"deps": DepsCommand(),
"id": IdCommand(),
"json": JsonCommand(),
"query": QueryCommand(),
+ "star": StarCommand(),
}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 8679821..3b7073e 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -109,41 +109,41 @@
var _ android.ImageInterface = (*bpf)(nil)
-func (bpf *bpf) ImageMutatorBegin(ctx android.BaseModuleContext) {}
+func (bpf *bpf) ImageMutatorBegin(ctx android.ImageInterfaceContext) {}
-func (bpf *bpf) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
+func (bpf *bpf) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
return proptools.Bool(bpf.properties.Vendor)
}
-func (bpf *bpf) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
+func (bpf *bpf) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (bpf *bpf) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+func (bpf *bpf) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
return !proptools.Bool(bpf.properties.Vendor)
}
-func (bpf *bpf) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (bpf *bpf) RamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (bpf *bpf) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (bpf *bpf) VendorRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (bpf *bpf) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (bpf *bpf) DebugRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (bpf *bpf) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+func (bpf *bpf) RecoveryVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (bpf *bpf) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+func (bpf *bpf) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
return nil
}
-func (bpf *bpf) SetImageVariation(ctx android.BaseModuleContext, variation string) {
+func (bpf *bpf) SetImageVariation(ctx android.ImageInterfaceContext, variation string) {
bpf.properties.VendorInternal = variation == "vendor"
}
diff --git a/bpf/libbpf/libbpf_prog.go b/bpf/libbpf/libbpf_prog.go
index ac61510..0ca7af1 100644
--- a/bpf/libbpf/libbpf_prog.go
+++ b/bpf/libbpf/libbpf_prog.go
@@ -104,41 +104,41 @@
var _ android.ImageInterface = (*libbpfProg)(nil)
-func (libbpf *libbpfProg) ImageMutatorBegin(ctx android.BaseModuleContext) {}
+func (libbpf *libbpfProg) ImageMutatorBegin(ctx android.ImageInterfaceContext) {}
-func (libbpf *libbpfProg) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
+func (libbpf *libbpfProg) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (libbpf *libbpfProg) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
+func (libbpf *libbpfProg) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (libbpf *libbpfProg) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+func (libbpf *libbpfProg) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
return true
}
-func (libbpf *libbpfProg) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (libbpf *libbpfProg) RamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (libbpf *libbpfProg) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (libbpf *libbpfProg) VendorRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (libbpf *libbpfProg) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (libbpf *libbpfProg) DebugRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (libbpf *libbpfProg) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+func (libbpf *libbpfProg) RecoveryVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (libbpf *libbpfProg) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+func (libbpf *libbpfProg) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
return nil
}
-func (libbpf *libbpfProg) SetImageVariation(ctx android.BaseModuleContext, variation string) {
+func (libbpf *libbpfProg) SetImageVariation(ctx android.ImageInterfaceContext, variation string) {
}
func (libbpf *libbpfProg) DepsMutator(ctx android.BottomUpMutatorContext) {
diff --git a/bpf/libbpf/libbpf_prog_test.go b/bpf/libbpf/libbpf_prog_test.go
index f4f5167..7f3653d 100644
--- a/bpf/libbpf/libbpf_prog_test.go
+++ b/bpf/libbpf/libbpf_prog_test.go
@@ -47,6 +47,7 @@
cc_test {
name: "vts_test_binary_bpf_module",
+ compile_multilib: "first",
srcs: ["BpfTest.cpp"],
data: [":bpf.o"],
gtest: false,
diff --git a/cc/Android.bp b/cc/Android.bp
index 88a793c..a5ad9ce 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -27,6 +27,7 @@
"builder.go",
"cc.go",
"ccdeps.go",
+ "cc_preprocess_no_configuration.go",
"check.go",
"coverage.go",
"gen.go",
@@ -88,6 +89,7 @@
testSrcs: [
"afdo_test.go",
"binary_test.go",
+ "cc_preprocess_no_configuration_test.go",
"cc_test.go",
"cc_test_only_property_test.go",
"cmake_snapshot_test.go",
diff --git a/cc/cc.go b/cc/cc.go
index 1b7624d..52bf669 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -48,10 +48,10 @@
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.Transition("sdk", &sdkTransitionMutator{})
- ctx.BottomUp("llndk", llndkMutator).Parallel()
+ ctx.BottomUp("llndk", llndkMutator)
ctx.Transition("link", &linkageTransitionMutator{})
ctx.Transition("version", &versionTransitionMutator{})
- ctx.BottomUp("begin", BeginMutator).Parallel()
+ ctx.BottomUp("begin", BeginMutator)
})
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -59,10 +59,10 @@
san.registerMutators(ctx)
}
- ctx.BottomUp("sanitize_runtime_deps", sanitizerRuntimeDepsMutator).Parallel()
- ctx.BottomUp("sanitize_runtime", sanitizerRuntimeMutator).Parallel()
+ ctx.BottomUp("sanitize_runtime_deps", sanitizerRuntimeDepsMutator)
+ ctx.BottomUp("sanitize_runtime", sanitizerRuntimeMutator)
- ctx.BottomUp("fuzz_deps", fuzzMutatorDeps)
+ ctx.Transition("fuzz", &fuzzTransitionMutator{})
ctx.Transition("coverage", &coverageTransitionMutator{})
@@ -72,8 +72,8 @@
ctx.Transition("lto", <oTransitionMutator{})
- ctx.BottomUp("check_linktype", checkLinkTypeMutator).Parallel()
- ctx.BottomUp("double_loadable", checkDoubleLoadableLibraries).Parallel()
+ ctx.BottomUp("check_linktype", checkLinkTypeMutator)
+ ctx.BottomUp("double_loadable", checkDoubleLoadableLibraries)
})
ctx.PostApexMutators(func(ctx android.RegisterMutatorsContext) {
@@ -119,9 +119,10 @@
ObjFiles []string
- GeneratedSources []string
- GeneratedHeaders []string
- GeneratedDeps []string
+ GeneratedSources []string
+ GeneratedHeaders []string
+ DeviceFirstGeneratedHeaders []string
+ GeneratedDeps []string
ReexportGeneratedHeaders []string
@@ -2609,6 +2610,11 @@
actx.AddDependency(c, depTag, gen)
}
+ for _, gen := range deps.DeviceFirstGeneratedHeaders {
+ depTag := genHeaderDepTag
+ actx.AddVariationDependencies(ctx.Config().AndroidFirstDeviceTarget.Variations(), depTag, gen)
+ }
+
crtVariations := GetCrtVariations(ctx, c)
actx.AddVariationDependencies(crtVariations, objDepTag, deps.ObjFiles...)
for _, crt := range deps.CrtBegin {
diff --git a/cc/cc_preprocess_no_configuration.go b/cc/cc_preprocess_no_configuration.go
new file mode 100644
index 0000000..3d4b077
--- /dev/null
+++ b/cc/cc_preprocess_no_configuration.go
@@ -0,0 +1,115 @@
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+ "android/soong/android"
+ "slices"
+ "strings"
+)
+
+func init() {
+ RegisterCCPreprocessNoConfiguration(android.InitRegistrationContext)
+}
+
+func RegisterCCPreprocessNoConfiguration(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("cc_preprocess_no_configuration", ccPreprocessNoConfigurationFactory)
+}
+
+// cc_preprocess_no_configuration modules run the c preprocessor on a single input source file.
+// They also have "no configuration", meaning they don't have an arch or os associated with them,
+// they should be thought of as pure textual transformations of the input file. In some cases this
+// is good, in others you might want to do different transformations depending on what arch the
+// result will be compiled in, in which case you can use cc_object instead of this module.
+func ccPreprocessNoConfigurationFactory() android.Module {
+ m := &ccPreprocessNoConfiguration{}
+ m.AddProperties(&m.properties)
+ android.InitAndroidModule(m)
+ return m
+}
+
+type ccPreprocessNoConfigurationProps struct {
+ // Called Srcs for consistency with the other cc module types, but only accepts 1 input source
+ // file.
+ Srcs []string `android:"path"`
+ // The flags to pass to the c compiler. Must include -E in order to enable preprocessing-only
+ // mode.
+ Cflags []string `android:"path"`
+}
+
+type ccPreprocessNoConfiguration struct {
+ android.ModuleBase
+ properties ccPreprocessNoConfigurationProps
+}
+
+func (m *ccPreprocessNoConfiguration) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
+ if len(srcs) != 1 {
+ ctx.PropertyErrorf("Srcs", "cc_preprocess_no_configuration only accepts 1 source file, found: %v", srcs.Strings())
+ return
+ }
+ src := srcs[0]
+
+ hasE := false
+ for _, cflag := range m.properties.Cflags {
+ if cflag == "-E" {
+ hasE = true
+ break
+ } else if cflag == "-P" || strings.HasPrefix(cflag, "-D") {
+ // do nothing, allow it
+ } else {
+ ctx.PropertyErrorf("Cflags", "cc_preprocess_no_configuration only allows -D and -P flags, found: %q", cflag)
+ return
+ }
+ }
+ if !hasE {
+ ctx.PropertyErrorf("Cflags", "cc_preprocess_no_configuration must have a -E cflag")
+ return
+ }
+
+ cflags := slices.Clone(m.properties.Cflags)
+
+ // Match behavior of other cc modules:
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/soong/cc/compiler.go;l=422;drc=7297f05ee8cda422ccb32c4af4d9d715d6bac10e
+ cflags = append(cflags, "-I"+ctx.ModuleDir())
+
+ var ccCmd string
+ switch src.Ext() {
+ case ".c":
+ ccCmd = "clang"
+ case ".cpp", ".cc", ".cxx", ".mm":
+ ccCmd = "clang++"
+ default:
+ ctx.PropertyErrorf("srcs", "File %s has unknown extension. Supported extensions: .c, .cpp, .cc, .cxx, .mm", src)
+ return
+ }
+
+ ccCmd = "${config.ClangBin}/" + ccCmd
+
+ outFile := android.PathForModuleOut(ctx, src.Base())
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: cc,
+ Description: ccCmd + " " + src.Rel(),
+ Output: outFile,
+ Input: src,
+ Args: map[string]string{
+ "cFlags": strings.Join(cflags, " "),
+ "ccCmd": ccCmd,
+ },
+ })
+
+ ctx.SetOutputFiles([]android.Path{outFile}, "")
+}
diff --git a/cc/cc_preprocess_no_configuration_test.go b/cc/cc_preprocess_no_configuration_test.go
new file mode 100644
index 0000000..c6eae4c
--- /dev/null
+++ b/cc/cc_preprocess_no_configuration_test.go
@@ -0,0 +1,43 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+ "android/soong/android"
+ "testing"
+)
+
+func TestCcPreprocessNoConfiguration(t *testing.T) {
+ bp := `
+ cc_preprocess_no_configuration {
+ name: "foo",
+ srcs: ["main.cc"],
+ cflags: ["-E", "-DANDROID"],
+ }
+ `
+
+ fixture := android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ android.FixtureRegisterWithContext(RegisterCCPreprocessNoConfiguration),
+ android.FixtureAddTextFile("foo/bar/Android.bp", bp),
+ )
+
+ result := fixture.RunTest(t)
+
+ foo := result.ModuleForTests("foo", "")
+ actual := foo.Rule("cc").Args["cFlags"]
+ expected := "-E -DANDROID -Ifoo/bar"
+ android.AssertStringEquals(t, "cflags should be correct", expected, actual)
+}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 3f3347b..90ec811 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -20,6 +20,7 @@
"reflect"
"regexp"
"runtime"
+ "slices"
"strings"
"testing"
@@ -1903,11 +1904,11 @@
moduleName = "afl_fuzz_static_lib"
checkPcGuardFlag(moduleName, variant+"_static", false)
- checkPcGuardFlag(moduleName, variant+"_static_fuzzer", true)
+ checkPcGuardFlag(moduleName, variant+"_static_fuzzer_afl", true)
moduleName = "second_static_lib"
checkPcGuardFlag(moduleName, variant+"_static", false)
- checkPcGuardFlag(moduleName, variant+"_static_fuzzer", true)
+ checkPcGuardFlag(moduleName, variant+"_static_fuzzer_afl", true)
ctx.ModuleForTests("afl_fuzz_shared_lib",
"android_arm64_armv8-a_shared").Rule("cc")
@@ -2733,6 +2734,11 @@
func TestIncludeDirectoryOrdering(t *testing.T) {
t.Parallel()
+
+ expectedPlatformFlags := []string{
+ "-nostdlibinc",
+ }
+
baseExpectedFlags := []string{
"${config.ArmThumbCflags}",
"${config.ArmCflags}",
@@ -2742,10 +2748,18 @@
"${config.ArmToolchainCflags}",
"${config.ArmArmv7ANeonCflags}",
"${config.ArmGenericCflags}",
+ }
+
+ expectedTargetNDKFlags := []string{
"-target",
"armv7a-linux-androideabi21",
}
+ expectedTargetPlatformFlags := []string{
+ "-target",
+ "armv7a-linux-androideabi10000",
+ }
+
expectedIncludes := []string{
"external/foo/android_arm_export_include_dirs",
"external/foo/lib32_export_include_dirs",
@@ -2773,6 +2787,9 @@
"external/foo/libarm",
"external/foo/lib32",
"external/foo/libandroid_arm",
+ }
+
+ expectedNDKSTLIncludes := []string{
"defaults/cc/common/ndk_libc++_shared_include_dirs",
}
@@ -2783,38 +2800,92 @@
cstd := []string{"-std=gnu17", "-std=conly"}
cppstd := []string{"-std=gnu++20", "-std=cpp", "-fno-rtti"}
- lastIncludes := []string{
- "out/soong/ndk/sysroot/usr/include",
- "out/soong/ndk/sysroot/usr/include/arm-linux-androideabi",
+ lastNDKFlags := []string{
+ "--sysroot",
+ "out/soong/ndk/sysroot",
}
- combineSlices := func(slices ...[]string) []string {
- var ret []string
- for _, s := range slices {
- ret = append(ret, s...)
- }
- return ret
+ lastPlatformIncludes := []string{
+ "${config.CommonGlobalIncludes}",
}
testCases := []struct {
- name string
- src string
- expected []string
+ name string
+ src string
+ expectedNDK []string
+ expectedPlatform []string
}{
{
- name: "c",
- src: "foo.c",
- expected: combineSlices(baseExpectedFlags, conly, expectedIncludes, cflags, cstd, lastIncludes, []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"}),
+ name: "c",
+ src: "foo.c",
+ expectedNDK: slices.Concat(
+ baseExpectedFlags,
+ expectedTargetNDKFlags,
+ conly,
+ expectedIncludes,
+ expectedNDKSTLIncludes,
+ cflags,
+ cstd,
+ lastNDKFlags,
+ []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"},
+ ),
+ expectedPlatform: slices.Concat(
+ expectedPlatformFlags,
+ baseExpectedFlags,
+ expectedTargetPlatformFlags,
+ conly,
+ expectedIncludes,
+ cflags,
+ cstd,
+ lastPlatformIncludes,
+ []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"},
+ ),
},
{
- name: "cc",
- src: "foo.cc",
- expected: combineSlices(baseExpectedFlags, cppOnly, expectedIncludes, cflags, cppstd, lastIncludes, []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"}),
+ name: "cc",
+ src: "foo.cc",
+ expectedNDK: slices.Concat(
+ baseExpectedFlags,
+ expectedTargetNDKFlags,
+ cppOnly,
+ expectedIncludes,
+ expectedNDKSTLIncludes,
+ cflags,
+ cppstd,
+ lastNDKFlags,
+ []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"},
+ ),
+ expectedPlatform: slices.Concat(
+ expectedPlatformFlags,
+ baseExpectedFlags,
+ expectedTargetPlatformFlags,
+ cppOnly,
+ expectedIncludes,
+ cflags,
+ cppstd,
+ lastPlatformIncludes,
+ []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"},
+ ),
},
{
- name: "assemble",
- src: "foo.s",
- expected: combineSlices(baseExpectedFlags, []string{"${config.CommonGlobalAsflags}"}, expectedIncludes, lastIncludes),
+ name: "assemble",
+ src: "foo.s",
+ expectedNDK: slices.Concat(
+ baseExpectedFlags,
+ expectedTargetNDKFlags,
+ []string{"${config.CommonGlobalAsflags}"},
+ expectedIncludes,
+ expectedNDKSTLIncludes,
+ lastNDKFlags,
+ ),
+ expectedPlatform: slices.Concat(
+ expectedPlatformFlags,
+ baseExpectedFlags,
+ expectedTargetPlatformFlags,
+ []string{"${config.CommonGlobalAsflags}"},
+ expectedIncludes,
+ lastPlatformIncludes,
+ ),
},
}
@@ -2909,25 +2980,34 @@
`, lib, lib)
}
- ctx := android.GroupFixturePreparers(
- PrepareForIntegrationTestWithCc,
- android.FixtureAddTextFile("external/foo/Android.bp", bp),
- ).RunTest(t)
- cflags := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_sdk_static").Output("obj/external/foo/foo.o").Args["cFlags"]
+ runTest := func(t *testing.T, variant string, expected []string) {
+ ctx := android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithCc,
+ android.FixtureAddTextFile("external/foo/Android.bp", bp),
+ ).RunTest(t)
+ cflags := ctx.ModuleForTests("libfoo", variant).Output("obj/external/foo/foo.o").Args["cFlags"]
- var includes []string
- flags := strings.Split(cflags, " ")
- for _, flag := range flags {
- if strings.HasPrefix(flag, "-I") {
- includes = append(includes, strings.TrimPrefix(flag, "-I"))
- } else if flag == "-isystem" {
- // skip isystem, include next
- } else if len(flag) > 0 {
- includes = append(includes, flag)
+ var includes []string
+ flags := strings.Split(cflags, " ")
+ for _, flag := range flags {
+ if strings.HasPrefix(flag, "-I") {
+ includes = append(includes, strings.TrimPrefix(flag, "-I"))
+ } else if flag == "-isystem" {
+ // skip isystem, include next
+ } else if len(flag) > 0 {
+ includes = append(includes, flag)
+ }
}
+
+ android.AssertArrayString(t, "includes", expected, includes)
}
- android.AssertArrayString(t, "includes", tc.expected, includes)
+ t.Run("platform", func(t *testing.T) {
+ runTest(t, "android_arm_armv7-a-neon_static", tc.expectedPlatform)
+ })
+ t.Run("ndk", func(t *testing.T) {
+ runTest(t, "android_arm_armv7-a-neon_sdk_static", tc.expectedNDK)
+ })
})
}
diff --git a/cc/compiler.go b/cc/compiler.go
index 022b712..f06287c 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -100,6 +100,11 @@
// of genrule modules.
Generated_headers proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
+ // Same as generated_headers, but the dependencies will be added based on the first supported
+ // arch variant and the device os variant. This can be useful for creating a host tool that
+ // embeds a copy of a device tool, that it then extracts and pushes to a device at runtime.
+ Device_first_generated_headers proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
+
// pass -frtti instead of -fno-rtti
Rtti *bool `android:"arch_variant"`
@@ -294,6 +299,7 @@
deps.GeneratedSources = append(deps.GeneratedSources, compiler.Properties.Generated_sources...)
deps.GeneratedSources = removeListFromList(deps.GeneratedSources, compiler.Properties.Exclude_generated_sources)
deps.GeneratedHeaders = append(deps.GeneratedHeaders, compiler.Properties.Generated_headers.GetOrDefault(ctx, nil)...)
+ deps.DeviceFirstGeneratedHeaders = append(deps.DeviceFirstGeneratedHeaders, compiler.Properties.Device_first_generated_headers.GetOrDefault(ctx, nil)...)
deps.AidlLibs = append(deps.AidlLibs, compiler.Properties.Aidl.Libs...)
android.ProtoDeps(ctx, &compiler.Proto)
@@ -430,14 +436,14 @@
}
if ctx.useSdk() {
- // TODO: Switch to --sysroot.
// The NDK headers are installed to a common sysroot. While a more
// typical Soong approach would be to only make the headers for the
// library you're using available, we're trying to emulate the NDK
// behavior here, and the NDK always has all the NDK headers available.
flags.SystemIncludeFlags = append(flags.SystemIncludeFlags,
- "-isystem "+getCurrentIncludePath(ctx).String(),
- "-isystem "+getCurrentIncludePath(ctx).Join(ctx, config.NDKTriple(tc)).String())
+ "--sysroot "+getNdkSysrootBase(ctx).String())
+ } else if ctx.Device() {
+ flags.Global.CommonFlags = append(flags.Global.CFlags, "-nostdlibinc")
}
if ctx.InVendorOrProduct() {
@@ -695,7 +701,9 @@
if ctx.optimizeForSize() {
flags.Local.CFlags = append(flags.Local.CFlags, "-Oz")
- flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,-enable-ml-inliner=release")
+ if !ctx.Config().IsEnvFalse("THINLTO_USE_MLGO") {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,-enable-ml-inliner=release")
+ }
}
// Exclude directories from manual binder interface allowed list.
diff --git a/cc/config/global.go b/cc/config/global.go
index 9d3de6d..d63f86d 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -172,7 +172,6 @@
"-Werror=address",
"-Werror=sequence-point",
"-Werror=format-security",
- "-nostdlibinc",
}
commonGlobalLldflags = []string{
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 3f21bc6..cbe139f 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -57,38 +57,76 @@
return []interface{}{&fuzzer.Properties}
}
-func fuzzMutatorDeps(mctx android.BottomUpMutatorContext) {
- currentModule, ok := mctx.Module().(*Module)
+// fuzzTransitionMutator creates variants to propagate the FuzzFramework value down to dependencies.
+type fuzzTransitionMutator struct{}
+
+func (f *fuzzTransitionMutator) Split(ctx android.BaseModuleContext) []string {
+ return []string{""}
+}
+
+func (f *fuzzTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ m, ok := ctx.Module().(*Module)
+ if !ok {
+ return ""
+ }
+
+ if m.fuzzer == nil {
+ return ""
+ }
+
+ if m.sanitize == nil {
+ return ""
+ }
+
+ isFuzzerPointer := m.sanitize.getSanitizerBoolPtr(Fuzzer)
+ if isFuzzerPointer == nil || !*isFuzzerPointer {
+ return ""
+ }
+
+ if m.fuzzer.Properties.FuzzFramework != "" {
+ return m.fuzzer.Properties.FuzzFramework.Variant()
+ }
+
+ return sourceVariation
+}
+
+func (f *fuzzTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ m, ok := ctx.Module().(*Module)
+ if !ok {
+ return ""
+ }
+
+ if m.fuzzer == nil {
+ return ""
+ }
+
+ if m.sanitize == nil {
+ return ""
+ }
+
+ isFuzzerPointer := m.sanitize.getSanitizerBoolPtr(Fuzzer)
+ if isFuzzerPointer == nil || !*isFuzzerPointer {
+ return ""
+ }
+
+ return incomingVariation
+}
+
+func (f *fuzzTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ m, ok := ctx.Module().(*Module)
if !ok {
return
}
- if currentModule.fuzzer == nil {
+ if m.fuzzer == nil {
return
}
- mctx.WalkDeps(func(child android.Module, parent android.Module) bool {
- c, ok := child.(*Module)
- if !ok {
- return false
- }
-
- if c.sanitize == nil {
- return false
- }
-
- isFuzzerPointer := c.sanitize.getSanitizerBoolPtr(Fuzzer)
- if isFuzzerPointer == nil || !*isFuzzerPointer {
- return false
- }
-
- if c.fuzzer == nil {
- return false
- }
-
- c.fuzzer.Properties.FuzzFramework = currentModule.fuzzer.Properties.FuzzFramework
- return true
- })
+ if variation != "" {
+ m.fuzzer.Properties.FuzzFramework = fuzz.FrameworkFromVariant(variation)
+ m.SetHideFromMake()
+ m.SetPreventInstall()
+ }
}
// cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at
@@ -144,9 +182,13 @@
}
func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
- subdir := "lib"
- if ctx.inVendor() {
+ var subdir string
+ if ctx.isForPlatform() {
+ subdir = "lib"
+ } else if ctx.inVendor() {
subdir = "lib/vendor"
+ } else {
+ ctx.ModuleErrorf("Fuzzer must be system or vendor variant")
}
flags = fuzz.binaryDecorator.linkerFlags(ctx, flags)
@@ -309,6 +351,7 @@
func PackageFuzzModule(ctx android.ModuleContext, fuzzPackagedModule fuzz.FuzzPackagedModule, pctx android.PackageContext) fuzz.FuzzPackagedModule {
fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Corpus)
+ fuzzPackagedModule.Corpus = append(fuzzPackagedModule.Corpus, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_common_corpus)...)
fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Data)
diff --git a/cc/genrule.go b/cc/genrule.go
index fe3b127..bd6c5f1 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -77,41 +77,41 @@
var _ android.ImageInterface = (*GenruleExtraProperties)(nil)
-func (g *GenruleExtraProperties) ImageMutatorBegin(ctx android.BaseModuleContext) {}
+func (g *GenruleExtraProperties) ImageMutatorBegin(ctx android.ImageInterfaceContext) {}
-func (g *GenruleExtraProperties) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
+func (g *GenruleExtraProperties) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
return Bool(g.Vendor_available) || Bool(g.Odm_available) || ctx.SocSpecific() || ctx.DeviceSpecific()
}
-func (g *GenruleExtraProperties) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
+func (g *GenruleExtraProperties) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
return Bool(g.Product_available) || ctx.ProductSpecific()
}
-func (g *GenruleExtraProperties) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+func (g *GenruleExtraProperties) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
return !(ctx.SocSpecific() || ctx.DeviceSpecific() || ctx.ProductSpecific())
}
-func (g *GenruleExtraProperties) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (g *GenruleExtraProperties) RamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return Bool(g.Ramdisk_available)
}
-func (g *GenruleExtraProperties) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (g *GenruleExtraProperties) VendorRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return Bool(g.Vendor_ramdisk_available)
}
-func (g *GenruleExtraProperties) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (g *GenruleExtraProperties) DebugRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (g *GenruleExtraProperties) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+func (g *GenruleExtraProperties) RecoveryVariantNeeded(ctx android.ImageInterfaceContext) bool {
// If the build is using a snapshot, the recovery variant under AOSP directories
// is not needed.
return Bool(g.Recovery_available)
}
-func (g *GenruleExtraProperties) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+func (g *GenruleExtraProperties) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
return nil
}
-func (g *GenruleExtraProperties) SetImageVariation(ctx android.BaseModuleContext, variation string) {
+func (g *GenruleExtraProperties) SetImageVariation(ctx android.ImageInterfaceContext, variation string) {
}
diff --git a/cc/image.go b/cc/image.go
index 7594a08..ee40483 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -177,7 +177,7 @@
IsSnapshotPrebuilt() bool
// SnapshotVersion returns the snapshot version for this module.
- SnapshotVersion(mctx android.BaseModuleContext) string
+ SnapshotVersion(mctx android.ImageInterfaceContext) string
// SdkVersion returns the SDK version for this module.
SdkVersion() string
@@ -209,7 +209,7 @@
var _ ImageMutatableModule = (*Module)(nil)
-func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
+func (m *Module) ImageMutatorBegin(mctx android.ImageInterfaceContext) {
MutateImage(mctx, m)
}
@@ -273,7 +273,7 @@
m.Properties.VendorVariantNeeded = b
}
-func (m *Module) SnapshotVersion(mctx android.BaseModuleContext) string {
+func (m *Module) SnapshotVersion(mctx android.ImageInterfaceContext) string {
if snapshot, ok := m.linker.(SnapshotInterface); ok {
return snapshot.Version()
} else {
@@ -291,7 +291,7 @@
}
// MutateImage handles common image mutations for ImageMutatableModule interfaces.
-func MutateImage(mctx android.BaseModuleContext, m ImageMutatableModule) {
+func MutateImage(mctx android.ImageInterfaceContext, m ImageMutatableModule) {
// Validation check
vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
productSpecific := mctx.ProductSpecific()
@@ -431,35 +431,35 @@
}
}
-func (c *Module) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
+func (c *Module) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
return c.Properties.VendorVariantNeeded
}
-func (c *Module) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
+func (c *Module) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
return c.Properties.ProductVariantNeeded
}
-func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+func (c *Module) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
return c.Properties.CoreVariantNeeded
}
-func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (c *Module) RamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return c.Properties.RamdiskVariantNeeded
}
-func (c *Module) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (c *Module) VendorRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return c.Properties.VendorRamdiskVariantNeeded
}
-func (c *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (c *Module) DebugRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+func (c *Module) RecoveryVariantNeeded(ctx android.ImageInterfaceContext) bool {
return c.Properties.RecoveryVariantNeeded
}
-func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+func (c *Module) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
return c.Properties.ExtraVersionedImageVariations
}
@@ -513,7 +513,7 @@
}
}
-func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string) {
+func (c *Module) SetImageVariation(ctx android.ImageInterfaceContext, variant string) {
if variant == android.RamdiskVariation {
c.MakeAsPlatform()
squashRamdiskSrcs(c)
diff --git a/cc/lto.go b/cc/lto.go
index f3af7d2..4444152 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -110,7 +110,7 @@
var ltoLdFlags []string
// Do not perform costly LTO optimizations for Eng builds.
- if Bool(lto.Properties.Lto_O0) || ctx.optimizeForSize() || ctx.Config().Eng() {
+ if Bool(lto.Properties.Lto_O0) || ctx.Config().Eng() {
ltoLdFlags = append(ltoLdFlags, "-Wl,--lto-O0")
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 85fdb02..118580e 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -176,7 +176,7 @@
switch t {
case cfi, Hwasan, Asan, tsan, Fuzzer, scs, Memtag_stack:
sanitizer := &sanitizerSplitMutator{t}
- ctx.BottomUp(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator).Parallel()
+ ctx.BottomUp(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator)
ctx.Transition(t.variationName(), sanitizer)
case Memtag_heap, Memtag_globals, intOverflow:
// do nothing
@@ -1830,10 +1830,7 @@
type sanitizerLibraryDependencyTag struct {
blueprint.BaseDependencyTag
-}
-
-func (t sanitizerLibraryDependencyTag) AllowDisabledModuleDependency(target android.Module) bool {
- return true
+ android.AlwaysAllowDisabledModuleDependencyTag
}
var _ android.AllowDisabledModuleDependency = (*sanitizerLibraryDependencyTag)(nil)
diff --git a/cc/test.go b/cc/test.go
index f5bb761..ae73886 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -15,10 +15,11 @@
package cc
import (
- "github.com/google/blueprint/proptools"
"path/filepath"
"strconv"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/tradefed"
)
@@ -82,6 +83,16 @@
// the test
Data []string `android:"path,arch_variant"`
+ // Same as data, but adds depedencies on modules using the device's os variant, and common
+ // architecture's variant. Can be useful to add device-built apps to the data of a host
+ // test.
+ Device_common_data []string `android:"path_device_common"`
+
+ // Same as data, but adds depedencies on modules using the device's os variant, and the device's
+ // first architecture's variant. Can be useful to add device-built apps to the data of a host
+ // test.
+ Device_first_data []string `android:"path_device_first"`
+
// list of shared library modules that should be installed alongside the test
Data_libs []string `android:"arch_variant"`
@@ -324,6 +335,8 @@
func (test *testBinary) install(ctx ModuleContext, file android.Path) {
dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
+ dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_common_data)...)
+ dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_first_data)...)
for _, dataSrcPath := range dataSrcPaths {
test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath})
diff --git a/cmd/release_config/build_flag/main.go b/cmd/release_config/build_flag/main.go
index 5d183ee..46efce7 100644
--- a/cmd/release_config/build_flag/main.go
+++ b/cmd/release_config/build_flag/main.go
@@ -329,7 +329,7 @@
return err
}
updatedFiles = append(updatedFiles, flagPath)
- fmt.Printf("Added/Updated: %s\n", strings.Join(updatedFiles, " "))
+ fmt.Printf("\033[1mAdded/Updated: %s\033[0m\n", strings.Join(updatedFiles, " "))
return nil
}
diff --git a/cmd/release_config/release_config_lib/release_config.go b/cmd/release_config/release_config_lib/release_config.go
index adf0e62..ee71336 100644
--- a/cmd/release_config/release_config_lib/release_config.go
+++ b/cmd/release_config/release_config_lib/release_config.go
@@ -280,11 +280,28 @@
directories := []string{}
valueDirectories := []string{}
+ // These path prefixes are exclusive for a release config.
+ // "A release config shall exist in at most one of these."
+ // If we find a benefit to generalizing this, we can do so at that time.
+ exclusiveDirPrefixes := []string{
+ "build/release",
+ "vendor/google_shared/build/release",
+ }
+ var exclusiveDir string
for idx, confDir := range configs.configDirs {
if _, ok := myDirsMap[idx]; ok {
directories = append(directories, confDir)
}
if _, ok := myValueDirsMap[idx]; ok {
+ for _, dir := range exclusiveDirPrefixes {
+ if strings.HasPrefix(confDir, dir) {
+ if exclusiveDir != "" && !strings.HasPrefix(exclusiveDir, dir) {
+ return fmt.Errorf("%s is declared in both %s and %s",
+ config.Name, exclusiveDir, confDir)
+ }
+ exclusiveDir = confDir
+ }
+ }
valueDirectories = append(valueDirectories, confDir)
}
}
diff --git a/compliance/notice_test.go b/compliance/notice_test.go
index 6187e53..e8578ec 100644
--- a/compliance/notice_test.go
+++ b/compliance/notice_test.go
@@ -35,4 +35,4 @@
m := result.Module("notice_xml_system", "android_arm64_armv8-a").(*NoticeXmlModule)
android.AssertStringEquals(t, "output file", "NOTICE.xml.gz", m.outputFile.Base())
-}
\ No newline at end of file
+}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 84d4f10..3dd6f9a 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -462,6 +462,12 @@
return target.IsReplacedByPrebuilt()
}
+func (d dex2oatDependencyTag) AllowDisabledModuleDependencyProxy(
+ ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool {
+ return android.OtherModuleProviderOrDefault(
+ ctx, target, android.CommonPropertiesProviderKey).ReplacedByPrebuilt
+}
+
// Dex2oatDepTag represents the dependency onto the dex2oatd module. It is added to any module that
// needs dexpreopting and so it makes no sense for it to be checked for visibility or included in
// the apex.
diff --git a/etc/adb_keys.go b/etc/adb_keys.go
index 1bce2f1..a2df41c 100644
--- a/etc/adb_keys.go
+++ b/etc/adb_keys.go
@@ -37,7 +37,6 @@
func (m *AdbKeysModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
productVariables := ctx.Config().ProductVariables()
if !(android.Bool(productVariables.Debuggable) && len(android.String(productVariables.AdbKeys)) > 0) {
- m.Disable()
m.SkipInstall()
return
}
diff --git a/etc/install_symlink.go b/etc/install_symlink.go
index 2182b86..aa33445 100644
--- a/etc/install_symlink.go
+++ b/etc/install_symlink.go
@@ -26,6 +26,7 @@
func RegisterInstallSymlinkBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("install_symlink", InstallSymlinkFactory)
+ ctx.RegisterModuleType("install_symlink_host", InstallSymlinkHostFactory)
}
// install_symlink can be used to install an symlink with an arbitrary target to an arbitrary path
@@ -37,6 +38,14 @@
return module
}
+// install_symlink can be used to install an symlink to an arbitrary path on the host.
+func InstallSymlinkHostFactory() android.Module {
+ module := &InstallSymlink{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidMultiTargetsArchModule(module, android.HostSupported, android.MultilibCommon)
+ return module
+}
+
type InstallSymlinkProperties struct {
// Where to install this symlink, relative to the partition it's installed on.
// Which partition it's installed on can be controlled by the vendor, system_ext, ramdisk, etc.
diff --git a/etc/install_symlink_test.go b/etc/install_symlink_test.go
index d7165e5..c97d97c 100644
--- a/etc/install_symlink_test.go
+++ b/etc/install_symlink_test.go
@@ -133,3 +133,39 @@
}
`)
}
+
+var prepareForInstallSymlinkHostTest = android.GroupFixturePreparers(
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.FixtureRegisterWithContext(RegisterInstallSymlinkBuildComponents),
+)
+
+func TestInstallSymlinkHostBasic(t *testing.T) {
+ result := prepareForInstallSymlinkHostTest.RunTestWithBp(t, `
+ install_symlink_host {
+ name: "foo",
+ installed_location: "bin/foo",
+ symlink_target: "aa/bb/cc",
+ }
+ `)
+
+ buildOS := result.Config.BuildOS.String()
+ foo := result.ModuleForTests("foo", buildOS+"_common").Module()
+
+ androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, foo)
+ if len(androidMkEntries) != 1 {
+ t.Fatalf("expected 1 androidmkentry, got %d", len(androidMkEntries))
+ }
+
+ symlinks := androidMkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"]
+ if len(symlinks) != 1 {
+ t.Fatalf("Expected 1 symlink, got %d", len(symlinks))
+ }
+
+ if !strings.HasSuffix(symlinks[0], "bin/foo") {
+ t.Fatalf("Expected symlink install path to end in bin/foo, got: %s", symlinks[0])
+ }
+
+ if !strings.Contains(symlinks[0], "host") {
+ t.Fatalf("Expected symlink install path to contain `host`, got: %s", symlinks[0])
+ }
+}
diff --git a/etc/otacerts_zip.go b/etc/otacerts_zip.go
index b6f175a..d12bdac 100644
--- a/etc/otacerts_zip.go
+++ b/etc/otacerts_zip.go
@@ -61,41 +61,41 @@
var _ android.ImageInterface = (*otacertsZipModule)(nil)
-func (m *otacertsZipModule) ImageMutatorBegin(ctx android.BaseModuleContext) {}
+func (m *otacertsZipModule) ImageMutatorBegin(ctx android.ImageInterfaceContext) {}
-func (m *otacertsZipModule) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
+func (m *otacertsZipModule) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (m *otacertsZipModule) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
+func (m *otacertsZipModule) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (m *otacertsZipModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+func (m *otacertsZipModule) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
return !m.ModuleBase.InstallInRecovery()
}
-func (m *otacertsZipModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (m *otacertsZipModule) RamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (m *otacertsZipModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (m *otacertsZipModule) VendorRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (m *otacertsZipModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (m *otacertsZipModule) DebugRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (m *otacertsZipModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+func (m *otacertsZipModule) RecoveryVariantNeeded(ctx android.ImageInterfaceContext) bool {
return proptools.Bool(m.properties.Recovery_available) || m.ModuleBase.InstallInRecovery()
}
-func (m *otacertsZipModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+func (m *otacertsZipModule) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
return nil
}
-func (m *otacertsZipModule) SetImageVariation(ctx android.BaseModuleContext, variation string) {
+func (m *otacertsZipModule) SetImageVariation(ctx android.ImageInterfaceContext, variation string) {
}
func (m *otacertsZipModule) InRecovery() bool {
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index fc6d1f7..59712c0 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -78,9 +78,16 @@
Src proptools.Configurable[string] `android:"path,arch_variant,replace_instead_of_append"`
// Source files of this prebuilt. Can reference a genrule type module with the ":module" syntax.
- // Mutually exclusive with src. When used, filename_from_src is set to true.
+ // Mutually exclusive with src. When used, filename_from_src is set to true unless dsts is also
+ // set. May use globs in filenames.
Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
+ // Destination files of this prebuilt. Requires srcs to be used and causes srcs not to implicitly
+ // set filename_from_src. This can be used to install each source file to a different directory
+ // and/or change filenames when files are installed. Must be exactly one entry per source file,
+ // which means care must be taken if srcs has globs.
+ Dsts proptools.Configurable[[]string] `android:"path,arch_variant"`
+
// Optional name for the installed file. If unspecified, name of the module is used as the file
// name. Only available when using a single source (src).
Filename *string `android:"arch_variant"`
@@ -166,7 +173,7 @@
// The base install location when soc_specific property is set to true, e.g. "firmware" for
// prebuilt_firmware.
socInstallDirBase string
- installDirPath android.InstallPath
+ installDirPaths []android.InstallPath
additionalDependencies *android.Paths
usedSrcsProperty bool
@@ -229,30 +236,30 @@
var _ android.ImageInterface = (*PrebuiltEtc)(nil)
-func (p *PrebuiltEtc) ImageMutatorBegin(ctx android.BaseModuleContext) {}
+func (p *PrebuiltEtc) ImageMutatorBegin(ctx android.ImageInterfaceContext) {}
-func (p *PrebuiltEtc) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
+func (p *PrebuiltEtc) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (p *PrebuiltEtc) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
+func (p *PrebuiltEtc) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (p *PrebuiltEtc) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+func (p *PrebuiltEtc) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
return !p.ModuleBase.InstallInRecovery() && !p.ModuleBase.InstallInRamdisk() &&
!p.ModuleBase.InstallInVendorRamdisk() && !p.ModuleBase.InstallInDebugRamdisk()
}
-func (p *PrebuiltEtc) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (p *PrebuiltEtc) RamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return proptools.Bool(p.properties.Ramdisk_available) || p.ModuleBase.InstallInRamdisk()
}
-func (p *PrebuiltEtc) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (p *PrebuiltEtc) VendorRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return proptools.Bool(p.properties.Vendor_ramdisk_available) || p.ModuleBase.InstallInVendorRamdisk()
}
-func (p *PrebuiltEtc) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (p *PrebuiltEtc) DebugRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return proptools.Bool(p.properties.Debug_ramdisk_available) || p.ModuleBase.InstallInDebugRamdisk()
}
@@ -260,15 +267,15 @@
return proptools.Bool(p.rootProperties.Install_in_root)
}
-func (p *PrebuiltEtc) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+func (p *PrebuiltEtc) RecoveryVariantNeeded(ctx android.ImageInterfaceContext) bool {
return proptools.Bool(p.properties.Recovery_available) || p.ModuleBase.InstallInRecovery()
}
-func (p *PrebuiltEtc) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+func (p *PrebuiltEtc) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
return nil
}
-func (p *PrebuiltEtc) SetImageVariation(ctx android.BaseModuleContext, variation string) {
+func (p *PrebuiltEtc) SetImageVariation(ctx android.ImageInterfaceContext, variation string) {
}
func (p *PrebuiltEtc) SourceFilePath(ctx android.ModuleContext) android.Path {
@@ -279,7 +286,10 @@
}
func (p *PrebuiltEtc) InstallDirPath() android.InstallPath {
- return p.installDirPath
+ if len(p.installDirPaths) != 1 {
+ panic(fmt.Errorf("InstallDirPath not available on multi-source prebuilt %q", p.Name()))
+ }
+ return p.installDirPaths[0]
}
// This allows other derivative modules (e.g. prebuilt_etc_xml) to perform
@@ -338,12 +348,16 @@
if srcProperty.IsPresent() && len(srcsProperty) > 0 {
ctx.PropertyErrorf("src", "src is set. Cannot set srcs")
}
+ dstsProperty := p.properties.Dsts.GetOrDefault(ctx, nil)
+ if len(dstsProperty) > 0 && len(srcsProperty) == 0 {
+ ctx.PropertyErrorf("dsts", "dsts is set. Must use srcs")
+ }
// Check that `sub_dir` and `relative_install_path` are not set at the same time.
if p.subdirProperties.Sub_dir != nil && p.subdirProperties.Relative_install_path != nil {
ctx.PropertyErrorf("sub_dir", "relative_install_path is set. Cannot set sub_dir")
}
- p.installDirPath = android.PathForModuleInstall(ctx, p.installBaseDir(ctx), p.SubDir())
+ baseInstallDirPath := android.PathForModuleInstall(ctx, p.installBaseDir(ctx), p.SubDir())
filename := proptools.String(p.properties.Filename)
filenameFromSrc := proptools.Bool(p.properties.Filename_from_src)
@@ -379,10 +393,11 @@
filename: filename,
sourceFilePath: p.sourceFilePaths[0],
outputFilePath: p.outputFilePaths[0],
- installDirPath: p.installDirPath,
+ installDirPath: baseInstallDirPath,
symlinks: p.properties.Symlinks,
}
installs = append(installs, ip)
+ p.installDirPaths = append(p.installDirPaths, baseInstallDirPath)
} else if len(srcsProperty) > 0 {
p.usedSrcsProperty = true
if filename != "" {
@@ -392,20 +407,39 @@
ctx.PropertyErrorf("symlinks", "symlinks cannot be set when using srcs")
}
if p.properties.Filename_from_src != nil {
- ctx.PropertyErrorf("filename_from_src", "filename_from_src is implicitly set to true when using srcs")
+ if len(dstsProperty) > 0 {
+ ctx.PropertyErrorf("filename_from_src", "dsts is set. Cannot set filename_from_src")
+ } else {
+ ctx.PropertyErrorf("filename_from_src", "filename_from_src is implicitly set to true when using srcs")
+ }
}
p.sourceFilePaths = android.PathsForModuleSrc(ctx, srcsProperty)
- for _, src := range p.sourceFilePaths {
- filename := src.Base()
+ if len(dstsProperty) > 0 && len(p.sourceFilePaths) != len(dstsProperty) {
+ ctx.PropertyErrorf("dsts", "Must have one entry in dsts per source file")
+ }
+ for i, src := range p.sourceFilePaths {
+ var filename string
+ var installDirPath android.InstallPath
+
+ if len(dstsProperty) > 0 {
+ var dstdir string
+
+ dstdir, filename = filepath.Split(dstsProperty[i])
+ installDirPath = baseInstallDirPath.Join(ctx, dstdir)
+ } else {
+ filename = src.Base()
+ installDirPath = baseInstallDirPath
+ }
output := android.PathForModuleOut(ctx, filename).OutputPath
ip := installProperties{
filename: filename,
sourceFilePath: src,
outputFilePath: output,
- installDirPath: p.installDirPath,
+ installDirPath: installDirPath,
}
p.outputFilePaths = append(p.outputFilePaths, output)
installs = append(installs, ip)
+ p.installDirPaths = append(p.installDirPaths, installDirPath)
}
} else if ctx.Config().AllowMissingDependencies() {
// If no srcs was set and AllowMissingDependencies is enabled then
@@ -421,9 +455,10 @@
filename: filename,
sourceFilePath: p.sourceFilePaths[0],
outputFilePath: p.outputFilePaths[0],
- installDirPath: p.installDirPath,
+ installDirPath: baseInstallDirPath,
}
installs = append(installs, ip)
+ p.installDirPaths = append(p.installDirPaths, baseInstallDirPath)
} else {
ctx.PropertyErrorf("src", "missing prebuilt source file")
return
@@ -493,7 +528,7 @@
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_MODULE_TAGS", "optional")
- entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.String())
+ entries.SetString("LOCAL_MODULE_PATH", p.installDirPaths[0].String())
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePaths[0].Base())
if len(p.properties.Symlinks) > 0 {
entries.AddStrings("LOCAL_MODULE_SYMLINKS", p.properties.Symlinks...)
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index e739afe..75c6d12 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -119,6 +119,113 @@
android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[2].Base())
}
+func TestPrebuiltEtcDsts(t *testing.T) {
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
+ prebuilt_etc {
+ name: "foo",
+ srcs: ["foo.conf", "bar.conf"],
+ dsts: ["foodir/foo.conf", "bardir/extradir/different.name"],
+ }
+ `)
+
+ p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
+ android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[0].Base())
+ android.AssertStringEquals(t, "output file path", "different.name", p.outputFilePaths[1].Base())
+
+ expectedPaths := [...]string{
+ "out/soong/target/product/test_device/system/etc/foodir",
+ "out/soong/target/product/test_device/system/etc/bardir/extradir",
+ }
+ android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[0], p.installDirPaths[0])
+ android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[1], p.installDirPaths[1])
+}
+
+func TestPrebuiltEtcDstsPlusRelativeInstallPath(t *testing.T) {
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
+ prebuilt_etc {
+ name: "foo",
+ srcs: ["foo.conf", "bar.conf"],
+ dsts: ["foodir/foo.conf", "bardir/extradir/different.name"],
+ relative_install_path: "somewhere",
+ }
+ `)
+
+ p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
+ android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[0].Base())
+ android.AssertStringEquals(t, "output file path", "different.name", p.outputFilePaths[1].Base())
+
+ expectedPaths := [...]string{
+ "out/soong/target/product/test_device/system/etc/somewhere/foodir",
+ "out/soong/target/product/test_device/system/etc/somewhere/bardir/extradir",
+ }
+ android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[0], p.installDirPaths[0])
+ android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[1], p.installDirPaths[1])
+}
+
+func TestPrebuiltEtcDstsSrcGlob(t *testing.T) {
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
+ prebuilt_etc {
+ name: "foo",
+ srcs: ["*.conf"],
+ dsts: ["a.conf", "b.conf", "c.conf"],
+ }
+ `)
+
+ p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
+ android.AssertStringEquals(t, "output file path", "a.conf", p.outputFilePaths[0].Base())
+ android.AssertStringEquals(t, "output file path", "b.conf", p.outputFilePaths[1].Base())
+ android.AssertStringEquals(t, "output file path", "c.conf", p.outputFilePaths[2].Base())
+}
+
+func TestPrebuiltEtcDstsSrcGlobDstsTooShort(t *testing.T) {
+ prepareForPrebuiltEtcTest.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("Must have one entry in dsts per source file")).
+ RunTestWithBp(t, `
+ prebuilt_etc {
+ name: "foo",
+ srcs: ["*.conf"],
+ dsts: ["a.conf", "b.conf"],
+ }
+ `)
+}
+
+func TestPrebuiltEtcDstsSrcGlobDstsTooLong(t *testing.T) {
+ prepareForPrebuiltEtcTest.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("Must have one entry in dsts per source file")).
+ RunTestWithBp(t, `
+ prebuilt_etc {
+ name: "foo",
+ srcs: ["*.conf"],
+ dsts: ["a.conf", "b.conf", "c.conf", "d.conf"],
+ }
+ `)
+}
+
+func TestPrebuiltEtcCannotDstsWithSrc(t *testing.T) {
+ prepareForPrebuiltEtcTest.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("dsts is set. Must use srcs")).
+ RunTestWithBp(t, `
+ prebuilt_etc {
+ name: "foo.conf",
+ src: "foo.conf",
+ dsts: ["a.conf"],
+ }
+ `)
+}
+
+func TestPrebuiltEtcCannotDstsWithFilenameFromSrc(t *testing.T) {
+ prepareForPrebuiltEtcTest.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("dsts is set. Cannot set filename_from_src")).
+ RunTestWithBp(t, `
+ prebuilt_etc {
+ name: "foo.conf",
+ srcs: ["foo.conf"],
+ dsts: ["a.conf"],
+ filename_from_src: true,
+ }
+ `)
+}
+
func TestPrebuiltEtcAndroidMk(t *testing.T) {
result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_etc {
@@ -165,7 +272,7 @@
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := "out/soong/target/product/test_device/system/etc/bar"
- android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
func TestPrebuiltEtcCannotSetRelativeInstallPathAndSubDir(t *testing.T) {
@@ -231,7 +338,7 @@
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := "out/soong/target/product/test_device/system"
- android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
func TestPrebuiltRootInstallDirPathValidate(t *testing.T) {
@@ -256,7 +363,7 @@
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := "out/soong/target/product/test_device/root/avb"
- android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
func TestPrebuiltAvdInstallDirPathValidate(t *testing.T) {
@@ -280,7 +387,7 @@
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := "out/soong/target/product/test_device/system/usr/share/bar"
- android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
func TestPrebuiltUserShareHostInstallDirPath(t *testing.T) {
@@ -295,7 +402,7 @@
buildOS := result.Config.BuildOS.String()
p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc)
expected := filepath.Join("out/soong/host", result.Config.PrebuiltOS(), "usr", "share", "bar")
- android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
func TestPrebuiltPrebuiltUserHyphenDataInstallDirPath(t *testing.T) {
@@ -309,7 +416,7 @@
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := "out/soong/target/product/test_device/system/usr/hyphen-data/bar"
- android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
func TestPrebuiltPrebuiltUserKeyLayoutInstallDirPath(t *testing.T) {
@@ -323,7 +430,7 @@
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := "out/soong/target/product/test_device/system/usr/keylayout/bar"
- android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
func TestPrebuiltPrebuiltUserKeyCharsInstallDirPath(t *testing.T) {
@@ -337,7 +444,7 @@
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := "out/soong/target/product/test_device/system/usr/keychars/bar"
- android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
func TestPrebuiltPrebuiltUserIdcInstallDirPath(t *testing.T) {
@@ -351,7 +458,7 @@
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := "out/soong/target/product/test_device/system/usr/idc/bar"
- android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
func TestPrebuiltFontInstallDirPath(t *testing.T) {
@@ -364,7 +471,7 @@
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := "out/soong/target/product/test_device/system/fonts"
- android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
func TestPrebuiltOverlayInstallDirPath(t *testing.T) {
@@ -377,7 +484,7 @@
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
expected := "out/soong/target/product/test_device/system/overlay"
- android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
func TestPrebuiltFirmwareDirPath(t *testing.T) {
@@ -409,7 +516,7 @@
t.Run(tt.description, func(t *testing.T) {
result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPaths[0])
})
}
}
@@ -443,7 +550,7 @@
t.Run(tt.description, func(t *testing.T) {
result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPaths[0])
})
}
}
@@ -477,7 +584,7 @@
t.Run(tt.description, func(t *testing.T) {
result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPaths[0])
})
}
}
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index a08f7cf..23ec3da 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -16,6 +16,7 @@
],
srcs: [
"aconfig_files.go",
+ "android_device.go",
"avb_add_hash_footer.go",
"avb_gen_vbmeta_image.go",
"bootimg.go",
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
new file mode 100644
index 0000000..68e6053
--- /dev/null
+++ b/filesystem/android_device.go
@@ -0,0 +1,73 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package filesystem
+
+import (
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+type PartitionNameProperties struct {
+ // Name of the Boot_partition_name partition filesystem module
+ Boot_partition_name *string
+ // Name of the System partition filesystem module
+ System_partition_name *string
+ // Name of the System_ext partition filesystem module
+ System_ext_partition_name *string
+ // Name of the Product partition filesystem module
+ Product_partition_name *string
+ // Name of the Vendor partition filesystem module
+ Vendor_partition_name *string
+}
+
+type androidDevice struct {
+ android.ModuleBase
+
+ partitionProps PartitionNameProperties
+}
+
+func AndroidDeviceFactory() android.Module {
+ module := &androidDevice{}
+ module.AddProperties(&module.partitionProps)
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+
+ return module
+}
+
+type partitionDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var filesystemDepTag partitionDepTagType
+
+func (a *androidDevice) DepsMutator(ctx android.BottomUpMutatorContext) {
+ addDependencyIfDefined := func(dep *string) {
+ if dep != nil {
+ ctx.AddDependency(ctx.Module(), filesystemDepTag, proptools.String(dep))
+ }
+ }
+
+ addDependencyIfDefined(a.partitionProps.Boot_partition_name)
+ addDependencyIfDefined(a.partitionProps.System_partition_name)
+ addDependencyIfDefined(a.partitionProps.System_ext_partition_name)
+ addDependencyIfDefined(a.partitionProps.Product_partition_name)
+ addDependencyIfDefined(a.partitionProps.Vendor_partition_name)
+}
+
+func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+
+}
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index e796ab9..9d93925 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -75,7 +75,7 @@
// Path to the private key that avbtool will use to sign this filesystem image.
// TODO(jiyong): allow apex_key to be specified here
- Avb_private_key *string `android:"path"`
+ Avb_private_key *string `android:"path_device_first"`
// Hash and signing algorithm for avbtool. Default is SHA256_RSA4096.
Avb_algorithm *string
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 09d8fba..ca0a7f7 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -92,7 +92,7 @@
// Name of the partition stored in vbmeta desc. Defaults to the name of this module.
Partition_name *string
- // Type of the filesystem. Currently, ext4, cpio, and compressed_cpio are supported. Default
+ // Type of the filesystem. Currently, ext4, erofs, cpio, and compressed_cpio are supported. Default
// is ext4.
Type *string
@@ -143,6 +143,24 @@
// build modules, where we want to emit some not-yet-working filesystems and we don't want them
// to be built.
Unchecked_module *bool `blueprint:"mutated"`
+
+ Erofs ErofsProperties
+
+ // Determines if the module is auto-generated from Soong or not. If the module is
+ // auto-generated, its deps are exempted from visibility enforcement.
+ Is_auto_generated *bool
+}
+
+// Additional properties required to generate erofs FS partitions.
+type ErofsProperties struct {
+ // Compressor and Compression level passed to mkfs.erofs. e.g. (lz4hc,9)
+ // Please see external/erofs-utils/README for complete documentation.
+ Compressor *string
+
+ // Used as --compress-hints for mkfs.erofs
+ Compress_hints *string `android:"path"`
+
+ Sparse *bool
}
// android_filesystem packages a set of modules and their transitive dependencies into a filesystem
@@ -165,24 +183,45 @@
android.InitDefaultableModule(module)
}
-var dependencyTag = struct {
+type depTag struct {
blueprint.BaseDependencyTag
android.PackagingItemAlwaysDepTag
-}{}
+}
+
+var dependencyTag = depTag{}
+
+type depTagWithVisibilityEnforcementBypass struct {
+ depTag
+}
+
+var _ android.ExcludeFromVisibilityEnforcementTag = (*depTagWithVisibilityEnforcementBypass)(nil)
+
+func (t depTagWithVisibilityEnforcementBypass) ExcludeFromVisibilityEnforcement() {}
+
+var dependencyTagWithVisibilityEnforcementBypass = depTagWithVisibilityEnforcementBypass{}
func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) {
- f.AddDeps(ctx, dependencyTag)
+ if proptools.Bool(f.properties.Is_auto_generated) {
+ f.AddDeps(ctx, dependencyTagWithVisibilityEnforcementBypass)
+ } else {
+ f.AddDeps(ctx, dependencyTag)
+ }
}
type fsType int
const (
ext4Type fsType = iota
+ erofsType
compressedCpioType
cpioType // uncompressed
unknown
)
+func (fs fsType) IsUnknown() bool {
+ return fs == unknown
+}
+
type FilesystemInfo struct {
// A text file containing the list of paths installed on the partition.
FileListFile android.Path
@@ -190,21 +229,30 @@
var FilesystemProvider = blueprint.NewProvider[FilesystemInfo]()
-func (f *filesystem) fsType(ctx android.ModuleContext) fsType {
- typeStr := proptools.StringDefault(f.properties.Type, "ext4")
+func GetFsTypeFromString(ctx android.EarlyModuleContext, typeStr string) fsType {
switch typeStr {
case "ext4":
return ext4Type
+ case "erofs":
+ return erofsType
case "compressed_cpio":
return compressedCpioType
case "cpio":
return cpioType
default:
- ctx.PropertyErrorf("type", "%q not supported", typeStr)
return unknown
}
}
+func (f *filesystem) fsType(ctx android.ModuleContext) fsType {
+ typeStr := proptools.StringDefault(f.properties.Type, "ext4")
+ fsType := GetFsTypeFromString(ctx, typeStr)
+ if fsType == unknown {
+ ctx.PropertyErrorf("type", "%q not supported", typeStr)
+ }
+ return fsType
+}
+
func (f *filesystem) installFileName() string {
return f.BaseModuleName() + ".img"
}
@@ -216,6 +264,9 @@
func (f *filesystem) filterInstallablePackagingSpec(ps android.PackagingSpec) bool {
// Filesystem module respects the installation semantic. A PackagingSpec from a module with
// IsSkipInstall() is skipped.
+ if proptools.Bool(f.properties.Is_auto_generated) { // TODO (spandandas): Remove this.
+ return !ps.SkipInstall() && (ps.Partition() == f.PartitionType())
+ }
return !ps.SkipInstall()
}
@@ -224,7 +275,7 @@
func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
validatePartitionType(ctx, f)
switch f.fsType(ctx) {
- case ext4Type:
+ case ext4Type, erofsType:
f.output = f.buildImageUsingBuildImage(ctx)
case compressedCpioType:
f.output = f.buildCpioImage(ctx, true)
@@ -434,9 +485,11 @@
// Type string that build_image.py accepts.
fsTypeStr := func(t fsType) string {
switch t {
- // TODO(jiyong): add more types like f2fs, erofs, etc.
+ // TODO(372522486): add more types like f2fs, erofs, etc.
case ext4Type:
return "ext4"
+ case erofsType:
+ return "erofs"
}
panic(fmt.Errorf("unsupported fs type %v", t))
}
@@ -486,6 +539,24 @@
addStr("uuid", uuid)
addStr("hash_seed", uuid)
}
+ // Add erofs properties
+ if f.fsType(ctx) == erofsType {
+ if compressor := f.properties.Erofs.Compressor; compressor != nil {
+ addStr("erofs_default_compressor", proptools.String(compressor))
+ }
+ if compressHints := f.properties.Erofs.Compress_hints; compressHints != nil {
+ addPath("erofs_default_compress_hints", android.PathForModuleSrc(ctx, *compressHints))
+ }
+ if proptools.BoolDefault(f.properties.Erofs.Sparse, true) {
+ // https://source.corp.google.com/h/googleplex-android/platform/build/+/88b1c67239ca545b11580237242774b411f2fed9:core/Makefile;l=2292;bpv=1;bpt=0;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b
+ addStr("erofs_sparse_flag", "-s")
+ }
+ } else if f.properties.Erofs.Compressor != nil || f.properties.Erofs.Compress_hints != nil || f.properties.Erofs.Sparse != nil {
+ // Raise an exception if the propfile contains erofs properties, but the fstype is not erofs
+ fs := fsTypeStr(f.fsType(ctx))
+ ctx.PropertyErrorf("erofs", "erofs is non-empty, but FS type is %s\n. Please delete erofs properties if this partition should use %s\n", fs, fs)
+ }
+
propFile = android.PathForModuleOut(ctx, "prop").OutputPath
android.WriteFileRuleVerbatim(ctx, propFile, propFileString.String())
return propFile, deps
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 8c0d111..ab63550 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -559,3 +559,73 @@
}
}
}
+
+func TestErofsPartition(t *testing.T) {
+ result := fixture.RunTestWithBp(t, `
+ android_filesystem {
+ name: "erofs_partition",
+ type: "erofs",
+ erofs: {
+ compressor: "lz4hc,9",
+ compress_hints: "compress_hints.txt",
+ },
+ deps: ["binfoo"],
+ }
+
+ cc_binary {
+ name: "binfoo",
+ }
+ `)
+
+ partition := result.ModuleForTests("erofs_partition", "android_common")
+ buildImageConfig := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("prop"))
+ android.AssertStringDoesContain(t, "erofs fs type", buildImageConfig, "fs_type=erofs")
+ android.AssertStringDoesContain(t, "erofs fs type compress algorithm", buildImageConfig, "erofs_default_compressor=lz4hc,9")
+ android.AssertStringDoesContain(t, "erofs fs type compress hint", buildImageConfig, "erofs_default_compress_hints=compress_hints.txt")
+ android.AssertStringDoesContain(t, "erofs fs type sparse", buildImageConfig, "erofs_sparse_flag=-s")
+}
+
+// If a system_ext/ module depends on system/ module, the dependency should *not*
+// be installed in system_ext/
+func TestDoNotPackageCrossPartitionDependencies(t *testing.T) {
+ t.Skip() // TODO (spandandas): Re-enable this
+ result := fixture.RunTestWithBp(t, `
+ android_filesystem {
+ name: "myfilesystem",
+ deps: ["binfoo"],
+ partition_type: "system_ext",
+ }
+
+ cc_binary {
+ name: "binfoo",
+ shared_libs: ["libfoo"],
+ system_ext_specific: true,
+ }
+ cc_library_shared {
+ name: "libfoo", // installed in system/
+ }
+ `)
+
+ partition := result.ModuleForTests("myfilesystem", "android_common")
+ fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList"))
+ android.AssertDeepEquals(t, "filesystem with dependencies on different partition", "bin/binfoo\n", fileList)
+}
+
+// If a cc_library is listed in `deps`, and it has a shared and static variant, then the shared variant
+// should be installed.
+func TestUseSharedVariationOfNativeLib(t *testing.T) {
+ result := fixture.RunTestWithBp(t, `
+ android_filesystem {
+ name: "myfilesystem",
+ deps: ["libfoo"],
+ }
+ // cc_library will create a static and shared variant.
+ cc_library {
+ name: "libfoo",
+ }
+ `)
+
+ partition := result.ModuleForTests("myfilesystem", "android_common")
+ fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList"))
+ android.AssertDeepEquals(t, "cc_library listed in deps", "lib64/libc++.so\nlib64/libc.so\nlib64/libdl.so\nlib64/libfoo.so\nlib64/libm.so\n", fileList)
+}
diff --git a/filesystem/fsverity_metadata.go b/filesystem/fsverity_metadata.go
index d7bb654..199c845 100644
--- a/filesystem/fsverity_metadata.go
+++ b/filesystem/fsverity_metadata.go
@@ -15,6 +15,7 @@
package filesystem
import (
+ "fmt"
"path/filepath"
"strings"
@@ -121,8 +122,13 @@
// STEP 2-2: generate BuildManifest.apk (unsigned)
aapt2Path := ctx.Config().HostToolPath(ctx, "aapt2")
- apkPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", "BuildManifest.apk")
- idsigPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", "BuildManifest.apk.idsig")
+ apkNameSuffix := ""
+ if f.PartitionType() == "system_ext" {
+ //https://source.corp.google.com/h/googleplex-android/platform/build/+/e392d2b486c2d4187b20a72b1c67cc737ecbcca5:core/Makefile;l=3410;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b;bpv=1;bpt=0
+ apkNameSuffix = "SystemExt"
+ }
+ apkPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", fmt.Sprintf("BuildManifest%s.apk", apkNameSuffix))
+ idsigPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", fmt.Sprintf("BuildManifest%s.apk.idsig", apkNameSuffix))
manifestTemplatePath := android.PathForSource(ctx, "system/security/fsverity/AndroidManifest.xml")
libs := android.PathsForModuleSrc(ctx, f.properties.Fsverity.Libs)
cmd.Implicit(aapt2Path)
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index 57239ae..7dbf986 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -103,6 +103,6 @@
// partition. Note that "apex" module installs its contents to "apex"(fake partition) as well
// for symbol lookup by imitating "activated" paths.
func (s *systemImage) filterPackagingSpec(ps android.PackagingSpec) bool {
- return s.filesystem.filterInstallablePackagingSpec(ps) &&
+ return !ps.SkipInstall() &&
(ps.Partition() == "system" || ps.Partition() == "root")
}
diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go
index 1d64796..51ba7c9 100644
--- a/filesystem/vbmeta.go
+++ b/filesystem/vbmeta.go
@@ -98,7 +98,7 @@
func vbmetaFactory() android.Module {
module := &vbmeta{}
module.AddProperties(&module.properties)
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
return module
}
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index a9f4256..fde344b 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -15,13 +15,18 @@
package fsgen
import (
- "android/soong/android"
- "android/soong/filesystem"
"crypto/sha256"
"fmt"
+ "slices"
"strconv"
+ "strings"
+ "sync"
+
+ "android/soong/android"
+ "android/soong/filesystem"
"github.com/google/blueprint"
+ "github.com/google/blueprint/parser"
"github.com/google/blueprint/proptools"
)
@@ -33,6 +38,248 @@
func registerBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("soong_filesystem_creator", filesystemCreatorFactory)
+ ctx.PreDepsMutators(RegisterCollectFileSystemDepsMutators)
+}
+
+func RegisterCollectFileSystemDepsMutators(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("fs_collect_deps", collectDepsMutator).MutatesGlobalState()
+ ctx.BottomUp("fs_set_deps", setDepsMutator)
+}
+
+var fsGenStateOnceKey = android.NewOnceKey("FsGenState")
+
+// Map of partition module name to its partition that may be generated by Soong.
+// Note that it is not guaranteed that all modules returned by this function are successfully
+// created.
+func getAllSoongGeneratedPartitionNames(config android.Config, partitions []string) map[string]string {
+ ret := map[string]string{}
+ for _, partition := range partitions {
+ ret[generatedModuleNameForPartition(config, partition)] = partition
+ }
+ return ret
+}
+
+type depCandidateProps struct {
+ Namespace string
+ Multilib string
+ Arch []android.ArchType
+}
+
+// Map of module name to depCandidateProps
+type multilibDeps *map[string]*depCandidateProps
+
+// Information necessary to generate the filesystem modules, including details about their
+// dependencies
+type FsGenState struct {
+ // List of modules in `PRODUCT_PACKAGES` and `PRODUCT_PACKAGES_DEBUG`
+ depCandidates []string
+ // Map of names of partition to the information of modules to be added as deps
+ fsDeps map[string]multilibDeps
+ // List of name of partitions to be generated by the filesystem_creator module
+ soongGeneratedPartitions []string
+ // Mutex to protect the fsDeps
+ fsDepsMutex sync.Mutex
+}
+
+func newMultilibDeps() multilibDeps {
+ return &map[string]*depCandidateProps{}
+}
+
+func defaultDepCandidateProps(config android.Config) *depCandidateProps {
+ return &depCandidateProps{
+ Namespace: ".",
+ Arch: []android.ArchType{config.BuildArch},
+ }
+}
+
+func createFsGenState(ctx android.LoadHookContext) *FsGenState {
+ return ctx.Config().Once(fsGenStateOnceKey, func() interface{} {
+ partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
+ candidates := android.FirstUniqueStrings(android.Concat(partitionVars.ProductPackages, partitionVars.ProductPackagesDebug))
+
+ generatedPartitions := []string{"system"}
+ if ctx.DeviceConfig().SystemExtPath() == "system_ext" {
+ generatedPartitions = append(generatedPartitions, "system_ext")
+ }
+ if ctx.DeviceConfig().BuildingVendorImage() && ctx.DeviceConfig().VendorPath() == "vendor" {
+ generatedPartitions = append(generatedPartitions, "vendor")
+ }
+ if ctx.DeviceConfig().BuildingProductImage() && ctx.DeviceConfig().ProductPath() == "product" {
+ generatedPartitions = append(generatedPartitions, "product")
+ }
+
+ return &FsGenState{
+ depCandidates: candidates,
+ fsDeps: map[string]multilibDeps{
+ // These additional deps are added according to the cuttlefish system image bp.
+ "system": &map[string]*depCandidateProps{
+ "com.android.apex.cts.shim.v1_prebuilt": defaultDepCandidateProps(ctx.Config()),
+ "dex_bootjars": defaultDepCandidateProps(ctx.Config()),
+ "framework_compatibility_matrix.device.xml": defaultDepCandidateProps(ctx.Config()),
+ "idc_data": defaultDepCandidateProps(ctx.Config()),
+ "init.environ.rc-soong": defaultDepCandidateProps(ctx.Config()),
+ "keychars_data": defaultDepCandidateProps(ctx.Config()),
+ "keylayout_data": defaultDepCandidateProps(ctx.Config()),
+ "libclang_rt.asan": defaultDepCandidateProps(ctx.Config()),
+ "libcompiler_rt": defaultDepCandidateProps(ctx.Config()),
+ "libdmabufheap": defaultDepCandidateProps(ctx.Config()),
+ "libgsi": defaultDepCandidateProps(ctx.Config()),
+ "llndk.libraries.txt": defaultDepCandidateProps(ctx.Config()),
+ "logpersist.start": defaultDepCandidateProps(ctx.Config()),
+ "preloaded-classes": defaultDepCandidateProps(ctx.Config()),
+ "public.libraries.android.txt": defaultDepCandidateProps(ctx.Config()),
+ "update_engine_sideload": defaultDepCandidateProps(ctx.Config()),
+ },
+ "vendor": newMultilibDeps(),
+ "odm": newMultilibDeps(),
+ "product": newMultilibDeps(),
+ "system_ext": &map[string]*depCandidateProps{
+ // VNDK apexes are automatically included.
+ // This hardcoded list will need to be updated if `PRODUCT_EXTRA_VNDK_VERSIONS` is updated.
+ // https://cs.android.com/android/_/android/platform/build/+/adba533072b00c53ac0f198c550a3cbd7a00e4cd:core/main.mk;l=984;bpv=1;bpt=0;drc=174db7b179592cf07cbfd2adb0119486fda911e7
+ "com.android.vndk.v30": defaultDepCandidateProps(ctx.Config()),
+ "com.android.vndk.v31": defaultDepCandidateProps(ctx.Config()),
+ "com.android.vndk.v32": defaultDepCandidateProps(ctx.Config()),
+ "com.android.vndk.v33": defaultDepCandidateProps(ctx.Config()),
+ "com.android.vndk.v34": defaultDepCandidateProps(ctx.Config()),
+ },
+ },
+ soongGeneratedPartitions: generatedPartitions,
+ fsDepsMutex: sync.Mutex{},
+ }
+ }).(*FsGenState)
+}
+
+func checkDepModuleInMultipleNamespaces(mctx android.BottomUpMutatorContext, foundDeps map[string]*depCandidateProps, module string, partitionName string) {
+ otherNamespace := mctx.Namespace().Path
+ if val, found := foundDeps[module]; found && otherNamespace != "." && !android.InList(val.Namespace, []string{".", otherNamespace}) {
+ mctx.ModuleErrorf("found in multiple namespaces(%s and %s) when including in %s partition", val.Namespace, otherNamespace, partitionName)
+ }
+}
+
+func appendDepIfAppropriate(mctx android.BottomUpMutatorContext, deps *map[string]*depCandidateProps, installPartition string) {
+ checkDepModuleInMultipleNamespaces(mctx, *deps, mctx.Module().Name(), installPartition)
+ if _, ok := (*deps)[mctx.Module().Name()]; ok {
+ // Prefer the namespace-specific module over the platform module
+ if mctx.Namespace().Path != "." {
+ (*deps)[mctx.Module().Name()].Namespace = mctx.Namespace().Path
+ }
+ (*deps)[mctx.Module().Name()].Arch = append((*deps)[mctx.Module().Name()].Arch, mctx.Module().Target().Arch.ArchType)
+ } else {
+ multilib, _ := mctx.Module().DecodeMultilib(mctx)
+ (*deps)[mctx.Module().Name()] = &depCandidateProps{
+ Namespace: mctx.Namespace().Path,
+ Multilib: multilib,
+ Arch: []android.ArchType{mctx.Module().Target().Arch.ArchType},
+ }
+ }
+}
+
+func collectDepsMutator(mctx android.BottomUpMutatorContext) {
+ fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
+
+ m := mctx.Module()
+ if m.Target().Os.Class == android.Device && slices.Contains(fsGenState.depCandidates, m.Name()) {
+ installPartition := m.PartitionTag(mctx.DeviceConfig())
+ fsGenState.fsDepsMutex.Lock()
+ // Only add the module as dependency when:
+ // - its enabled
+ // - its namespace is included in PRODUCT_SOONG_NAMESPACES
+ if m.Enabled(mctx) && m.ExportedToMake() {
+ appendDepIfAppropriate(mctx, fsGenState.fsDeps[installPartition], installPartition)
+ }
+ fsGenState.fsDepsMutex.Unlock()
+ }
+}
+
+type depsStruct struct {
+ Deps []string
+}
+
+type multilibDepsStruct struct {
+ Common depsStruct
+ Lib32 depsStruct
+ Lib64 depsStruct
+ Both depsStruct
+ Prefer32 depsStruct
+}
+
+type packagingPropsStruct struct {
+ Deps []string
+ Multilib multilibDepsStruct
+}
+
+func fullyQualifiedModuleName(moduleName, namespace string) string {
+ if namespace == "." {
+ return moduleName
+ }
+ return fmt.Sprintf("//%s:%s", namespace, moduleName)
+}
+
+func getBitness(archTypes []android.ArchType) (ret []string) {
+ for _, archType := range archTypes {
+ if archType.Multilib == "" {
+ ret = append(ret, android.COMMON_VARIANT)
+ } else {
+ ret = append(ret, archType.Bitness())
+ }
+ }
+ return ret
+}
+
+func setDepsMutator(mctx android.BottomUpMutatorContext) {
+ fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
+ fsDeps := fsGenState.fsDeps
+ soongGeneratedPartitionMap := getAllSoongGeneratedPartitionNames(mctx.Config(), fsGenState.soongGeneratedPartitions)
+ m := mctx.Module()
+ if partition, ok := soongGeneratedPartitionMap[m.Name()]; ok {
+ depsStruct := generateDepStruct(*fsDeps[partition])
+ if err := proptools.AppendMatchingProperties(m.GetProperties(), depsStruct, nil); err != nil {
+ mctx.ModuleErrorf(err.Error())
+ }
+ }
+}
+
+func generateDepStruct(deps map[string]*depCandidateProps) *packagingPropsStruct {
+ depsStruct := packagingPropsStruct{}
+ for depName, depProps := range deps {
+ bitness := getBitness(depProps.Arch)
+ fullyQualifiedDepName := fullyQualifiedModuleName(depName, depProps.Namespace)
+ if android.InList("32", bitness) && android.InList("64", bitness) {
+ // If both 32 and 64 bit variants are enabled for this module
+ switch depProps.Multilib {
+ case string(android.MultilibBoth):
+ depsStruct.Multilib.Both.Deps = append(depsStruct.Multilib.Both.Deps, fullyQualifiedDepName)
+ case string(android.MultilibCommon), string(android.MultilibFirst):
+ depsStruct.Deps = append(depsStruct.Deps, fullyQualifiedDepName)
+ case "32":
+ depsStruct.Multilib.Lib32.Deps = append(depsStruct.Multilib.Lib32.Deps, fullyQualifiedDepName)
+ case "64", "darwin_universal":
+ depsStruct.Multilib.Lib64.Deps = append(depsStruct.Multilib.Lib64.Deps, fullyQualifiedDepName)
+ case "prefer32", "first_prefer32":
+ depsStruct.Multilib.Prefer32.Deps = append(depsStruct.Multilib.Prefer32.Deps, fullyQualifiedDepName)
+ default:
+ depsStruct.Multilib.Both.Deps = append(depsStruct.Multilib.Both.Deps, fullyQualifiedDepName)
+ }
+ } else if android.InList("64", bitness) {
+ // If only 64 bit variant is enabled
+ depsStruct.Multilib.Lib64.Deps = append(depsStruct.Multilib.Lib64.Deps, fullyQualifiedDepName)
+ } else if android.InList("32", bitness) {
+ // If only 32 bit variant is enabled
+ depsStruct.Multilib.Lib32.Deps = append(depsStruct.Multilib.Lib32.Deps, fullyQualifiedDepName)
+ } else {
+ // If only common variant is enabled
+ depsStruct.Multilib.Common.Deps = append(depsStruct.Multilib.Common.Deps, fullyQualifiedDepName)
+ }
+ }
+ depsStruct.Deps = android.SortedUniqueStrings(depsStruct.Deps)
+ depsStruct.Multilib.Lib32.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Lib32.Deps)
+ depsStruct.Multilib.Lib64.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Lib64.Deps)
+ depsStruct.Multilib.Prefer32.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Prefer32.Deps)
+ depsStruct.Multilib.Both.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Both.Deps)
+ depsStruct.Multilib.Common.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Common.Deps)
+
+ return &depsStruct
}
type filesystemCreatorProps struct {
@@ -49,9 +296,10 @@
func filesystemCreatorFactory() android.Module {
module := &filesystemCreator{}
- android.InitAndroidModule(module)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
module.AddProperties(&module.properties)
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ createFsGenState(ctx)
module.createInternalModules(ctx)
})
@@ -59,41 +307,123 @@
}
func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) {
- for _, partitionType := range []string{"system"} {
+ soongGeneratedPartitions := &ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions
+ for _, partitionType := range *soongGeneratedPartitions {
if f.createPartition(ctx, partitionType) {
f.properties.Generated_partition_types = append(f.properties.Generated_partition_types, partitionType)
} else {
f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, partitionType)
+ _, *soongGeneratedPartitions = android.RemoveFromList(partitionType, *soongGeneratedPartitions)
}
}
+ f.createDeviceModule(ctx)
}
-func (f *filesystemCreator) generatedModuleNameForPartition(cfg android.Config, partitionType string) string {
+func generatedModuleName(cfg android.Config, suffix string) string {
prefix := "soong"
if cfg.HasDeviceProduct() {
prefix = cfg.DeviceProduct()
}
- return fmt.Sprintf("%s_generated_%s_image", prefix, partitionType)
+ return fmt.Sprintf("%s_generated_%s", prefix, suffix)
+}
+
+func generatedModuleNameForPartition(cfg android.Config, partitionType string) string {
+ return generatedModuleName(cfg, fmt.Sprintf("%s_image", partitionType))
+}
+
+func (f *filesystemCreator) createDeviceModule(ctx android.LoadHookContext) {
+ baseProps := &struct {
+ Name *string
+ }{
+ Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "device")),
+ }
+
+ // Currently, only the system and system_ext partition module is created.
+ partitionProps := &filesystem.PartitionNameProperties{}
+ if android.InList("system", f.properties.Generated_partition_types) {
+ partitionProps.System_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
+ }
+ if android.InList("system_ext", f.properties.Generated_partition_types) {
+ partitionProps.System_ext_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
+ }
+ if android.InList("vendor", f.properties.Generated_partition_types) {
+ partitionProps.Vendor_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor"))
+ }
+ if android.InList("product", f.properties.Generated_partition_types) {
+ partitionProps.Product_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "product"))
+ }
+
+ ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps)
+}
+
+func partitionSpecificFsProps(fsProps *filesystem.FilesystemProperties, partitionType string) {
+ switch partitionType {
+ case "system":
+ fsProps.Build_logtags = proptools.BoolPtr(true)
+ // https://source.corp.google.com/h/googleplex-android/platform/build//639d79f5012a6542ab1f733b0697db45761ab0f3:core/packaging/flags.mk;l=21;drc=5ba8a8b77507f93aa48cc61c5ba3f31a4d0cbf37;bpv=1;bpt=0
+ fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
+ case "product":
+ fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
+ case "vendor":
+ fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
+ }
}
// Creates a soong module to build the given partition. Returns false if we can't support building
// it.
func (f *filesystemCreator) createPartition(ctx android.LoadHookContext, partitionType string) bool {
- baseProps := &struct {
- Name *string
- }{
- Name: proptools.StringPtr(f.generatedModuleNameForPartition(ctx.Config(), partitionType)),
+ baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType)))
+
+ fsProps, supported := generateFsProps(ctx, partitionType)
+ if !supported {
+ return false
}
+ var module android.Module
+ if partitionType == "system" {
+ module = ctx.CreateModule(filesystem.SystemImageFactory, baseProps, fsProps)
+ } else {
+ // Explicitly set the partition.
+ fsProps.Partition_type = proptools.StringPtr(partitionType)
+ module = ctx.CreateModule(filesystem.FilesystemFactory, baseProps, fsProps)
+ }
+ module.HideFromMake()
+ return true
+}
+
+type filesystemBaseProperty struct {
+ Name *string
+ Compile_multilib *string
+}
+
+func generateBaseProps(namePtr *string) *filesystemBaseProperty {
+ return &filesystemBaseProperty{
+ Name: namePtr,
+ Compile_multilib: proptools.StringPtr("both"),
+ }
+}
+
+func generateFsProps(ctx android.EarlyModuleContext, partitionType string) (*filesystem.FilesystemProperties, bool) {
fsProps := &filesystem.FilesystemProperties{}
+ partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
+ specificPartitionVars := partitionVars.PartitionQualifiedVariables[partitionType]
+
+ // BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE
+ fsType := specificPartitionVars.BoardFileSystemType
+ if fsType == "" {
+ fsType = "ext4" //default
+ }
+ fsProps.Type = proptools.StringPtr(fsType)
+ if filesystem.GetFsTypeFromString(ctx, *fsProps.Type).IsUnknown() {
+ // Currently the android_filesystem module type only supports a handful of FS types like ext4, erofs
+ return nil, false
+ }
+
// Don't build this module on checkbuilds, the soong-built partitions are still in-progress
// and sometimes don't build.
fsProps.Unchecked_module = proptools.BoolPtr(true)
- partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
- specificPartitionVars := partitionVars.PartitionQualifiedVariables[partitionType]
-
// BOARD_AVB_ENABLE
fsProps.Use_avb = proptools.BoolPtr(partitionVars.BoardAvbEnable)
// BOARD_AVB_KEY_PATH
@@ -106,17 +436,10 @@
}
fsProps.Partition_name = proptools.StringPtr(partitionType)
- // BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE
- fsProps.Type = proptools.StringPtr(specificPartitionVars.BoardFileSystemType)
- if *fsProps.Type != "ext4" {
- // Currently the android_filesystem module type only supports ext4:
- // https://cs.android.com/android/platform/superproject/main/+/main:build/soong/filesystem/filesystem.go;l=416;drc=98047cfd07944b297a12d173453bc984806760d2
- return false
- }
fsProps.Base_dir = proptools.StringPtr(partitionType)
- fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
+ fsProps.Is_auto_generated = proptools.BoolPtr(true)
// Identical to that of the generic_system_image
fsProps.Fsverity.Inputs = []string{
@@ -128,6 +451,9 @@
"framework/*/*", // framework/{arch}
"framework/oat/*/*", // framework/oat/{arch}
}
+ fsProps.Fsverity.Libs = []string{":framework-res{.export-package.apk}"}
+
+ partitionSpecificFsProps(fsProps, partitionType)
// system_image properties that are not set:
// - filesystemProperties.Avb_hash_algorithm
@@ -139,20 +465,13 @@
// - filesystemProperties.Mount_point
// - filesystemProperties.Include_make_built_files
// - filesystemProperties.Build_logtags
- // - filesystemProperties.Fsverity.Libs
// - systemImageProperties.Linker_config_src
- var module android.Module
- if partitionType == "system" {
- module = ctx.CreateModule(filesystem.SystemImageFactory, baseProps, fsProps)
- } else {
- module = ctx.CreateModule(filesystem.FilesystemFactory, baseProps, fsProps)
- }
- module.HideFromMake()
- return true
+
+ return fsProps, true
}
func (f *filesystemCreator) createDiffTest(ctx android.ModuleContext, partitionType string) android.Path {
- partitionModuleName := f.generatedModuleNameForPartition(ctx.Config(), partitionType)
+ partitionModuleName := generatedModuleNameForPartition(ctx.Config(), partitionType)
systemImage := ctx.GetDirectDepWithTag(partitionModuleName, generatedFilesystemDepTag)
filesystemInfo, ok := android.OtherModuleProvider(ctx, systemImage, filesystem.FilesystemProvider)
if !ok {
@@ -196,7 +515,7 @@
func (f *filesystemCreator) DepsMutator(ctx android.BottomUpMutatorContext) {
for _, partitionType := range f.properties.Generated_partition_types {
- ctx.AddDependency(ctx.Module(), generatedFilesystemDepTag, f.generatedModuleNameForPartition(ctx.Config(), partitionType))
+ ctx.AddDependency(ctx.Module(), generatedFilesystemDepTag, generatedModuleNameForPartition(ctx.Config(), partitionType))
}
}
@@ -206,12 +525,61 @@
}
f.HideFromMake()
+ var content strings.Builder
+ generatedBp := android.PathForModuleOut(ctx, "soong_generated_product_config.bp")
+ for _, partition := range ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions {
+ content.WriteString(generateBpContent(ctx, partition))
+ content.WriteString("\n")
+ }
+ android.WriteFileRule(ctx, generatedBp, content.String())
+
+ ctx.Phony("product_config_to_bp", generatedBp)
+
var diffTestFiles []android.Path
for _, partitionType := range f.properties.Generated_partition_types {
- diffTestFiles = append(diffTestFiles, f.createDiffTest(ctx, partitionType))
+ diffTestFile := f.createDiffTest(ctx, partitionType)
+ diffTestFiles = append(diffTestFiles, diffTestFile)
+ ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", partitionType), diffTestFile)
}
for _, partitionType := range f.properties.Unsupported_partition_types {
- diffTestFiles = append(diffTestFiles, createFailingCommand(ctx, fmt.Sprintf("Couldn't build %s partition", partitionType)))
+ diffTestFile := createFailingCommand(ctx, fmt.Sprintf("Couldn't build %s partition", partitionType))
+ diffTestFiles = append(diffTestFiles, diffTestFile)
+ ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", partitionType), diffTestFile)
}
ctx.Phony("soong_generated_filesystem_tests", diffTestFiles...)
}
+
+func generateBpContent(ctx android.EarlyModuleContext, partitionType string) string {
+ fsProps, fsTypeSupported := generateFsProps(ctx, partitionType)
+ if !fsTypeSupported {
+ return ""
+ }
+
+ baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType)))
+ deps := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).fsDeps[partitionType]
+ depProps := generateDepStruct(*deps)
+
+ result, err := proptools.RepackProperties([]interface{}{baseProps, fsProps, depProps})
+ if err != nil {
+ ctx.ModuleErrorf(err.Error())
+ }
+
+ moduleType := "android_filesystem"
+ if partitionType == "system" {
+ moduleType = "android_system_image"
+ }
+
+ file := &parser.File{
+ Defs: []parser.Definition{
+ &parser.Module{
+ Type: moduleType,
+ Map: *result,
+ },
+ },
+ }
+ bytes, err := parser.Print(file)
+ if err != nil {
+ ctx.ModuleErrorf(err.Error())
+ }
+ return strings.TrimSpace(string(bytes))
+}
diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go
index 554b66b..484cc38 100644
--- a/fsgen/filesystem_creator_test.go
+++ b/fsgen/filesystem_creator_test.go
@@ -17,6 +17,7 @@
import (
"android/soong/android"
"android/soong/filesystem"
+ "android/soong/java"
"testing"
"github.com/google/blueprint/proptools"
@@ -28,6 +29,7 @@
result := android.GroupFixturePreparers(
android.PrepareForIntegrationTestWithAndroid,
android.PrepareForTestWithAndroidBuildComponents,
+ android.PrepareForTestWithAllowMissingDependencies,
filesystem.PrepareForTestWithFilesystemBuildComponents,
prepareForTestWithFsgenBuildComponents,
android.FixtureModifyConfig(func(config android.Config) {
@@ -86,3 +88,132 @@
proptools.String(fooSystem.FsProps().Type),
)
}
+
+func TestFileSystemCreatorSetPartitionDeps(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.PrepareForTestWithAllowMissingDependencies,
+ filesystem.PrepareForTestWithFilesystemBuildComponents,
+ prepareForTestWithFsgenBuildComponents,
+ java.PrepareForTestWithJavaBuildComponents,
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"bar", "baz"}
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
+ map[string]android.PartitionQualifiedVariablesType{
+ "system": {
+ BoardFileSystemType: "ext4",
+ },
+ }
+ }),
+ android.FixtureMergeMockFs(android.MockFS{
+ "external/avb/test/data/testkey_rsa4096.pem": nil,
+ "build/soong/fsgen/Android.bp": []byte(`
+ soong_filesystem_creator {
+ name: "foo",
+ }
+ `),
+ }),
+ ).RunTestWithBp(t, `
+ java_library {
+ name: "bar",
+ srcs: ["A.java"],
+ }
+ java_library {
+ name: "baz",
+ srcs: ["A.java"],
+ product_specific: true,
+ }
+ `)
+
+ android.AssertBoolEquals(
+ t,
+ "Generated system image expected to depend on system partition installed \"bar\"",
+ true,
+ java.CheckModuleHasDependency(t, result.TestContext, "test_product_generated_system_image", "android_common", "bar"),
+ )
+ android.AssertBoolEquals(
+ t,
+ "Generated system image expected to not depend on product partition installed \"baz\"",
+ false,
+ java.CheckModuleHasDependency(t, result.TestContext, "test_product_generated_system_image", "android_common", "baz"),
+ )
+}
+
+func TestFileSystemCreatorDepsWithNamespace(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.PrepareForTestWithAllowMissingDependencies,
+ android.PrepareForTestWithNamespace,
+ android.PrepareForTestWithArchMutator,
+ filesystem.PrepareForTestWithFilesystemBuildComponents,
+ prepareForTestWithFsgenBuildComponents,
+ java.PrepareForTestWithJavaBuildComponents,
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"bar"}
+ config.TestProductVariables.NamespacesToExport = []string{"a/b"}
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
+ map[string]android.PartitionQualifiedVariablesType{
+ "system": {
+ BoardFileSystemType: "ext4",
+ },
+ }
+ config.Targets[android.Android] = []android.Target{
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: "", HostCross: false},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: "", HostCross: false},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86_64", NativeBridgeRelativePath: "arm64", HostCross: false},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86", NativeBridgeRelativePath: "arm", HostCross: false},
+ }
+ }),
+ android.FixtureMergeMockFs(android.MockFS{
+ "external/avb/test/data/testkey_rsa4096.pem": nil,
+ "build/soong/fsgen/Android.bp": []byte(`
+ soong_filesystem_creator {
+ name: "foo",
+ }
+ `),
+ "a/b/Android.bp": []byte(`
+ soong_namespace{
+ }
+ java_library {
+ name: "bar",
+ srcs: ["A.java"],
+ compile_multilib: "64",
+ }
+ `),
+ "c/d/Android.bp": []byte(`
+ soong_namespace{
+ }
+ java_library {
+ name: "bar",
+ srcs: ["A.java"],
+ }
+ `),
+ }),
+ ).RunTest(t)
+
+ var packagingProps android.PackagingProperties
+ for _, prop := range result.ModuleForTests("test_product_generated_system_image", "android_common").Module().GetProperties() {
+ if packagingPropStruct, ok := prop.(*android.PackagingProperties); ok {
+ packagingProps = *packagingPropStruct
+ }
+ }
+ moduleDeps := packagingProps.Multilib.Lib64.Deps
+
+ eval := result.ModuleForTests("test_product_generated_system_image", "android_common").Module().ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ android.AssertStringListContains(
+ t,
+ "Generated system image expected to depend on \"bar\" defined in \"a/b\" namespace",
+ moduleDeps.GetOrDefault(eval, nil),
+ "//a/b:bar",
+ )
+ android.AssertStringListDoesNotContain(
+ t,
+ "Generated system image expected to not depend on \"bar\" defined in \"c/d\" namespace",
+ moduleDeps.GetOrDefault(eval, nil),
+ "//c/d:bar",
+ )
+}
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index a059837..aa393a2 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -44,6 +44,32 @@
UnknownFramework Framework = "unknownframework"
)
+func (f Framework) Variant() string {
+ switch f {
+ case AFL:
+ return "afl"
+ case LibFuzzer:
+ return "libfuzzer"
+ case Jazzer:
+ return "jazzer"
+ default:
+ panic(fmt.Errorf("unknown fuzzer %q when getting variant", f))
+ }
+}
+
+func FrameworkFromVariant(v string) Framework {
+ switch v {
+ case "afl":
+ return AFL
+ case "libfuzzer":
+ return LibFuzzer
+ case "jazzer":
+ return Jazzer
+ default:
+ panic(fmt.Errorf("unknown variant %q when getting fuzzer", v))
+ }
+}
+
var BoolDefault = proptools.BoolDefault
type FuzzModule struct {
@@ -385,6 +411,11 @@
// Optional list of seed files to be installed to the fuzz target's output
// directory.
Corpus []string `android:"path"`
+
+ // Same as corpus, but adds dependencies on module references using the device's os variant
+ // and the common arch variant.
+ Device_common_corpus []string `android:"path_device_common"`
+
// Optional list of data files to be installed to the fuzz target's output
// directory. Directory structure relative to the module is preserved.
Data []string `android:"path"`
diff --git a/genrule/genrule.go b/genrule/genrule.go
index e5222a4..1ab1378 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -63,7 +63,7 @@
ctx.RegisterModuleType("genrule", GenRuleFactory)
ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("genrule_tool_deps", toolDepsMutator).Parallel()
+ ctx.BottomUp("genrule_tool_deps", toolDepsMutator)
})
}
@@ -112,6 +112,12 @@
return target.IsReplacedByPrebuilt()
}
+func (t hostToolDependencyTag) AllowDisabledModuleDependencyProxy(
+ ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool {
+ return android.OtherModuleProviderOrDefault(
+ ctx, target, android.CommonPropertiesProviderKey).ReplacedByPrebuilt
+}
+
var _ android.AllowDisabledModuleDependency = (*hostToolDependencyTag)(nil)
type generatorProperties struct {
@@ -139,8 +145,19 @@
Export_include_dirs []string
// list of input files
- Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
- ResolvedSrcs []string `blueprint:"mutated"`
+ Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
+
+ // Same as srcs, but will add dependencies on modules via a device os variation and the device's
+ // first supported arch's variation. Can be used to add a dependency from a host genrule to
+ // a device module.
+ Device_first_srcs proptools.Configurable[[]string] `android:"path_device_first"`
+
+ // Same as srcs, but will add dependencies on modules via a device os variation and the common
+ // arch variation. Can be used to add a dependency from a host genrule to a device module.
+ Device_common_srcs proptools.Configurable[[]string] `android:"path_device_common"`
+
+ // Same as srcs, but will add dependencies on modules via a common_os os variation.
+ Common_os_srcs proptools.Configurable[[]string] `android:"path_common_os"`
// input files to exclude
Exclude_srcs []string `android:"path,arch_variant"`
@@ -214,6 +231,7 @@
// For nsjail tasks
useNsjail bool
+ dirSrcs android.Paths
}
func (g *Module) GeneratedSourceFiles() android.Paths {
@@ -283,7 +301,15 @@
// approach zero; there should be no genrule action registration done directly
// by Soong logic in the mixed-build case.
func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
- g.subName = ctx.ModuleSubDir()
+ // Add the variant as a suffix to the make modules to create, so that the make modules
+ // don't conflict because make doesn't know about variants. However, this causes issues with
+ // tracking required dependencies as the required property in soong is passed straight to make
+ // without accounting for these suffixes. To make it a little easier to work with, don't use
+ // a suffix for android_common variants so that java_genrules look like regular 1-variant
+ // genrules to make.
+ if ctx.ModuleSubDir() != "android_common" {
+ g.subName = ctx.ModuleSubDir()
+ }
if len(g.properties.Export_include_dirs) > 0 {
for _, dir := range g.properties.Export_include_dirs {
@@ -316,21 +342,18 @@
var packagedTools []android.PackagingSpec
if len(g.properties.Tools) > 0 {
seenTools := make(map[string]bool)
-
- ctx.VisitDirectDepsAllowDisabled(func(module android.Module) {
- switch tag := ctx.OtherModuleDependencyTag(module).(type) {
+ ctx.VisitDirectDepsProxyAllowDisabled(func(proxy android.ModuleProxy) {
+ switch tag := ctx.OtherModuleDependencyTag(proxy).(type) {
case hostToolDependencyTag:
- tool := ctx.OtherModuleName(module)
// 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:
+ module := android.PrebuiltGetPreferred(ctx, proxy)
+ tool := ctx.OtherModuleName(module)
+ if h, ok := android.OtherModuleProvider(ctx, module, android.HostToolProviderKey); ok {
// A HostToolProvider provides the path to a tool, which will be copied
// into the sandbox.
- if !t.(android.Module).Enabled(ctx) {
+ if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonPropertiesProviderKey).Enabled {
if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{tool})
} else {
@@ -338,13 +361,13 @@
}
return
}
- path := t.HostToolPath()
+ path := h.HostToolPath
if !path.Valid() {
ctx.ModuleErrorf("host tool %q missing output file", tool)
return
}
if specs := android.OtherModuleProviderOrDefault(
- ctx, t, android.InstallFilesProvider).TransitivePackagingSpecs.ToList(); specs != nil {
+ ctx, module, android.InstallFilesProvider).TransitivePackagingSpecs.ToList(); specs != nil {
// If the HostToolProvider has PackgingSpecs, which are definitions of the
// required relative locations of the tool and its dependencies, use those
// instead. They will be copied to those relative locations in the sbox
@@ -366,7 +389,7 @@
tools = append(tools, path.Path())
addLocationLabel(tag.label, toolLocation{android.Paths{path.Path()}})
}
- default:
+ } else {
ctx.ModuleErrorf("%q is not a host tool provider", tool)
return
}
@@ -426,8 +449,11 @@
}
return srcFiles
}
- g.properties.ResolvedSrcs = g.properties.Srcs.GetOrDefault(ctx, nil)
- srcFiles := addLabelsForInputs("srcs", g.properties.ResolvedSrcs, g.properties.Exclude_srcs)
+ srcs := g.properties.Srcs.GetOrDefault(ctx, nil)
+ srcFiles := addLabelsForInputs("srcs", srcs, g.properties.Exclude_srcs)
+ srcFiles = append(srcFiles, addLabelsForInputs("device_first_srcs", g.properties.Device_first_srcs.GetOrDefault(ctx, nil), nil)...)
+ srcFiles = append(srcFiles, addLabelsForInputs("device_common_srcs", g.properties.Device_common_srcs.GetOrDefault(ctx, nil), nil)...)
+ srcFiles = append(srcFiles, addLabelsForInputs("common_os_srcs", g.properties.Common_os_srcs.GetOrDefault(ctx, nil), nil)...)
android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcFiles.Strings()})
var copyFrom android.Paths
@@ -577,10 +603,12 @@
}
if task.useNsjail {
- for _, input := range task.in {
- // can fail if input is a file.
+ for _, input := range task.dirSrcs {
+ cmd.Implicit(input)
if paths, err := ctx.GlobWithDeps(filepath.Join(input.String(), "**/*"), nil); err == nil {
rule.NsjailImplicits(android.PathsForSource(ctx, paths))
+ } else {
+ ctx.PropertyErrorf("dir_srcs", "can't glob %q", input.String())
}
}
}
@@ -643,6 +671,12 @@
}
g.setOutputFiles(ctx)
+
+ if ctx.Os() == android.Windows {
+ // Make doesn't support windows:
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/module_arch_supported.mk;l=66;drc=f264690860bb6ee7762784d6b7201aae057ba6f2
+ g.HideFromMake()
+ }
}
func (g *Module) setOutputFiles(ctx android.ModuleContext) {
@@ -659,7 +693,7 @@
// Collect information for opening IDE project files in java/jdeps.go.
func (g *Module) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
dpInfo.Srcs = append(dpInfo.Srcs, g.Srcs().Strings()...)
- for _, src := range g.properties.ResolvedSrcs {
+ for _, src := range g.properties.Srcs.GetOrDefault(ctx, nil) {
if strings.HasPrefix(src, ":") {
src = strings.Trim(src, ":")
dpInfo.Deps = append(dpInfo.Deps, src)
@@ -712,16 +746,22 @@
type noopImageInterface struct{}
-func (x noopImageInterface) ImageMutatorBegin(android.BaseModuleContext) {}
-func (x noopImageInterface) VendorVariantNeeded(android.BaseModuleContext) bool { return false }
-func (x noopImageInterface) ProductVariantNeeded(android.BaseModuleContext) bool { return false }
-func (x noopImageInterface) CoreVariantNeeded(android.BaseModuleContext) bool { return false }
-func (x noopImageInterface) RamdiskVariantNeeded(android.BaseModuleContext) bool { return false }
-func (x noopImageInterface) VendorRamdiskVariantNeeded(android.BaseModuleContext) bool { return false }
-func (x noopImageInterface) DebugRamdiskVariantNeeded(android.BaseModuleContext) bool { return false }
-func (x noopImageInterface) RecoveryVariantNeeded(android.BaseModuleContext) bool { return false }
-func (x noopImageInterface) ExtraImageVariations(ctx android.BaseModuleContext) []string { return nil }
-func (x noopImageInterface) SetImageVariation(ctx android.BaseModuleContext, variation string) {
+func (x noopImageInterface) ImageMutatorBegin(android.ImageInterfaceContext) {}
+func (x noopImageInterface) VendorVariantNeeded(android.ImageInterfaceContext) bool { return false }
+func (x noopImageInterface) ProductVariantNeeded(android.ImageInterfaceContext) bool { return false }
+func (x noopImageInterface) CoreVariantNeeded(android.ImageInterfaceContext) bool { return false }
+func (x noopImageInterface) RamdiskVariantNeeded(android.ImageInterfaceContext) bool { return false }
+func (x noopImageInterface) VendorRamdiskVariantNeeded(android.ImageInterfaceContext) bool {
+ return false
+}
+func (x noopImageInterface) DebugRamdiskVariantNeeded(android.ImageInterfaceContext) bool {
+ return false
+}
+func (x noopImageInterface) RecoveryVariantNeeded(android.ImageInterfaceContext) bool { return false }
+func (x noopImageInterface) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
+ return nil
+}
+func (x noopImageInterface) SetImageVariation(ctx android.ImageInterfaceContext, variation string) {
}
func NewGenSrcs() *Module {
@@ -850,6 +890,12 @@
taskGenerator := func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask {
useNsjail := Bool(properties.Use_nsjail)
+ dirSrcs := android.DirectoryPathsForModuleSrc(ctx, properties.Dir_srcs)
+ if len(dirSrcs) > 0 && !useNsjail {
+ ctx.PropertyErrorf("dir_srcs", "can't use dir_srcs if use_nsjail is false")
+ return nil
+ }
+
outs := make(android.WritablePaths, len(properties.Out))
for i, out := range properties.Out {
outs[i] = android.PathForModuleGen(ctx, out)
@@ -860,6 +906,7 @@
genDir: android.PathForModuleGen(ctx),
cmd: rawCommand,
useNsjail: useNsjail,
+ dirSrcs: dirSrcs,
}}
}
@@ -876,6 +923,10 @@
type genRuleProperties struct {
Use_nsjail *bool
+ // List of input directories. Can be set only when use_nsjail is true. Currently, usage of
+ // dir_srcs is limited only to Trusty build.
+ Dir_srcs []string `android:"path"`
+
// names of the output files that will be generated
Out []string `android:"arch_variant"`
}
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 9278f15..f190750 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -24,6 +24,7 @@
"android/soong/android"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -694,8 +695,12 @@
expectedCmd := "cp in1 __SBOX_SANDBOX_DIR__/out/out"
android.AssertStringEquals(t, "cmd", expectedCmd, gen.rawCommands[0])
+ srcsFileProvider, ok := android.OtherModuleProvider(result.TestContext, gen, blueprint.SrcsFileProviderKey)
+ if !ok {
+ t.Fatal("Expected genrule to have a SrcsFileProviderData, but did not")
+ }
expectedSrcs := []string{"in1"}
- android.AssertDeepEquals(t, "srcs", expectedSrcs, gen.properties.ResolvedSrcs)
+ android.AssertDeepEquals(t, "srcs", expectedSrcs, srcsFileProvider.SrcPaths)
}
func TestGenruleAllowMissingDependencies(t *testing.T) {
diff --git a/go.mod b/go.mod
index aa43066..57b59c0 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module android/soong
-go 1.22
+go 1.23
require (
github.com/google/blueprint v0.0.0
diff --git a/go.work b/go.work
index 46a135b..e538915 100644
--- a/go.work
+++ b/go.work
@@ -1,4 +1,4 @@
-go 1.22
+go 1.23
use (
.
diff --git a/golang/golang_test.go b/golang/golang_test.go
index b512144..0a4baed 100644
--- a/golang/golang_test.go
+++ b/golang/golang_test.go
@@ -16,9 +16,10 @@
import (
"android/soong/android"
- "github.com/google/blueprint/bootstrap"
- "path/filepath"
+ "regexp"
"testing"
+
+ "github.com/google/blueprint/bootstrap"
)
func TestGolang(t *testing.T) {
@@ -39,13 +40,19 @@
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
RegisterGoModuleTypes(ctx)
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUpBlueprint("bootstrap_deps", bootstrap.BootstrapDeps)
+ ctx.BottomUpBlueprint("bootstrap_deps", bootstrap.BootstrapDeps).UsesReverseDependencies()
})
}),
).RunTestWithBp(t, bp)
bin := result.ModuleForTests("gobin", result.Config.BuildOSTarget.String())
- expected := filepath.Join("out/soong/host", result.Config.PrebuiltOS(), "bin/go/gobin/obj/gobin")
- android.AssertPathsRelativeToTopEquals(t, "output files", []string{expected}, bin.OutputFiles(result.TestContext, t, ""))
+ expected := "^out/soong/host/" + result.Config.PrebuiltOS() + "/bin/go/gobin/?[^/]*/obj/gobin$"
+ actual := android.PathsRelativeToTop(bin.OutputFiles(result.TestContext, t, ""))
+ if len(actual) != 1 {
+ t.Fatalf("Expected 1 output file, got %v", actual)
+ }
+ if match, err := regexp.Match(expected, []byte(actual[0])); err != nil || !match {
+ t.Fatalf("Expected output file to match %q, but got %q", expected, actual[0])
+ }
}
diff --git a/java/aapt2.go b/java/aapt2.go
index 61cf373..bae4d1e 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -15,7 +15,9 @@
package java
import (
+ "fmt"
"path/filepath"
+ "regexp"
"sort"
"strconv"
"strings"
@@ -31,19 +33,35 @@
return strings.HasPrefix(lastDir, "values")
}
+func isFlagsPath(subDir string) bool {
+ re := regexp.MustCompile(`flag\(!?([a-zA-Z_-]+\.)*[a-zA-Z0-9_-]+\)`)
+ lastDir := filepath.Base(subDir)
+ return re.MatchString(lastDir)
+}
+
// Convert input resource file path to output file path.
// values-[config]/<file>.xml -> values-[config]_<file>.arsc.flat;
+// flag(fully.qualified.flag_name)/values-[config]/<file>.xml -> /values-[config]_<file>.(fully.qualified.flag_name).arsc.flat;
// For other resource file, just replace the last "/" with "_" and add .flat extension.
func pathToAapt2Path(ctx android.ModuleContext, res android.Path) android.WritablePath {
- name := res.Base()
+ extension := filepath.Ext(res.Base())
+ name := strings.TrimSuffix(res.Base(), extension)
if isPathValueResource(res) {
- name = strings.TrimSuffix(name, ".xml") + ".arsc"
+ extension = ".arsc"
}
subDir := filepath.Dir(res.String())
subDir, lastDir := filepath.Split(subDir)
- name = lastDir + "_" + name + ".flat"
- return android.PathForModuleOut(ctx, "aapt2", subDir, name)
+ if isFlagsPath(subDir) {
+ var flag string
+ subDir, flag = filepath.Split(filepath.Dir(subDir))
+ flag = strings.TrimPrefix(flag, "flag")
+ name = fmt.Sprintf("%s_%s.%s%s.flat", lastDir, name, flag, extension)
+ } else {
+ name = fmt.Sprintf("%s_%s%s.flat", lastDir, name, extension)
+ }
+ out := android.PathForModuleOut(ctx, "aapt2", subDir, name)
+ return out
}
// pathsToAapt2Paths Calls pathToAapt2Path on each entry of the given Paths, i.e. []Path.
diff --git a/java/androidmk.go b/java/androidmk.go
index 2dff6cd..bacd925 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -281,50 +281,24 @@
return nil
}
- if !binary.isWrapperVariant {
- return []android.AndroidMkEntries{android.AndroidMkEntries{
- Class: "JAVA_LIBRARIES",
- OutputFile: android.OptionalPathForPath(binary.outputFile),
- Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetPath("LOCAL_SOONG_HEADER_JAR", binary.headerJarFile)
- entries.SetPath("LOCAL_SOONG_CLASSES_JAR", binary.implementationAndResourcesJar)
- if binary.dexJarFile.IsSet() {
- entries.SetPath("LOCAL_SOONG_DEX_JAR", binary.dexJarFile.Path())
- }
- if len(binary.dexpreopter.builtInstalled) > 0 {
- entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled)
- }
- },
+ return []android.AndroidMkEntries{{
+ Class: "JAVA_LIBRARIES",
+ OutputFile: android.OptionalPathForPath(binary.outputFile),
+ Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", binary.headerJarFile)
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", binary.implementationAndResourcesJar)
+ if binary.dexJarFile.IsSet() {
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", binary.dexJarFile.Path())
+ }
+ if len(binary.dexpreopter.builtInstalled) > 0 {
+ entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled)
+ }
+ entries.AddStrings("LOCAL_REQUIRED_MODULES", binary.androidMkNamesOfJniLibs...)
},
- ExtraFooters: []android.AndroidMkExtraFootersFunc{
- func(w io.Writer, name, prefix, moduleDir string) {
- fmt.Fprintln(w, "jar_installed_module := $(LOCAL_INSTALLED_MODULE)")
- },
- },
- }}
- } else {
- outputFile := binary.wrapperFile
-
- return []android.AndroidMkEntries{android.AndroidMkEntries{
- Class: "EXECUTABLES",
- OutputFile: android.OptionalPathForPath(outputFile),
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetBool("LOCAL_STRIP_MODULE", false)
- entries.AddStrings("LOCAL_REQUIRED_MODULES", binary.androidMkNamesOfJniLibs...)
- },
- },
- ExtraFooters: []android.AndroidMkExtraFootersFunc{
- func(w io.Writer, name, prefix, moduleDir string) {
- // Ensure that the wrapper script timestamp is always updated when the jar is updated
- fmt.Fprintln(w, "$(LOCAL_INSTALLED_MODULE): $(jar_installed_module)")
- fmt.Fprintln(w, "jar_installed_module :=")
- },
- },
- }}
- }
+ },
+ }}
}
func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/java/app.go b/java/app.go
index dd99675..56fcfbb 100644
--- a/java/app.go
+++ b/java/app.go
@@ -30,7 +30,6 @@
"android/soong/android"
"android/soong/cc"
"android/soong/dexpreopt"
- "android/soong/genrule"
"android/soong/tradefed"
)
@@ -679,7 +678,7 @@
a.dexProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx))
}
a.dexpreopter.uncompressedDex = *a.dexProperties.Uncompress_dex
- a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
+ a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries(ctx)
a.dexpreopter.classLoaderContexts = a.classLoaderContexts
a.dexpreopter.manifestFile = a.mergedManifestFile
a.dexpreopter.preventInstall = a.appProperties.PreventInstall
@@ -908,10 +907,10 @@
// Process all building blocks, from AAPT to certificates.
a.aaptBuildActions(ctx)
// The decision to enforce <uses-library> checks is made before adding implicit SDK libraries.
- a.usesLibrary.freezeEnforceUsesLibraries()
+ a.usesLibrary.freezeEnforceUsesLibraries(ctx)
// Check that the <uses-library> list is coherent with the manifest.
- if a.usesLibrary.enforceUsesLibraries() {
+ if a.usesLibrary.enforceUsesLibraries(ctx) {
manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(
ctx, a.mergedManifestFile, &a.classLoaderContexts)
apkDeps = append(apkDeps, manifestCheckFile)
@@ -1333,7 +1332,7 @@
Srcs: []string{":" + a.Name() + "{.apk}"},
Cmd: proptools.StringPtr("$(location characteristics_rro_generator) $$($(location aapt2) dump packagename $(in)) $(out)"),
}
- ctx.CreateModule(genrule.GenRuleFactory, &rroManifestProperties)
+ ctx.CreateModule(GenRuleFactory, &rroManifestProperties)
rroProperties := struct {
Name *string
@@ -1341,12 +1340,14 @@
Aaptflags []string
Manifest *string
Resource_dirs []string
+ Flags_packages []string
}{
Name: proptools.StringPtr(rroPackageName),
Filter_product: proptools.StringPtr(characteristics),
Aaptflags: []string{"--auto-add-overlay"},
Manifest: proptools.StringPtr(":" + rroManifestName),
Resource_dirs: a.aaptProperties.Resource_dirs,
+ Flags_packages: a.aaptProperties.Flags_packages,
}
if !Bool(a.aaptProperties.Aapt_include_all_resources) {
for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
@@ -1439,6 +1440,8 @@
a.testConfig = a.FixTestConfig(ctx, testConfig)
a.extraTestConfigs = android.PathsForModuleSrc(ctx, a.testProperties.Test_options.Extra_test_configs)
a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
+ a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_common_data)...)
+ a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_data)...)
android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{
InstalledFiles: a.data,
@@ -1687,11 +1690,11 @@
type UsesLibraryProperties struct {
// A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file.
- Uses_libs []string
+ Uses_libs proptools.Configurable[[]string]
// A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file with
// required=false.
- Optional_uses_libs []string
+ Optional_uses_libs proptools.Configurable[[]string]
// If true, the list of uses_libs and optional_uses_libs modules must match the AndroidManifest.xml file. Defaults
// to true if either uses_libs or optional_uses_libs is set. Will unconditionally default to true in the future.
@@ -1739,7 +1742,7 @@
func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, addCompatDeps bool) {
if !ctx.Config().UnbundledBuild() || ctx.Config().UnbundledBuildImage() {
- ctx.AddVariationDependencies(nil, usesLibReqTag, u.usesLibraryProperties.Uses_libs...)
+ ctx.AddVariationDependencies(nil, usesLibReqTag, u.usesLibraryProperties.Uses_libs.GetOrDefault(ctx, nil)...)
presentOptionalUsesLibs := u.presentOptionalUsesLibs(ctx)
ctx.AddVariationDependencies(nil, usesLibOptTag, presentOptionalUsesLibs...)
// Only add these extra dependencies if the module is an app that depends on framework
@@ -1752,17 +1755,17 @@
ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
}
- _, diff, _ := android.ListSetDifference(u.usesLibraryProperties.Optional_uses_libs, presentOptionalUsesLibs)
+ _, diff, _ := android.ListSetDifference(u.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil), presentOptionalUsesLibs)
u.usesLibraryProperties.Missing_optional_uses_libs = diff
} else {
- ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.usesLibraryProperties.Uses_libs...)
+ ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.usesLibraryProperties.Uses_libs.GetOrDefault(ctx, nil)...)
ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.presentOptionalUsesLibs(ctx)...)
}
}
// presentOptionalUsesLibs returns optional_uses_libs after filtering out libraries that don't exist in the source tree.
func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []string {
- optionalUsesLibs := android.FilterListPred(u.usesLibraryProperties.Optional_uses_libs, func(s string) bool {
+ optionalUsesLibs := android.FilterListPred(u.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil), func(s string) bool {
exists := ctx.OtherModuleExists(s)
if !exists && !android.InList(ctx.ModuleName(), ctx.Config().BuildWarningBadOptionalUsesLibsAllowlist()) {
fmt.Printf("Warning: Module '%s' depends on non-existing optional_uses_libs '%s'\n", ctx.ModuleName(), s)
@@ -1828,15 +1831,15 @@
// enforceUsesLibraries returns true of <uses-library> tags should be checked against uses_libs and optional_uses_libs
// properties. Defaults to true if either of uses_libs or optional_uses_libs is specified. Will default to true
// unconditionally in the future.
-func (u *usesLibrary) enforceUsesLibraries() bool {
- defaultEnforceUsesLibs := len(u.usesLibraryProperties.Uses_libs) > 0 ||
- len(u.usesLibraryProperties.Optional_uses_libs) > 0
+func (u *usesLibrary) enforceUsesLibraries(ctx android.ModuleContext) bool {
+ defaultEnforceUsesLibs := len(u.usesLibraryProperties.Uses_libs.GetOrDefault(ctx, nil)) > 0 ||
+ len(u.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil)) > 0
return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, u.enforce || defaultEnforceUsesLibs)
}
// Freeze the value of `enforce_uses_libs` based on the current values of `uses_libs` and `optional_uses_libs`.
-func (u *usesLibrary) freezeEnforceUsesLibraries() {
- enforce := u.enforceUsesLibraries()
+func (u *usesLibrary) freezeEnforceUsesLibraries(ctx android.ModuleContext) {
+ enforce := u.enforceUsesLibraries(ctx)
u.usesLibraryProperties.Enforce_uses_libs = &enforce
}
diff --git a/java/app_import.go b/java/app_import.go
index a54cf2f..6b88f1c 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -61,6 +61,9 @@
func RegisterAppImportBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("android_app_import", AndroidAppImportFactory)
ctx.RegisterModuleType("android_test_import", AndroidTestImportFactory)
+ ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("disable_prebuilts_without_apk", disablePrebuiltsWithoutApkMutator)
+ })
}
type AndroidAppImport struct {
@@ -90,7 +93,7 @@
type AndroidAppImportProperties struct {
// A prebuilt apk to import
- Apk *string `android:"path"`
+ Apk proptools.Configurable[string] `android:"path,replace_instead_of_append"`
// The name of a certificate in the default certificate directory or an android_app_certificate
// module name in the form ":module". Should be empty if presigned or default_dev_cert is set.
@@ -193,13 +196,6 @@
}
}
}
-
- if String(a.properties.Apk) == "" {
- // Disable this module since the apk property is still empty after processing all matching
- // variants. This likely means there is no matching variant, and the default variant doesn't
- // have an apk property value either.
- a.Disable()
- }
}
func MergePropertiesFromVariant(ctx android.EarlyModuleContext,
@@ -219,6 +215,30 @@
}
}
+// disablePrebuiltsWithoutApkMutator is a pre-arch mutator that disables AndroidAppImport or
+// AndroidTestImport modules that don't have an apk set. We need this separate mutator instead
+// of doing it in processVariants because processVariants is a defaultable hook, and configurable
+// properties can only be evaluated after the defaults (and eventually, base configurabtion)
+// mutators.
+func disablePrebuiltsWithoutApkMutator(ctx android.BottomUpMutatorContext) {
+ switch a := ctx.Module().(type) {
+ case *AndroidAppImport:
+ if a.properties.Apk.GetOrDefault(ctx, "") == "" {
+ // Disable this module since the apk property is still empty after processing all
+ // matching variants. This likely means there is no matching variant, and the default
+ // variant doesn't have an apk property value either.
+ a.Disable()
+ }
+ case *AndroidTestImport:
+ if a.properties.Apk.GetOrDefault(ctx, "") == "" {
+ // Disable this module since the apk property is still empty after processing all
+ // matching variants. This likely means there is no matching variant, and the default
+ // variant doesn't have an apk property value either.
+ a.Disable()
+ }
+ }
+}
+
func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
cert := android.SrcIsModule(String(a.properties.Certificate))
if cert != "" {
@@ -344,13 +364,13 @@
a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
- a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
+ a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries(ctx)
a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
if a.usesLibrary.shouldDisableDexpreopt {
a.dexpreopter.disableDexpreopt()
}
- if a.usesLibrary.enforceUsesLibraries() {
+ if a.usesLibrary.enforceUsesLibraries(ctx) {
a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk, &a.dexpreopter.classLoaderContexts)
}
@@ -409,7 +429,7 @@
if apexInfo.IsForPlatform() {
a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
- artifactPath := android.PathForModuleSrc(ctx, *a.properties.Apk)
+ artifactPath := android.PathForModuleSrc(ctx, a.properties.Apk.GetOrDefault(ctx, ""))
a.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath)
}
@@ -633,7 +653,7 @@
android.InitApexModule(module)
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
- android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
+ android.InitConfigurablePrebuiltModuleString(module, &module.properties.Apk, "Apk")
module.usesLibrary.enforce = true
@@ -686,7 +706,7 @@
android.InitApexModule(module)
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
- android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
+ android.InitConfigurablePrebuiltModuleString(module, &module.properties.Apk, "Apk")
return module
}
diff --git a/java/app_test.go b/java/app_test.go
index dd672a0..3d83ea1 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -4679,3 +4679,51 @@
"--override-placeholder-version",
)
}
+
+func TestResourcesWithFlagDirectories(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.FixtureMergeMockFs(android.MockFS{
+ "res/flag(test.package.flag1)/values/bools.xml": nil,
+ "res/flag(!test.package.flag2)/values/bools.xml": nil,
+ "res/flag(test.package.flag1)/values-config/strings_google_services.xml": nil,
+ "res/flags(test.package.flag1)/values/strings.xml": nil,
+ }),
+ ).RunTestWithBp(t, `
+ android_library {
+ name: "foo",
+ srcs: ["a.java"],
+ use_resource_processor: true,
+ resource_dirs: [
+ "res",
+ ],
+ }
+ `)
+ fooModule := result.ModuleForTests("foo", "android_common")
+ compileOutputPaths := fooModule.Rule("aapt2Compile").Outputs.Strings()
+
+ android.AssertStringListContains(
+ t,
+ "Expected to generate flag path",
+ compileOutputPaths,
+ "out/soong/.intermediates/foo/android_common/aapt2/res/values_bools.(test.package.flag1).arsc.flat",
+ )
+ android.AssertStringListContains(
+ t,
+ "Expected to generate flag path with ! prefix in name",
+ compileOutputPaths,
+ "out/soong/.intermediates/foo/android_common/aapt2/res/values_bools.(!test.package.flag2).arsc.flat",
+ )
+ android.AssertStringListContains(
+ t,
+ "Expected to generate flag path with configs",
+ compileOutputPaths,
+ "out/soong/.intermediates/foo/android_common/aapt2/res/values-config_strings_google_services.(test.package.flag1).arsc.flat",
+ )
+ android.AssertStringListDoesNotContain(
+ t,
+ "Expected to not generate flag path with non-flag(flag_name) pattern",
+ compileOutputPaths,
+ "out/soong/.intermediates/foo/android_common/aapt2/res/values_strings.(test.package.flag1).arsc.flat",
+ )
+}
diff --git a/java/base.go b/java/base.go
index 7a95735..3927c61 100644
--- a/java/base.go
+++ b/java/base.go
@@ -71,6 +71,15 @@
// list of files that should be excluded from java_resources and java_resource_dirs
Exclude_java_resources []string `android:"path,arch_variant"`
+ // Same as java_resources, but modules added here will use the device variant. Can be useful
+ // for making a host test that tests the contents of a device built app.
+ Device_common_java_resources []string `android:"path_device_common"`
+
+ // Same as java_resources, but modules added here will use the device's os variant and the
+ // device's first architecture variant. Can be useful for making a host test that tests the
+ // contents of a native device built app.
+ Device_first_java_resources []string `android:"path_device_first"`
+
// list of module-specific flags that will be used for javac compiles
Javacflags []string `android:"arch_variant"`
@@ -113,6 +122,9 @@
// List of modules to use as annotation processors
Plugins []string
+ // List of modules to use as kotlin plugin
+ Kotlin_plugins []string
+
// List of modules to export to libraries that directly depend on this library as annotation
// processors. Note that if the plugins set generates_api: true this will disable the turbine
// optimization on modules that depend on this module, which will reduce parallelism and cause
@@ -862,7 +874,7 @@
// explicitly listed in the optional_uses_libs property.
tag := usesLibReqTag
if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) ||
- android.InList(*lib, j.usesLibrary.usesLibraryProperties.Optional_uses_libs) {
+ android.InList(*lib, j.usesLibrary.usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil)) {
tag = usesLibOptTag
}
ctx.AddVariationDependencies(nil, tag, *lib)
@@ -872,6 +884,7 @@
}
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...)
+ ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag, j.properties.Kotlin_plugins...)
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), errorpronePluginTag, j.properties.Errorprone.Extra_check_modules...)
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_plugins...)
@@ -904,7 +917,7 @@
if j.useCompose(ctx) {
ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag,
- "androidx.compose.compiler_compiler-hosted")
+ "androidx.compose.compiler_compiler-hosted-plugin")
}
}
@@ -1482,6 +1495,10 @@
dirArgs, dirDeps := ResourceDirsToJarArgs(ctx, j.properties.Java_resource_dirs,
j.properties.Exclude_java_resource_dirs, j.properties.Exclude_java_resources)
fileArgs, fileDeps := ResourceFilesToJarArgs(ctx, j.properties.Java_resources, j.properties.Exclude_java_resources)
+ fileArgs2, fileDeps2 := ResourceFilesToJarArgs(ctx, j.properties.Device_common_java_resources, nil)
+ fileArgs3, fileDeps3 := ResourceFilesToJarArgs(ctx, j.properties.Device_first_java_resources, nil)
+ fileArgs = slices.Concat(fileArgs, fileArgs2, fileArgs3)
+ fileDeps = slices.Concat(fileDeps, fileDeps2, fileDeps3)
extraArgs, extraDeps := resourcePathsToJarArgs(j.extraResources), j.extraResources
var resArgs []string
@@ -2172,16 +2189,14 @@
// Collect information for opening IDE project files in java/jdeps.go.
func (j *Module) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
- // jarjar rules will repackage the sources. To prevent misleading results, IdeInfo should contain the
- // repackaged jar instead of the input sources.
if j.expandJarjarRules != nil {
dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
+ // Add the header jar so that the rdeps can be resolved to the repackaged classes.
dpInfo.Jars = append(dpInfo.Jars, j.headerJarFile.String())
- } else {
- dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...)
- dpInfo.SrcJars = append(dpInfo.SrcJars, j.compiledSrcJars.Strings()...)
- dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...)
}
+ dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...)
+ dpInfo.SrcJars = append(dpInfo.SrcJars, j.compiledSrcJars.Strings()...)
+ dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...)
dpInfo.Deps = append(dpInfo.Deps, j.CompilerDeps()...)
dpInfo.Aidl_include_dirs = append(dpInfo.Aidl_include_dirs, j.deviceProperties.Aidl.Include_dirs...)
dpInfo.Static_libs = append(dpInfo.Static_libs, j.staticLibs(ctx)...)
@@ -2501,7 +2516,11 @@
ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName)
}
case kotlinPluginTag:
- deps.kotlinPlugins = append(deps.kotlinPlugins, dep.ImplementationAndResourcesJars...)
+ if _, ok := module.(*KotlinPlugin); ok {
+ deps.kotlinPlugins = append(deps.kotlinPlugins, dep.ImplementationAndResourcesJars...)
+ } else {
+ ctx.PropertyErrorf("kotlin_plugins", "%q is not a kotlin_plugin module", otherName)
+ }
case syspropPublicStubDepTag:
// This is a sysprop implementation library, forward the JavaInfoProvider from
// the corresponding sysprop public stub library as SyspropPublicStubInfoProvider.
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index 029f6f6..3413cf3 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -29,7 +29,7 @@
func registerBootclasspathBuildComponents(ctx android.RegistrationContext) {
ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator).Parallel()
+ ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator)
})
}
diff --git a/java/builder.go b/java/builder.go
index e5d5109..895ddb6 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -301,7 +301,7 @@
gatherReleasedFlaggedApisRule = pctx.AndroidStaticRule("gatherReleasedFlaggedApisRule",
blueprint.RuleParams{
- Command: `${aconfig} dump-cache --dedup --format='{fully_qualified_name}={state:bool}' ` +
+ Command: `${aconfig} dump-cache --dedup --format='{fully_qualified_name}' ` +
`--out ${out} ` +
`${flags_path} ` +
`${filter_args} `,
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index 1cca7ad..da86540 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -41,10 +41,50 @@
is_stubs_module: true,
}
+soong_config_module_type {
+ name: "core_current_stubs_soong_config_defaults",
+ module_type: "java_defaults",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "release_hidden_api_exportable_stubs",
+ ],
+ properties: [
+ "dist.targets",
+ "dist.dest",
+ ],
+}
+
+core_current_stubs_soong_config_defaults {
+ name: "core_current_stubs_everything_soong_config_defaults",
+ soong_config_variables: {
+ release_hidden_api_exportable_stubs: {
+ conditions_default: {
+ dist: {
+ targets: dist_targets,
+ dest: "core.current.stubs.jar",
+ },
+ },
+ },
+ },
+}
+
+core_current_stubs_soong_config_defaults {
+ name: "core_current_stubs_exportable_soong_config_defaults",
+ soong_config_variables: {
+ release_hidden_api_exportable_stubs: {
+ dist: {
+ targets: dist_targets,
+ dest: "core.current.stubs.jar",
+ },
+ },
+ },
+}
+
java_library {
name: "core.current.stubs",
defaults: [
"core.current.stubs.defaults",
+ "core_current_stubs_everything_soong_config_defaults",
],
static_libs: [
"art.module.public.api.stubs",
@@ -76,16 +116,13 @@
name: "core.current.stubs.exportable",
defaults: [
"core.current.stubs.defaults",
+ "core_current_stubs_exportable_soong_config_defaults",
],
static_libs: [
"art.module.public.api.stubs.exportable",
"conscrypt.module.public.api.stubs.exportable",
"i18n.module.public.api.stubs.exportable",
],
- dist: {
- targets: dist_targets,
- dest: "core.current.stubs.jar",
- },
}
// Distributed with the SDK for turning into system modules to compile apps
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 637da36..5928446 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -562,7 +562,7 @@
// TODO(b/346662300): Let dexpreopter generate the installPath for dexpreopt files instead of
// using the dex location to generate the installPath.
if isApexSystemServerJar {
- dexpreoptPartition = "system"
+ dexpreoptPartition = dexpreoptConfig.ApexPartition
}
for _, install := range dexpreoptRule.Installs() {
// Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 5c69ff1..8c60d23 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -465,7 +465,7 @@
ctx.RegisterParallelSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory)
ctx.RegisterModuleType("art_boot_images", artBootImagesFactory)
ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("dex_bootjars_deps", DexpreoptBootJarsMutator).Parallel()
+ ctx.BottomUp("dex_bootjars_deps", DexpreoptBootJarsMutator)
})
}
@@ -1442,7 +1442,7 @@
func (dbj *artBootImages) DepsMutator(ctx android.BottomUpMutatorContext) {
// Create a dependency on `dex_bootjars` to access the intermediate locations of host art boot image.
- ctx.AddDependency(ctx.Module(), dexpreoptBootJarDepTag, "dex_bootjars")
+ ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), dexpreoptBootJarDepTag, "dex_bootjars")
}
func (d *artBootImages) GenerateAndroidBuildActions(ctx android.ModuleContext) {
diff --git a/java/fuzz.go b/java/fuzz.go
index e5f1f04..90f09a8 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -110,6 +110,9 @@
if j.fuzzPackagedModule.FuzzProperties.Corpus != nil {
j.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Corpus)
}
+ if j.fuzzPackagedModule.FuzzProperties.Device_common_corpus != nil {
+ j.fuzzPackagedModule.Corpus = append(j.fuzzPackagedModule.Corpus, android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Device_common_corpus)...)
+ }
if j.fuzzPackagedModule.FuzzProperties.Data != nil {
j.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Data)
}
diff --git a/java/java.go b/java/java.go
index 018850f..5bb3636 100644
--- a/java/java.go
+++ b/java/java.go
@@ -70,9 +70,9 @@
// established, to not get the dependencies split into the wrong variants and
// to support the checks in dexpreoptDisabled().
ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator).Parallel()
+ ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator)
// needs access to ApexInfoProvider which is available after variant creation
- ctx.BottomUp("jacoco_deps", jacocoDepsMutator).Parallel()
+ ctx.BottomUp("jacoco_deps", jacocoDepsMutator)
})
ctx.RegisterParallelSingletonType("kythe_java_extract", kytheExtractJavaFactory)
@@ -450,7 +450,6 @@
javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"}
jniInstallTag = dependencyTag{name: "jni install", runtimeLinked: true, installable: true}
- binaryInstallTag = dependencyTag{name: "binary install", runtimeLinked: true, installable: true}
usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true)
usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true)
@@ -1004,13 +1003,7 @@
}
j.compile(ctx, nil, nil, nil, nil)
- // If this module is an impl library created from java_sdk_library,
- // install the files under the java_sdk_library module outdir instead of this module outdir.
- if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") {
- j.setInstallRules(ctx, proptools.String(j.SdkLibraryName()))
- } else {
- j.setInstallRules(ctx, ctx.ModuleName())
- }
+ j.setInstallRules(ctx)
android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
TestOnly: Bool(j.sourceProperties.Test_only),
@@ -1020,7 +1013,27 @@
setOutputFiles(ctx, j.Module)
}
-func (j *Library) setInstallRules(ctx android.ModuleContext, installModuleName string) {
+func (j *Library) getJarInstallDir(ctx android.ModuleContext) android.InstallPath {
+ var installDir android.InstallPath
+ if ctx.InstallInTestcases() {
+ var archDir string
+ if !ctx.Host() {
+ archDir = ctx.DeviceConfig().DeviceArch()
+ }
+ installModuleName := ctx.ModuleName()
+ // If this module is an impl library created from java_sdk_library,
+ // install the files under the java_sdk_library module outdir instead of this module outdir.
+ if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") {
+ installModuleName = proptools.String(j.SdkLibraryName())
+ }
+ installDir = android.PathForModuleInstall(ctx, installModuleName, archDir)
+ } else {
+ installDir = android.PathForModuleInstall(ctx, "framework")
+ }
+ return installDir
+}
+
+func (j *Library) setInstallRules(ctx android.ModuleContext) {
apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if (Bool(j.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() {
@@ -1034,17 +1047,7 @@
android.PathForHostDexInstall(ctx, "framework"),
j.Stem()+"-hostdex.jar", j.outputFile)
}
- var installDir android.InstallPath
- if ctx.InstallInTestcases() {
- var archDir string
- if !ctx.Host() {
- archDir = ctx.DeviceConfig().DeviceArch()
- }
- installDir = android.PathForModuleInstall(ctx, installModuleName, archDir)
- } else {
- installDir = android.PathForModuleInstall(ctx, "framework")
- }
- j.installFile = ctx.InstallFileWithoutCheckbuild(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
+ j.installFile = ctx.InstallFileWithoutCheckbuild(j.getJarInstallDir(ctx), j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
}
@@ -1288,6 +1291,16 @@
// the test
Data []string `android:"path"`
+ // Same as data, but will add dependencies on modules using the device's os variation and
+ // the common arch variation. Useful for a host test that wants to embed a module built for
+ // device.
+ Device_common_data []string `android:"path_device_common"`
+
+ // same as data, but adds dependencies using the device's os variation and the device's first
+ // architecture's variation. Can be used to add a module built for device to the data of a
+ // host test.
+ Device_first_data []string `android:"path_device_first"`
+
// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
// explicitly.
@@ -1578,6 +1591,8 @@
})
j.data = android.PathsForModuleSrc(ctx, j.testProperties.Data)
+ j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Device_common_data)...)
+ j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Device_first_data)...)
j.extraTestConfigs = android.PathsForModuleSrc(ctx, j.testProperties.Test_options.Extra_test_configs)
@@ -1804,8 +1819,6 @@
binaryProperties binaryProperties
- isWrapperVariant bool
-
wrapperFile android.Path
binaryFile android.InstallPath
@@ -1819,97 +1832,94 @@
func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.stem = proptools.StringDefault(j.overridableProperties.Stem, ctx.ModuleName())
- if ctx.Arch().ArchType == android.Common {
- // Compile the jar
- if j.binaryProperties.Main_class != nil {
- if j.properties.Manifest != nil {
- ctx.PropertyErrorf("main_class", "main_class cannot be used when manifest is set")
- }
- manifestFile := android.PathForModuleOut(ctx, "manifest.txt")
- GenerateMainClassManifest(ctx, manifestFile, String(j.binaryProperties.Main_class))
- j.overrideManifest = android.OptionalPathForPath(manifestFile)
- }
-
- j.Library.GenerateAndroidBuildActions(ctx)
+ // Handle the binary wrapper. This comes before compiling the jar so that the wrapper
+ // is the first PackagingSpec
+ if j.binaryProperties.Wrapper != nil {
+ j.wrapperFile = android.PathForModuleSrc(ctx, *j.binaryProperties.Wrapper)
} else {
- // Handle the binary wrapper
- j.isWrapperVariant = true
-
- if j.binaryProperties.Wrapper != nil {
- j.wrapperFile = android.PathForModuleSrc(ctx, *j.binaryProperties.Wrapper)
- } else {
- if ctx.Windows() {
- ctx.PropertyErrorf("wrapper", "wrapper is required for Windows")
- }
-
- if ctx.Device() {
- // device binary should have a main_class property if it does not
- // have a specific wrapper, so that a default wrapper can
- // be generated for it.
- if j.binaryProperties.Main_class == nil {
- ctx.PropertyErrorf("main_class", "main_class property "+
- "is required for device binary if no default wrapper is assigned")
- } else {
- wrapper := android.PathForModuleOut(ctx, ctx.ModuleName()+".sh")
- jarName := j.Stem() + ".jar"
- partition := j.PartitionTag(ctx.DeviceConfig())
- ctx.Build(pctx, android.BuildParams{
- Rule: deviceBinaryWrapper,
- Output: wrapper,
- Args: map[string]string{
- "jar_name": jarName,
- "partition": partition,
- "main_class": String(j.binaryProperties.Main_class),
- },
- })
- j.wrapperFile = wrapper
- }
- } else {
- j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
- }
- }
-
- ext := ""
if ctx.Windows() {
- ext = ".bat"
+ ctx.PropertyErrorf("wrapper", "wrapper is required for Windows")
}
- // The host installation rules make the installed wrapper depend on all the dependencies
- // of the wrapper variant, which will include the common variant's jar file and any JNI
- // libraries. This is verified by TestBinary.
- j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
- ctx.ModuleName()+ext, j.wrapperFile)
-
- setOutputFiles(ctx, j.Library.Module)
-
- // Set the jniLibs of this binary.
- // These will be added to `LOCAL_REQUIRED_MODULES`, and the kati packaging system will
- // install these alongside the java binary.
- ctx.VisitDirectDepsWithTag(jniInstallTag, func(jni android.Module) {
- // Use the BaseModuleName of the dependency (without any prebuilt_ prefix)
- bmn, _ := jni.(interface{ BaseModuleName() string })
- j.androidMkNamesOfJniLibs = append(j.androidMkNamesOfJniLibs, bmn.BaseModuleName()+":"+jni.Target().Arch.ArchType.Bitness())
- })
- // Check that native libraries are not listed in `required`. Prompt users to use `jni_libs` instead.
- ctx.VisitDirectDepsWithTag(android.RequiredDepTag, func(dep android.Module) {
- if _, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider); hasSharedLibraryInfo {
- ctx.ModuleErrorf("cc_library %s is no longer supported in `required` of java_binary modules. Please use jni_libs instead.", dep.Name())
+ if ctx.Device() {
+ // device binary should have a main_class property if it does not
+ // have a specific wrapper, so that a default wrapper can
+ // be generated for it.
+ if j.binaryProperties.Main_class == nil {
+ ctx.PropertyErrorf("main_class", "main_class property "+
+ "is required for device binary if no default wrapper is assigned")
+ } else {
+ wrapper := android.PathForModuleOut(ctx, ctx.ModuleName()+".sh")
+ jarName := j.Stem() + ".jar"
+ partition := j.PartitionTag(ctx.DeviceConfig())
+ ctx.Build(pctx, android.BuildParams{
+ Rule: deviceBinaryWrapper,
+ Output: wrapper,
+ Args: map[string]string{
+ "jar_name": jarName,
+ "partition": partition,
+ "main_class": String(j.binaryProperties.Main_class),
+ },
+ })
+ j.wrapperFile = wrapper
}
- })
+ } else {
+ j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
+ }
}
+
+ ext := ""
+ if ctx.Windows() {
+ ext = ".bat"
+ }
+
+ // The host installation rules make the installed wrapper depend on all the dependencies
+ // of the wrapper variant, which will include the common variant's jar file and any JNI
+ // libraries. This is verified by TestBinary. Also make it depend on the jar file so that
+ // the binary file timestamp will update when the jar file timestamp does. The jar file is
+ // built later on, in j.Library.GenerateAndroidBuildActions, so we have to create an identical
+ // installpath representing it here.
+ j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
+ ctx.ModuleName()+ext, j.wrapperFile, j.getJarInstallDir(ctx).Join(ctx, j.Stem()+".jar"))
+
+ // Set the jniLibs of this binary.
+ // These will be added to `LOCAL_REQUIRED_MODULES`, and the kati packaging system will
+ // install these alongside the java binary.
+ ctx.VisitDirectDepsWithTag(jniInstallTag, func(jni android.Module) {
+ // Use the BaseModuleName of the dependency (without any prebuilt_ prefix)
+ bmn, _ := jni.(interface{ BaseModuleName() string })
+ j.androidMkNamesOfJniLibs = append(j.androidMkNamesOfJniLibs, bmn.BaseModuleName()+":"+jni.Target().Arch.ArchType.Bitness())
+ })
+ // Check that native libraries are not listed in `required`. Prompt users to use `jni_libs` instead.
+ ctx.VisitDirectDepsWithTag(android.RequiredDepTag, func(dep android.Module) {
+ if _, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider); hasSharedLibraryInfo {
+ ctx.ModuleErrorf("cc_library %s is no longer supported in `required` of java_binary modules. Please use jni_libs instead.", dep.Name())
+ }
+ })
+
+ // Compile the jar
+ if j.binaryProperties.Main_class != nil {
+ if j.properties.Manifest != nil {
+ ctx.PropertyErrorf("main_class", "main_class cannot be used when manifest is set")
+ }
+ manifestFile := android.PathForModuleOut(ctx, "manifest.txt")
+ GenerateMainClassManifest(ctx, manifestFile, String(j.binaryProperties.Main_class))
+ j.overrideManifest = android.OptionalPathForPath(manifestFile)
+ }
+
+ j.Library.GenerateAndroidBuildActions(ctx)
}
func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) {
- if ctx.Arch().ArchType == android.Common {
- j.deps(ctx)
- }
+ j.deps(ctx)
// These dependencies ensure the installation rules will install the jar file when the
// wrapper is installed, and the jni libraries when the wrapper is installed.
- if ctx.Arch().ArchType != android.Common {
- ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...)
- ctx.AddVariationDependencies(
- []blueprint.Variation{{Mutator: "arch", Variation: android.CommonArch.String()}},
- binaryInstallTag, ctx.ModuleName())
+ if ctx.Os().Class == android.Host {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniInstallTag, j.binaryProperties.Jni_libs...)
+ } else if ctx.Os().Class == android.Device {
+ ctx.AddVariationDependencies(ctx.Config().AndroidFirstDeviceTarget.Variations(), jniInstallTag, j.binaryProperties.Jni_libs...)
+ } else {
+ ctx.ModuleErrorf("Unknown os class")
}
}
@@ -1929,7 +1939,7 @@
module.Module.properties.Installable = proptools.BoolPtr(true)
- android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommonFirst)
+ android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
return module
@@ -1947,7 +1957,7 @@
module.Module.properties.Installable = proptools.BoolPtr(true)
- android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommonFirst)
+ android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
return module
}
@@ -2456,7 +2466,7 @@
ret := []string{}
ret = append(ret, al.properties.Libs.GetOrDefault(ctx, nil)...)
ret = append(ret, al.properties.Static_libs.GetOrDefault(ctx, nil)...)
- if al.properties.System_modules != nil {
+ if proptools.StringDefault(al.properties.System_modules, "none") != "none" {
ret = append(ret, proptools.String(al.properties.System_modules))
}
// Other non java_library dependencies like java_api_contribution are ignored for now.
@@ -3345,7 +3355,7 @@
if sdkLib != nil {
optional := false
if module, ok := ctx.Module().(ModuleWithUsesLibrary); ok {
- if android.InList(*sdkLib, module.UsesLibrary().usesLibraryProperties.Optional_uses_libs) {
+ if android.InList(*sdkLib, module.UsesLibrary().usesLibraryProperties.Optional_uses_libs.GetOrDefault(ctx, nil)) {
optional = true
}
}
diff --git a/java/java_resources.go b/java/java_resources.go
index b0dc5a1..c525233 100644
--- a/java/java_resources.go
+++ b/java/java_resources.go
@@ -17,6 +17,7 @@
import (
"fmt"
"path/filepath"
+ "slices"
"strings"
"github.com/google/blueprint/pathtools"
@@ -99,10 +100,7 @@
// that should not be treated as resources (including *.java).
func ResourceFilesToJarArgs(ctx android.ModuleContext,
res, exclude []string) (args []string, deps android.Paths) {
-
- exclude = append([]string(nil), exclude...)
- exclude = append(exclude, resourceExcludes...)
- return resourceFilesToJarArgs(ctx, res, exclude)
+ return resourceFilesToJarArgs(ctx, res, slices.Concat(exclude, resourceExcludes))
}
func resourceFilesToJarArgs(ctx android.ModuleContext,
diff --git a/java/java_test.go b/java/java_test.go
index 24dabdb1..54eb3e1 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -569,8 +569,7 @@
bar := ctx.ModuleForTests("bar", buildOS+"_common")
barJar := bar.Output("bar.jar").Output.String()
- barWrapper := ctx.ModuleForTests("bar", buildOS+"_x86_64")
- barWrapperDeps := barWrapper.Output("bar").Implicits.Strings()
+ barWrapperDeps := bar.Output("bar").Implicits.Strings()
libjni := ctx.ModuleForTests("libjni", buildOS+"_x86_64_shared")
libjniSO := libjni.Rule("Cp").Output.String()
@@ -1174,7 +1173,7 @@
filegroup {
name: "core-jar",
- srcs: [":core{.jar}"],
+ device_common_srcs: [":core{.jar}"],
}
`),
})
@@ -1190,7 +1189,7 @@
filegroup {
name: "core-jar",
- srcs: [":core{.jar}"],
+ device_common_srcs: [":core{.jar}"],
}
`),
})
@@ -1931,7 +1930,7 @@
main_class: "foo.bar.jb",
}
`)
- wrapperPath := fmt.Sprint(ctx.ModuleForTests("foo", "android_arm64_armv8-a").AllOutputs())
+ wrapperPath := fmt.Sprint(ctx.ModuleForTests("foo", "android_common").AllOutputs())
if !strings.Contains(wrapperPath, "foo.sh") {
t.Errorf("wrapper file foo.sh is not generated")
}
@@ -3125,13 +3124,6 @@
}
`
res, _ := testJava(t, bp)
- // The first variant installs the native library via the common variant, so check the deps of both variants.
- nativeVariantDepsWithDups := findDepsOfModule(res, res.ModuleForTests("myjavabin", "android_arm64_armv8-a").Module(), "mynativelib")
- nativeVariantDepsWithDups = append(nativeVariantDepsWithDups, findDepsOfModule(res, res.ModuleForTests("myjavabin", "android_common").Module(), "mynativelib")...)
-
- nativeVariantDepsUnique := map[blueprint.Module]bool{}
- for _, dep := range nativeVariantDepsWithDups {
- nativeVariantDepsUnique[dep] = true
- }
- android.AssertIntEquals(t, "Create a dep on the first variant", 1, len(nativeVariantDepsUnique))
+ deps := findDepsOfModule(res, res.ModuleForTests("myjavabin", "android_common").Module(), "mynativelib")
+ android.AssertIntEquals(t, "Create a dep on the first variant", 1, len(deps))
}
diff --git a/java/jdeps_test.go b/java/jdeps_test.go
index d282f19..1435000 100644
--- a/java/jdeps_test.go
+++ b/java/jdeps_test.go
@@ -109,7 +109,7 @@
module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
- android.AssertBoolEquals(t, "IdeInfo.Srcs of repackaged library should be empty", true, len(dpInfo.Srcs) == 0)
+ android.AssertStringEquals(t, "IdeInfo.Srcs of repackaged library should not be empty", "foo.java", dpInfo.Srcs[0])
android.AssertStringEquals(t, "IdeInfo.Jar_rules of repackaged library should not be empty", "jarjar_rules.txt", dpInfo.Jarjar_rules[0])
if !android.SubstringInList(dpInfo.Jars, "soong/.intermediates/javalib/android_common/jarjar/turbine/javalib.jar") {
t.Errorf("IdeInfo.Jars of repackaged library should contain the output of jarjar-ing. All outputs: %v\n", dpInfo.Jars)
@@ -134,3 +134,42 @@
android.AssertStringListContains(t, "IdeInfo.Deps should contain versioned sdk module", dpInfo.Deps, "sdk_public_29_android")
}
+
+func TestDoNotAddNoneSystemModulesToDeps(t *testing.T) {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t,
+ `
+ java_library {
+ name: "javalib",
+ srcs: ["foo.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ }
+
+ java_api_library {
+ name: "javalib.stubs",
+ stubs_type: "everything",
+ api_contributions: ["javalib-current.txt"],
+ api_surface: "public",
+ system_modules: "none",
+ }
+ java_api_contribution {
+ name: "javalib-current.txt",
+ api_file: "javalib-current.txt",
+ api_surface: "public",
+ }
+ `)
+ javalib := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
+ dpInfo, _ := android.OtherModuleProvider(ctx, javalib, android.IdeInfoProviderKey)
+ android.AssertStringListDoesNotContain(t, "IdeInfo.Deps should contain not contain `none`", dpInfo.Deps, "none")
+
+ javalib_stubs := ctx.ModuleForTests("javalib.stubs", "android_common").Module().(*ApiLibrary)
+ dpInfo, _ = android.OtherModuleProvider(ctx, javalib_stubs, android.IdeInfoProviderKey)
+ android.AssertStringListDoesNotContain(t, "IdeInfo.Deps should contain not contain `none`", dpInfo.Deps, "none")
+}
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index f6e7fca..45eac01 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -500,8 +500,8 @@
name: "androidx.compose.runtime_runtime",
}
- java_library_host {
- name: "androidx.compose.compiler_compiler-hosted",
+ kotlin_plugin {
+ name: "androidx.compose.compiler_compiler-hosted-plugin",
}
java_library {
@@ -523,7 +523,7 @@
buildOS := result.Config.BuildOS.String()
- composeCompiler := result.ModuleForTests("androidx.compose.compiler_compiler-hosted", buildOS+"_common").Rule("combineJar").Output
+ composeCompiler := result.ModuleForTests("androidx.compose.compiler_compiler-hosted-plugin", buildOS+"_common").Rule("combineJar").Output
withCompose := result.ModuleForTests("withcompose", "android_common")
noCompose := result.ModuleForTests("nocompose", "android_common")
@@ -542,3 +542,50 @@
android.AssertStringDoesNotContain(t, "unexpected compose compiler plugin",
noCompose.VariablesForTestsRelativeToTop()["kotlincFlags"], "-Xplugin="+composeCompiler.String())
}
+
+func TestKotlinPlugin(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, `
+ kotlin_plugin {
+ name: "kotlin_plugin",
+ }
+
+ java_library {
+ name: "with_kotlin_plugin",
+ srcs: ["a.kt"],
+ plugins: ["plugin"],
+ kotlin_plugins: ["kotlin_plugin"],
+ }
+
+ java_library {
+ name: "no_kotlin_plugin",
+ srcs: ["a.kt"],
+ }
+
+ java_plugin {
+ name: "plugin",
+ }
+ `)
+
+ buildOS := result.Config.BuildOS.String()
+
+ kotlinPlugin := result.ModuleForTests("kotlin_plugin", buildOS+"_common").Rule("combineJar").Output
+ withKotlinPlugin := result.ModuleForTests("with_kotlin_plugin", "android_common")
+ noKotlinPlugin := result.ModuleForTests("no_kotlin_plugin", "android_common")
+
+ android.AssertStringListContains(t, "missing plugin compiler dependency",
+ withKotlinPlugin.Rule("kotlinc").Implicits.Strings(), kotlinPlugin.String())
+
+ android.AssertStringDoesContain(t, "missing kotlin plugin",
+ withKotlinPlugin.VariablesForTestsRelativeToTop()["kotlincFlags"], "-Xplugin="+kotlinPlugin.String())
+
+ android.AssertStringListContains(t, "missing kapt kotlin plugin dependency",
+ withKotlinPlugin.Rule("kapt").Implicits.Strings(), kotlinPlugin.String())
+
+ android.AssertStringListDoesNotContain(t, "unexpected kotlin plugin dependency",
+ noKotlinPlugin.Rule("kotlinc").Implicits.Strings(), kotlinPlugin.String())
+
+ android.AssertStringDoesNotContain(t, "unexpected kotlin plugin",
+ noKotlinPlugin.VariablesForTestsRelativeToTop()["kotlincFlags"], "-Xplugin="+kotlinPlugin.String())
+}
diff --git a/java/plugin.go b/java/plugin.go
index 9c4774a..610c9fd 100644
--- a/java/plugin.go
+++ b/java/plugin.go
@@ -24,6 +24,7 @@
func registerJavaPluginBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("java_plugin", PluginFactory)
+ ctx.RegisterModuleType("kotlin_plugin", KotlinPluginFactory)
}
func PluginFactory() android.Module {
@@ -37,6 +38,16 @@
return module
}
+func KotlinPluginFactory() android.Module {
+ module := &KotlinPlugin{}
+
+ module.addHostProperties()
+
+ InitJavaModule(module, android.HostSupported)
+
+ return module
+}
+
// Plugin describes a java_plugin module, a host java library that will be used by javac as an annotation processor.
type Plugin struct {
Library
@@ -53,3 +64,8 @@
// parallelism and cause more recompilation for modules that depend on modules that use this plugin.
Generates_api *bool
}
+
+// Plugin describes a kotlin_plugin module, a host java/kotlin library that will be used by kotlinc as a compiler plugin.
+type KotlinPlugin struct {
+ Library
+}
diff --git a/java/robolectric.go b/java/robolectric.go
index 30c7203..fb820ef 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -149,6 +149,8 @@
HostTemplate: "${RobolectricTestConfigTemplate}",
})
r.data = android.PathsForModuleSrc(ctx, r.testProperties.Data)
+ r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_common_data)...)
+ r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_first_data)...)
var ok bool
var instrumentedApp *AndroidApp
@@ -208,6 +210,11 @@
installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
var installDeps android.InstallPaths
+ for _, data := range r.data {
+ installedData := ctx.InstallFile(installPath, data.Rel(), data)
+ installDeps = append(installDeps, installedData)
+ }
+
if manifest != nil {
r.data = append(r.data, manifest)
installedManifest := ctx.InstallFile(installPath, ctx.ModuleName()+"-AndroidManifest.xml", manifest)
@@ -228,11 +235,6 @@
installedConfig := ctx.InstallFile(installPath, ctx.ModuleName()+".config", r.testConfig)
installDeps = append(installDeps, installedConfig)
- for _, data := range android.PathsForModuleSrc(ctx, r.testProperties.Data) {
- installedData := ctx.InstallFile(installPath, data.Rel(), data)
- installDeps = append(installDeps, installedData)
- }
-
soInstallPath := installPath.Join(ctx, getLibPath(r.forceArchType))
for _, jniLib := range collectTransitiveJniDeps(ctx) {
installJni := ctx.InstallFile(soInstallPath, jniLib.path.Base(), jniLib.path)
diff --git a/java/sdk_library_internal.go b/java/sdk_library_internal.go
index ca088cf..768e57a 100644
--- a/java/sdk_library_internal.go
+++ b/java/sdk_library_internal.go
@@ -566,7 +566,7 @@
Min_device_sdk *string
Max_device_sdk *string
Sdk_library_min_api_level *string
- Uses_libs_dependencies []string
+ Uses_libs_dependencies proptools.Configurable[[]string]
}{
Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
Enabled: module.EnabledProperty(),
@@ -577,7 +577,7 @@
Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk,
Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk,
Sdk_library_min_api_level: &moduleMinApiLevelStr,
- Uses_libs_dependencies: module.usesLibraryProperties.Uses_libs,
+ Uses_libs_dependencies: module.usesLibraryProperties.Uses_libs.Clone(),
}
mctx.CreateModule(sdkLibraryXmlFactory, &props)
@@ -742,7 +742,7 @@
// Uses-libs dependencies that the shared library requires to work correctly.
//
// This will add dependency="foo:bar" to the <library> section.
- Uses_libs_dependencies []string
+ Uses_libs_dependencies proptools.Configurable[[]string]
}
// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
@@ -864,7 +864,7 @@
implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before)
minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk)
maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk)
- dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies)
+ dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies.GetOrDefault(ctx, nil))
// <library> is understood in all android versions whereas <apex-library> is only understood from API T (and ignored before that).
// similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the apex-library to make sure this library is not loaded before T
var libraryTag string
diff --git a/python/python.go b/python/python.go
index 01ac86c..d3e5743 100644
--- a/python/python.go
+++ b/python/python.go
@@ -90,6 +90,11 @@
// the test. the file extension can be arbitrary except for (.py).
Data []string `android:"path,arch_variant"`
+ // Same as data, but will add dependencies on modules using the device's os variation and
+ // the common arch variation. Useful for a host test that wants to embed a module built for
+ // device.
+ Device_common_data []string `android:"path_device_common"`
+
// list of java modules that provide data that should be installed alongside the test.
Java_data []string
@@ -451,6 +456,7 @@
// expand data files from "data" property.
expandedData := android.PathsForModuleSrc(ctx, p.properties.Data)
+ expandedData = append(expandedData, android.PathsForModuleSrc(ctx, p.properties.Device_common_data)...)
// Emulate the data property for java_data dependencies.
for _, javaData := range ctx.GetDirectDepsWithTag(javaDataTag) {
diff --git a/rust/bindgen.go b/rust/bindgen.go
index abb5181..3944495 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -186,7 +186,7 @@
// Default clang flags
cflags = append(cflags, "${cc_config.CommonGlobalCflags}")
if ctx.Device() {
- cflags = append(cflags, "${cc_config.DeviceGlobalCflags}")
+ cflags = append(cflags, "${cc_config.DeviceGlobalCflags}", "-nostdlibinc")
}
// Toolchain clang flags
diff --git a/rust/image.go b/rust/image.go
index 26929b1..51b8289 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -85,7 +85,7 @@
mod.Properties.VendorVariantNeeded = b
}
-func (mod *Module) SnapshotVersion(mctx android.BaseModuleContext) string {
+func (mod *Module) SnapshotVersion(mctx android.ImageInterfaceContext) string {
if snapshot, ok := mod.compiler.(cc.SnapshotInterface); ok {
return snapshot.Version()
} else {
@@ -94,35 +94,35 @@
}
}
-func (mod *Module) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
+func (mod *Module) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
return mod.Properties.VendorVariantNeeded
}
-func (mod *Module) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
+func (mod *Module) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
return mod.Properties.ProductVariantNeeded
}
-func (mod *Module) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (mod *Module) VendorRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return mod.Properties.VendorRamdiskVariantNeeded
}
-func (mod *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+func (mod *Module) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
return mod.Properties.CoreVariantNeeded
}
-func (mod *Module) RamdiskVariantNeeded(android.BaseModuleContext) bool {
+func (mod *Module) RamdiskVariantNeeded(android.ImageInterfaceContext) bool {
return mod.Properties.RamdiskVariantNeeded
}
-func (mod *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (mod *Module) DebugRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (mod *Module) RecoveryVariantNeeded(android.BaseModuleContext) bool {
+func (mod *Module) RecoveryVariantNeeded(android.ImageInterfaceContext) bool {
return mod.Properties.RecoveryVariantNeeded
}
-func (mod *Module) ExtraImageVariations(android.BaseModuleContext) []string {
+func (mod *Module) ExtraImageVariations(android.ImageInterfaceContext) []string {
return mod.Properties.ExtraVariants
}
@@ -213,7 +213,7 @@
return mod.InVendor() || mod.InProduct()
}
-func (mod *Module) SetImageVariation(ctx android.BaseModuleContext, variant string) {
+func (mod *Module) SetImageVariation(ctx android.ImageInterfaceContext, variant string) {
if variant == android.VendorRamdiskVariation {
mod.MakeAsPlatform()
} else if variant == android.RecoveryVariation {
@@ -231,7 +231,7 @@
}
}
-func (mod *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
+func (mod *Module) ImageMutatorBegin(mctx android.ImageInterfaceContext) {
if Bool(mod.VendorProperties.Double_loadable) {
mctx.PropertyErrorf("double_loadable",
"Rust modules do not yet support double loading")
diff --git a/rust/rust.go b/rust/rust.go
index a044a99..b22ebf7 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -47,11 +47,11 @@
func registerPreDepsMutators(ctx android.RegisterMutatorsContext) {
ctx.Transition("rust_libraries", &libraryTransitionMutator{})
ctx.Transition("rust_stdlinkage", &libstdTransitionMutator{})
- ctx.BottomUp("rust_begin", BeginMutator).Parallel()
+ ctx.BottomUp("rust_begin", BeginMutator)
}
func registerPostDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel()
+ ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator)
}
type Flags struct {
diff --git a/rust/test.go b/rust/test.go
index b7ddd06..20ccfb3 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -46,6 +46,9 @@
// the test
Data []string `android:"path,arch_variant"`
+ // Same as data, but will add dependencies on the device's
+ Device_common_data []string `android:"path_device_common"`
+
// list of shared library modules that should be installed alongside the test
Data_libs []string `android:"arch_variant"`
@@ -143,6 +146,7 @@
})
dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
+ dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_common_data)...)
ctx.VisitDirectDepsWithTag(dataLibDepTag, func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
diff --git a/scripts/hiddenapi/Android.bp b/scripts/hiddenapi/Android.bp
index 43edf44..061af19 100644
--- a/scripts/hiddenapi/Android.bp
+++ b/scripts/hiddenapi/Android.bp
@@ -27,6 +27,12 @@
libs: [
"signature_trie",
],
+ target: {
+ windows: {
+ // go modules (bpmodify) don't support windows
+ enabled: false,
+ },
+ },
}
python_test_host {
@@ -44,6 +50,12 @@
test_options: {
unit_test: true,
},
+ target: {
+ windows: {
+ // go modules (bpmodify) don't support windows
+ enabled: false,
+ },
+ },
}
python_binary_host {
diff --git a/scripts/keep-flagged-apis.sh b/scripts/keep-flagged-apis.sh
index 9c48fdb..48efb7a 100755
--- a/scripts/keep-flagged-apis.sh
+++ b/scripts/keep-flagged-apis.sh
@@ -25,21 +25,12 @@
# Convert the list of feature flags in the input file to Metalava options
# of the form `--revert-annotation !android.annotation.FlaggedApi("<flag>")`
# to prevent the annotated APIs from being hidden, i.e. include the annotated
-# APIs in the SDK snapshots. This also preserves the line comments, they will
-# be ignored by Metalava but might be useful when debugging.
+# APIs in the SDK snapshots.
while read -r line; do
- key=$(echo "$line" | cut -d= -f1)
- value=$(echo "$line" | cut -d= -f2)
-
- # Skip if value is not true and line does not start with '#'
- if [[ ( $value != "true" ) && ( $line =~ ^[^#] )]]; then
- continue
- fi
-
# Escape and quote the key for sed
- escaped_key=$(echo "$key" | sed "s/'/\\\'/g; s/ /\\ /g")
+ escaped_line=$(echo "$line" | sed "s/'/\\\'/g; s/ /\\ /g")
- echo $line | sed "s|^[^#].*$|--revert-annotation '!$FLAGGED(\"$escaped_key\")'|"
+ echo "--revert-annotation '!$FLAGGED(\"$escaped_line\")'"
done < "$FLAGS"
# Revert all flagged APIs, unless listed above.
diff --git a/sdk/genrule_test.go b/sdk/genrule_test.go
index 6e52a3d..bf67795 100644
--- a/sdk/genrule_test.go
+++ b/sdk/genrule_test.go
@@ -23,21 +23,14 @@
)
func TestSdkGenrule(t *testing.T) {
- // Test that an sdk_genrule can depend on an sdk, and that a genrule can depend on an sdk_genrule
+ // Test that a genrule can depend on an sdk if using common_os_srcs
bp := `
sdk {
name: "my_sdk",
}
- sdk_genrule {
- name: "my_sdk_genrule",
- tool_files: ["tool"],
- cmd: "$(location tool) $(in) $(out)",
- srcs: [":my_sdk"],
- out: ["out"],
- }
genrule {
name: "my_regular_genrule",
- srcs: [":my_sdk_genrule"],
+ common_os_srcs: [":my_sdk"],
out: ["out"],
cmd: "cp $(in) $(out)",
}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 15e13db..4db163c 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -1724,7 +1724,7 @@
filegroup {
name: "mygroup",
- srcs: [":myjavalib{.doctags}"],
+ device_common_srcs: [":myjavalib{.doctags}"],
}
`)
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 2e48d83..3991449 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -120,6 +120,16 @@
// the test.
Data []string `android:"path,arch_variant"`
+ // same as data, but adds dependencies using the device's os variation and the common
+ // architecture's variation. Can be used to add a module built for device to the data of a
+ // host test.
+ Device_common_data []string `android:"path_device_common"`
+
+ // same as data, but adds dependencies using the device's os variation and the device's first
+ // architecture's variation. Can be used to add a module built for device to the data of a
+ // host test.
+ Device_first_data []string `android:"path_device_first"`
+
// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
// with root permission.
Require_root *bool
@@ -210,41 +220,41 @@
var _ android.ImageInterface = (*ShBinary)(nil)
-func (s *ShBinary) ImageMutatorBegin(ctx android.BaseModuleContext) {}
+func (s *ShBinary) ImageMutatorBegin(ctx android.ImageInterfaceContext) {}
-func (s *ShBinary) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
+func (s *ShBinary) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
return s.InstallInVendor()
}
-func (s *ShBinary) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
+func (s *ShBinary) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
return s.InstallInProduct()
}
-func (s *ShBinary) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+func (s *ShBinary) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
return !s.InstallInRecovery() && !s.InstallInRamdisk() && !s.InstallInVendorRamdisk() && !s.ModuleBase.InstallInVendor()
}
-func (s *ShBinary) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (s *ShBinary) RamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return proptools.Bool(s.properties.Ramdisk_available) || s.InstallInRamdisk()
}
-func (s *ShBinary) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (s *ShBinary) VendorRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return proptools.Bool(s.properties.Vendor_ramdisk_available) || s.InstallInVendorRamdisk()
}
-func (s *ShBinary) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (s *ShBinary) DebugRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
return false
}
-func (s *ShBinary) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+func (s *ShBinary) RecoveryVariantNeeded(ctx android.ImageInterfaceContext) bool {
return proptools.Bool(s.properties.Recovery_available) || s.InstallInRecovery()
}
-func (s *ShBinary) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+func (s *ShBinary) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
return nil
}
-func (s *ShBinary) SetImageVariation(ctx android.BaseModuleContext, variation string) {
+func (s *ShBinary) SetImageVariation(ctx android.ImageInterfaceContext, variation string) {
s.properties.ImageVariation = variation
}
@@ -407,6 +417,8 @@
s.ShBinary.generateAndroidBuildActions(ctx)
expandedData := android.PathsForModuleSrc(ctx, s.testProperties.Data)
+ expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Device_common_data)...)
+ expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Device_first_data)...)
// Emulate the data property for java_data dependencies.
for _, javaData := range ctx.GetDirectDepsWithTag(shTestJavaDataTag) {
expandedData = append(expandedData, android.OutputFilesForModule(ctx, javaData, "")...)
diff --git a/tradefed_modules/test_module_config_test.go b/tradefed_modules/test_module_config_test.go
index f76a152..cf6c7d1 100644
--- a/tradefed_modules/test_module_config_test.go
+++ b/tradefed_modules/test_module_config_test.go
@@ -123,24 +123,24 @@
// Ensure we error for a base we don't support.
func TestModuleConfigWithHostBaseShouldFailWithExplicitMessage(t *testing.T) {
badBp := `
- java_test_host {
- name: "base",
- srcs: ["a.java"],
+ java_test {
+ name: "base",
+ srcs: ["a.java"],
}
- test_module_config {
- name: "derived_test",
- base: "base",
- exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
- include_annotations: ["android.platform.test.annotations.LargeTest"],
- test_suites: ["general-tests"],
- }`
+ test_module_config {
+ name: "derived_test",
+ base: "base",
+ exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
+ include_annotations: ["android.platform.test.annotations.LargeTest"],
+ test_suites: ["general-tests"],
+ }`
android.GroupFixturePreparers(
java.PrepareForTestWithJavaDefaultModules,
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
).ExtendWithErrorHandler(
- android.FixtureExpectsAtLeastOneErrorMatchingPattern("'java_test_host' module used as base, but 'android_test' expected")).
+ android.FixtureExpectsAtLeastOneErrorMatchingPattern("'base' module used as base but it is not a 'android_test' module.")).
RunTestWithBp(t, badBp)
}
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index fcf29c5..1f842f5 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -35,7 +35,6 @@
"blueprint",
"blueprint-bootstrap",
"blueprint-microfactory",
- "soong-android",
"soong-elf",
"soong-finder",
"soong-remoteexec",
diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go
index 2ec8972..c54d55f 100644
--- a/ui/build/androidmk_denylist.go
+++ b/ui/build/androidmk_denylist.go
@@ -64,3 +64,37 @@
}
}
}
+
+// The Android.mk files in these directories are for NDK build system.
+var external_ndk_androidmks []string = []string{
+ "external/fmtlib/",
+ "external/google-breakpad/",
+ "external/googletest/",
+ "external/libaom/",
+ "external/libusb/",
+ "external/libvpx/",
+ "external/libwebm/",
+ "external/libwebsockets/",
+ "external/vulkan-validation-layers/",
+ "external/walt/",
+ "external/webp/",
+}
+
+func ignoreNdkAndroidMks(androidMks []string) (filtered []string) {
+ filter := func(s string) bool {
+ for _, d := range external_ndk_androidmks {
+ if strings.HasPrefix(s, d) {
+ return false
+ }
+ }
+ return true
+ }
+
+ for _, l := range androidMks {
+ if filter(l) {
+ filtered = append(filtered, l)
+ }
+ }
+
+ return
+}
diff --git a/ui/build/config.go b/ui/build/config.go
index 75edfcd..9ec04a0 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -98,7 +98,6 @@
buildFromSourceStub bool
incrementalBuildActions bool
ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built
- partialCompileFlags partialCompileFlags
// From the product config
katiArgs []string
@@ -138,16 +137,6 @@
ninjaCommand ninjaCommandType
}
-type partialCompileFlags struct {
- // Is partial compilation enabled at all?
- enabled bool
-
- // Whether to use d8 instead of r8
- use_d8 bool
-
- // Add others as needed.
-}
-
type NinjaWeightListSource uint
const (
@@ -304,12 +293,24 @@
ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
}
- ret.partialCompileFlags = parsePartialCompileFlags(ctx)
-
if os.Getenv("GENERATE_SOONG_DEBUG") == "true" {
ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json"))
}
+ // If SOONG_USE_PARTIAL_COMPILE is set, make it one of "true" or the empty string.
+ // This simplifies the generated Ninja rules, so that they only need to check for the empty string.
+ if value, ok := os.LookupEnv("SOONG_USE_PARTIAL_COMPILE"); ok {
+ if value == "true" || value == "1" || value == "y" || value == "yes" {
+ value = "true"
+ } else {
+ value = ""
+ }
+ err = os.Setenv("SOONG_USE_PARTIAL_COMPILE", value)
+ if err != nil {
+ ctx.Fatalln("Failed to set SOONG_USE_PARTIAL_COMPILE: %v", err)
+ }
+ }
+
ret.ninjaCommand = NINJA_NINJA
switch os.Getenv("SOONG_NINJA") {
case "n2":
@@ -382,7 +383,6 @@
// Use config.ninjaCommand instead.
"SOONG_NINJA",
"SOONG_USE_N2",
- "SOONG_PARTIAL_COMPILE",
)
if ret.UseGoma() || ret.ForceUseGoma() {
@@ -501,78 +501,6 @@
return c
}
-// Parse SOONG_PARTIAL_COMPILE.
-//
-// The user-facing documentation shows:
-//
-// - empty or not set: "The current default state"
-// - "true" or "on": enable all stable partial compile features.
-// - "false" or "off": disable partial compile completely.
-//
-// What we actually allow is a comma separated list of tokens, whose first
-// character may be "+" (enable) or "-" (disable). If neither is present, "+"
-// is assumed. For example, "on,+use_d8" will enable partial compilation, and
-// additionally set the use_d8 flag (regardless of whether it is opt-in or
-// opt-out).
-//
-// To add a new feature to the list, add the field in the struct
-// `partialCompileFlags` above, and then add the name of the field in the
-// switch statement below.
-func parsePartialCompileFlags(ctx Context) partialCompileFlags {
- defaultFlags := partialCompileFlags{
- // Set any opt-out flags here. Opt-in flags are off by default.
- enabled: false,
- }
- value, ok := os.LookupEnv("SOONG_PARTIAL_COMPILE")
-
- if !ok {
- return defaultFlags
- }
-
- ret := defaultFlags
- tokens := strings.Split(strings.ToLower(value), ",")
- makeVal := func(state string, defaultValue bool) bool {
- switch state {
- case "":
- return defaultValue
- case "-":
- return false
- case "+":
- return true
- }
- return false
- }
- for _, tok := range tokens {
- var state string
- switch tok[0:1] {
- case "":
- // Ignore empty tokens.
- continue
- case "-", "+":
- state = tok[0:1]
- tok = tok[1:]
- default:
- // Treat `feature` as `+feature`.
- state = "+"
- }
- switch tok {
- case "true", "on", "yes":
- ret = defaultFlags
- ret.enabled = true
- case "false", "off", "no":
- // Set everything to false.
- ret = partialCompileFlags{}
- case "enabled":
- ret.enabled = makeVal(state, defaultFlags.enabled)
- case "use_d8":
- ret.use_d8 = makeVal(state, defaultFlags.use_d8)
- default:
- ctx.Fatalln("Unknown SOONG_PARTIAL_COMPILE value:", value)
- }
- }
- return ret
-}
-
// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
// processed based on the build action and extracts any arguments that belongs to the build action.
func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
@@ -1855,10 +1783,6 @@
return c.ensureAllowlistIntegrity
}
-func (c *configImpl) PartialCompileFlags() partialCompileFlags {
- return c.partialCompileFlags
-}
-
// Returns a Time object if one was passed via a command-line flag.
// Otherwise returns the passed default.
func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
diff --git a/ui/build/finder.go b/ui/build/finder.go
index 573df21..a899822 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -128,6 +128,7 @@
// Stop searching a subdirectory recursively after finding an Android.mk.
androidMks := f.FindFirstNamedAt(".", "Android.mk")
+ androidMks = ignoreNdkAndroidMks(androidMks)
blockAndroidMks(ctx, androidMks)
err := dumpListToFile(ctx, config, androidMks, filepath.Join(dumpDir, "Android.mk.list"))
if err != nil {
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 5743ff7..4dfb710 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -183,6 +183,23 @@
username = usernameFromEnv
}
+ // SOONG_USE_PARTIAL_COMPILE may be used in makefiles, but both cases must be supported.
+ //
+ // In general, the partial compile features will be implemented in Soong-based rules. We
+ // also allow them to be used in makefiles. Clear the environment variable when calling
+ // kati so that we avoid reanalysis when the user changes it. We will pass it to Ninja.
+ // As a result, rules where we want to allow the developer to toggle the feature ("use
+ // the partial compile feature" vs "legacy, aka full compile behavior") need to use this
+ // in the rule, since changing it will not cause reanalysis.
+ //
+ // Shell syntax in the rule might look something like this:
+ // if [[ -n ${SOONG_USE_PARTIAL_COMPILE} ]]; then
+ // # partial compile behavior
+ // else
+ // # legacy behavior
+ // fi
+ cmd.Environment.Unset("SOONG_USE_PARTIAL_COMPILE")
+
hostname, ok := cmd.Environment.Get("BUILD_HOSTNAME")
// Unset BUILD_HOSTNAME during kati run to avoid kati rerun, kati will use BUILD_HOSTNAME from a file.
cmd.Environment.Unset("BUILD_HOSTNAME")
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index def0783..f5f637f 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -241,6 +241,9 @@
"SOONG_USE_N2",
"RUST_BACKTRACE",
"RUST_LOG",
+
+ // SOONG_USE_PARTIAL_COMPILE only determines which half of the rule we execute.
+ "SOONG_USE_PARTIAL_COMPILE",
}, config.BuildBrokenNinjaUsesEnvVars()...)...)
}