aboutsummaryrefslogtreecommitdiff
path: root/android/module.go
diff options
context:
space:
mode:
authormosimchah <mosimchah@gmail.com>2025-12-02 09:27:38 -0500
committermosimchah <mosimchah@gmail.com>2025-12-02 09:27:38 -0500
commitc7bade461dc55726f62997d13a48582f7c4b4655 (patch)
treeea0588da76060a2038f54f67efd046ca77634b10 /android/module.go
parent0f5414d19317805e8bbbe7c4db5f0fd78769bad5 (diff)
parent89d78cff8b00d3b20a90074635c3fe5a2ee49474 (diff)
Merge branch 'lineage-23.1' of https://github.com/LineageOS/android_build_soong into HEADw16.1
* 'lineage-23.1' of https://github.com/LineageOS/android_build_soong: (528 commits) Revert "install_symlink: Make symlink target configurable" Reapply "Clear as much of cc.Module as possible after GenerateBuildActions" Revert "rust: config: Fix missing CPU variant LD flags in Rust" Rename build-flag in outdir Revert^4 "cipd: Default CIPD proxy server to on, add opt-out" Convert check-vintf-all to phony with actions Create a partial implementation of check-vintf-all for soong-only Configure RBE rust pool based on build variant Revert^3 "Add sdk version check to arr" Add jdk.internal.invoke to the allowlist Make droid always depend on symbols zip Import Device and Odm skus Don't install gob_gen in Soong Remove bazel reference from run_integration_tests.sh Fix bootstrap_test.sh Don't panic in aconfig libraries when AllowMissingDependencies is set Avoid returning nil paths from PathForModuleSrc Revert "Flag controled clang version" Rework module target dependencies on required deps Revert^2 "Add sdk version check to arr" ... Change-Id: I6e9a63fa14fda917a42e426e5dcebbad7f67e1de
Diffstat (limited to 'android/module.go')
-rw-r--r--android/module.go606
1 files changed, 406 insertions, 200 deletions
diff --git a/android/module.go b/android/module.go
index baacfa7e1..481e4107f 100644
--- a/android/module.go
+++ b/android/module.go
@@ -27,10 +27,12 @@ import (
"github.com/google/blueprint"
"github.com/google/blueprint/depset"
- "github.com/google/blueprint/gobtools"
+ "github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
)
+//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go
+
var (
DeviceSharedLibrary = "shared_library"
DeviceStaticLibrary = "static_library"
@@ -45,6 +47,14 @@ type Module interface {
// For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go
GenerateAndroidBuildActions(ModuleContext)
+ // CleanupAfterBuildActions is called after ModuleBase.GenerateBuildActions is finished.
+ // If all interactions with this module are handled via providers instead of direct access
+ // to the module then it can free memory attached to the module.
+ // This is a temporary measure to reduce memory usage, eventually blueprint's reference
+ // to the Module should be dropped after GenerateAndroidBuildActions once all accesses
+ // can be done through providers.
+ CleanupAfterBuildActions()
+
// Add dependencies to the components of a module, i.e. modules that are created
// by the module and which are considered to be part of the creating module.
//
@@ -112,7 +122,7 @@ type Module interface {
qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName
// Get information about the properties that can contain visibility rules.
- visibilityProperties() []visibilityProperty
+ visibilityProperties() []*visibilityProperty
RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string
HostRequiredModuleNames() []string
@@ -132,6 +142,8 @@ type Module interface {
// If this is true, the module must not read product-specific configurations.
UseGenericConfig() bool
+
+ NoFullInstall() bool
}
// Qualified id for a module
@@ -177,6 +189,7 @@ func newPackageId(pkg string) qualifiedModuleName {
return qualifiedModuleName{pkg: pkg, name: ""}
}
+// @auto-generate: gob
type Dist struct {
// Copy the output of this module to the $DIST_DIR when `dist` is specified on the
// command line and any of these targets are also on the command line, or otherwise
@@ -413,12 +426,6 @@ type commonProperties struct {
// Whether this module is built for non-native architectures (also known as native bridge binary)
Native_bridge_supported *bool `android:"arch_variant"`
- // init.rc files to be installed if this module is installed
- Init_rc proptools.Configurable[[]string] `android:"arch_variant,path"`
-
- // VINTF manifest fragments to be installed if this module is installed
- Vintf_fragments proptools.Configurable[[]string] `android:"path"`
-
// The OsType of artifacts that this module variant is responsible for creating.
//
// Set by osMutator
@@ -500,6 +507,7 @@ type commonProperties struct {
// Name and variant strings stored by mutators to enable Module.String()
DebugName string `blueprint:"mutated"`
+ DebugNamespace string `blueprint:"mutated"`
DebugMutators []string `blueprint:"mutated"`
DebugVariations []string `blueprint:"mutated"`
@@ -511,13 +519,6 @@ type commonProperties struct {
// The team (defined by the owner/vendor) who owns the property.
Team *string `android:"path"`
- // vintf_fragment Modules required from this module.
- Vintf_fragment_modules proptools.Configurable[[]string] `android:"path"`
-
- // List of module names that are prevented from being installed when this module gets
- // installed.
- Overrides []string
-
// Set to true if this module must be generic and does not require product-specific information.
// To be included in the system image, this property must be set to true.
Use_generic_config *bool
@@ -539,6 +540,19 @@ type baseProperties struct {
// module type. This is used by neverallow to ensure you can't bypass a ModuleType() matcher
// just by creating a soong config module type.
Soong_config_base_module_type *string `blueprint:"mutated"`
+
+ // init.rc files to be installed if this module is installed
+ Init_rc proptools.Configurable[[]string] `android:"arch_variant,path"`
+
+ // VINTF manifest fragments to be installed if this module is installed
+ Vintf_fragments proptools.Configurable[[]string] `android:"path"`
+
+ // vintf_fragment Modules required from this module.
+ Vintf_fragment_modules proptools.Configurable[[]string] `android:"path"`
+
+ // List of module names that are prevented from being installed when this module gets
+ // installed.
+ Overrides []string
}
type distProperties struct {
@@ -840,6 +854,7 @@ func InitCommonOSAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupport
// // ...
// }
type ModuleBase struct {
+ blueprint.ModuleBase
// Putting the curiously recurring thing pointing to the thing that contains
// the thing pattern to good use.
// TODO: remove this
@@ -862,13 +877,13 @@ type ModuleBase struct {
// Information about all the properties on the module that contains visibility rules that need
// checking.
- visibilityPropertyInfo []visibilityProperty
+ visibilityPropertyInfo []*visibilityProperty
// The primary visibility property, may be nil, that controls access to the module.
- primaryVisibilityProperty visibilityProperty
+ primaryVisibilityProperty *visibilityProperty
// The primary licenses property, may be nil, records license metadata for the module.
- primaryLicensesProperty applicableLicensesProperty
+ primaryLicensesProperty *applicableLicensesProperty
noAddressSanitizer bool
@@ -882,13 +897,6 @@ type ModuleBase struct {
variables map[string]string
}
-func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
- (*d)["Android"] = map[string]interface{}{
- // Properties set in Blueprint or in blueprint of a defaults modules
- "SetProperties": m.propertiesWithValues(),
- }
-}
-
type propInfo struct {
Name string
Type string
@@ -1032,6 +1040,9 @@ func (m *ModuleBase) baseOverridablePropertiesDepsMutator(ctx BottomUpMutatorCon
// addRequiredDeps adds required, target_required, and host_required as dependencies.
func addRequiredDeps(ctx BottomUpMutatorContext) {
addDep := func(target Target, depName string) {
+ if !blueprint.IsValidModuleName(depName) {
+ ctx.PropertyErrorf("required", "%s is not a valid module", depName)
+ }
if !ctx.OtherModuleExists(depName) {
if ctx.Config().AllowMissingDependencies() {
return
@@ -1118,29 +1129,21 @@ func addVintfFragmentDeps(ctx BottomUpMutatorContext) {
return
}
- deviceConfig := ctx.DeviceConfig()
-
mod := ctx.Module()
- vintfModules := ctx.AddDependency(mod, vintfDepTag, mod.VintfFragmentModuleNames(ctx)...)
+ ctx.AddDependency(mod, vintfDepTag, mod.VintfFragmentModuleNames(ctx)...)
+}
- 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
+func checkVintfFragmentDeps(ctx ModuleContext) {
+ modPartition := ctx.Module().PartitionTag(ctx.DeviceConfig())
+ ctx.VisitDirectDepsProxyWithTag(vintfDepTag, func(vintf ModuleProxy) {
+ commonInfo := OtherModulePointerProviderOrDefault(ctx, vintf, CommonModuleInfoProvider)
+ vintfPartition := commonInfo.PartitionTag
+ if modPartition != vintfPartition {
+ ctx.ModuleErrorf("Module %q(%q) and Vintf_fragment %q(%q) are installed to different partitions.",
+ ctx.ModuleName(), modPartition,
+ vintf.Name(), vintfPartition)
}
- if vintfModule, ok := vintf.(*VintfFragmentModule); ok {
- vintfPartition := vintfModule.PartitionTag(deviceConfig)
- if modPartition != vintfPartition {
- ctx.ModuleErrorf("Module %q(%q) and Vintf_fragment %q(%q) are installed to different partitions.",
- mod.Name(), modPartition,
- vintfModule.Name(), vintfPartition)
- }
- } else {
- ctx.ModuleErrorf("Only vintf_fragment type module should be listed in vintf_fragment_modules : %q", vintf.Name())
- }
- }
+ })
}
// AddProperties "registers" the provided props
@@ -1224,7 +1227,7 @@ func (m *ModuleBase) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleNam
return qualifiedModuleName{pkg: ctx.ModuleDir(), name: ctx.ModuleName()}
}
-func (m *ModuleBase) visibilityProperties() []visibilityProperty {
+func (m *ModuleBase) visibilityProperties() []*visibilityProperty {
return m.visibilityPropertyInfo
}
@@ -1307,6 +1310,10 @@ func (m *ModuleBase) IsCommonOSVariant() bool {
return m.commonProperties.CompileOS == CommonOS
}
+func (m *ModuleBase) NoFullInstall() bool {
+ return proptools.Bool(m.commonProperties.No_full_install)
+}
+
// supportsTarget returns true if the given Target is supported by the current module.
func (m *ModuleBase) supportsTarget(target Target) bool {
switch target.Os.Class {
@@ -1424,6 +1431,8 @@ func (m *ModuleBase) PartitionTag(config DeviceConfig) string {
partition = "vendor_ramdisk"
} else if m.InstallInRecovery() {
partition = "recovery"
+ } else if m.InstallInVendorDlkm() {
+ partition = "vendor_dlkm"
}
return partition
}
@@ -1660,45 +1669,54 @@ func (m *ModuleBase) TargetRequiredModuleNames() []string {
}
func (m *ModuleBase) VintfFragmentModuleNames(ctx ConfigurableEvaluatorContext) []string {
- return m.base().commonProperties.Vintf_fragment_modules.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
+ return m.base().baseProperties.Vintf_fragment_modules.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
}
func (m *ModuleBase) VintfFragments(ctx ConfigurableEvaluatorContext) []string {
- return m.base().commonProperties.Vintf_fragments.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
-}
-
-func (m *ModuleBase) generateVariantTarget(ctx *moduleContext) {
- namespacePrefix := ctx.Namespace().id
- if namespacePrefix != "" {
- namespacePrefix = namespacePrefix + "-"
- }
-
- if !ctx.uncheckedModule {
- name := namespacePrefix + ctx.ModuleName() + "-" + ctx.ModuleSubDir() + "-checkbuild"
- ctx.Phony(name, ctx.checkbuildFiles...)
- ctx.checkbuildTarget = PathForPhony(ctx, name)
- }
-
+ return m.base().baseProperties.Vintf_fragments.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
}
// generateModuleTarget generates phony targets so that you can do `m <module-name>`.
// It will be run on every variant of the module, so it relies on the fact that phony targets
// are deduped to merge all the deps from different variants together.
-func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) {
+func (m *ModuleBase) generateModuleTarget(ctx *moduleContext, testSuiteInstalls []filePair) {
var namespacePrefix string
nameSpace := ctx.Namespace().Path
if nameSpace != "." {
namespacePrefix = strings.ReplaceAll(nameSpace, "/", ".") + "-"
}
+ shouldSkipAndroidMk := shouldSkipAndroidMkProcessing(ctx, m)
+
+ phony := func(suffix string, deps Paths) string {
+ if ctx.Config().KatiEnabled() {
+ suffix += "-soong"
+ }
+ var ret string
+ // Create a target without the namespace prefix if it's exported to make. One of the
+ // conditions for being exported to make is that the namespace is in
+ // PRODUCT_SOONG_NAMESPACES, so historically that would mean that make would create the
+ // phonies for those modules as if they weren't in any namespace.
+ if !shouldSkipAndroidMk {
+ ret = ctx.module.base().BaseModuleName() + suffix
+ ctx.Phony(ret, deps...)
+ }
+ // Create another phony for building with the namespace specified. This can be used
+ // regardless of if the namespace is in PRODUCT_SOONG_NAMESPACES or not.
+ if nameSpace != "." {
+ ctx.Phony(namespacePrefix+ctx.module.base().BaseModuleName()+suffix, deps...)
+ }
+ return ret
+ }
var deps Paths
var info ModuleBuildTargetsInfo
- if len(ctx.installFiles) > 0 {
- name := namespacePrefix + ctx.ModuleName() + "-install"
+ if len(ctx.installFiles) > 0 && !shouldSkipAndroidMk {
installFiles := ctx.installFiles.Paths()
- ctx.Phony(name, installFiles...)
- info.InstallTarget = PathForPhony(ctx, name)
+ name := phony("-install", installFiles)
+ if name != "" {
+ info.InstallTarget = PathForPhony(ctx, name)
+ }
deps = append(deps, installFiles...)
}
@@ -1706,38 +1724,47 @@ func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) {
// not be created if the module is not exported to make.
// Those could depend on the build target and fail to compile
// for the current build target.
- if (!ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(ctx, m)) && !ctx.uncheckedModule && ctx.checkbuildTarget != nil {
- name := namespacePrefix + ctx.ModuleName() + "-checkbuild"
- ctx.Phony(name, ctx.checkbuildTarget)
- deps = append(deps, ctx.checkbuildTarget)
+ if !shouldSkipAndroidMk && !ctx.uncheckedModule {
+ phony("-checkbuild", ctx.checkbuildFiles)
+ checkbuildTarget := phony("-"+ctx.ModuleSubDir()+"-checkbuild", ctx.checkbuildFiles)
+ if checkbuildTarget != "" {
+ info.CheckbuildTarget = PathForPhony(ctx, checkbuildTarget)
+ }
+ deps = append(deps, ctx.checkbuildFiles...)
}
- if outputFiles, err := outputFilesForModule(ctx, ctx.Module(), ""); err == nil && len(outputFiles) > 0 {
- name := namespacePrefix + ctx.ModuleName() + "-outputs"
- ctx.Phony(name, outputFiles...)
+ if outputFiles, err := outputFilesForModule(ctx, ctx.Module(), ""); err == nil && len(outputFiles) > 0 && !shouldSkipAndroidMk {
+ phony("-outputs", outputFiles)
deps = append(deps, outputFiles...)
}
- if len(deps) > 0 {
- suffix := ""
- if ctx.Config().KatiEnabled() {
- suffix = "-soong"
+ // Act as if you built the required dependencies as well when building the current module
+ for _, dep := range ctx.GetDirectDepsProxyWithTag(RequiredDepTag) {
+ if info, ok := OtherModuleProvider(ctx, dep, ModuleBuildTargetsProvider); ok {
+ deps = append(deps, info.AllDeps...)
}
+ }
- ctx.Phony(namespacePrefix+ctx.ModuleName()+suffix, deps...)
+ for _, p := range testSuiteInstalls {
+ deps = append(deps, p.dst)
+ }
+
+ if len(deps) > 0 {
+ phony("", deps)
if ctx.Device() {
// Generate a target suffix for use in atest etc.
- ctx.Phony(namespacePrefix+ctx.ModuleName()+"-target"+suffix, deps...)
+ phony("-target", deps)
} else {
// Generate a host suffix for use in atest etc.
- ctx.Phony(namespacePrefix+ctx.ModuleName()+"-host"+suffix, deps...)
+ phony("-host", deps)
if ctx.Target().HostCross {
// Generate a host-cross suffix for use in atest etc.
- ctx.Phony(namespacePrefix+ctx.ModuleName()+"-host-cross"+suffix, deps...)
+ phony("-host-cross", deps)
}
}
info.BlueprintDir = ctx.ModuleDir()
+ info.AllDeps = deps
SetProvider(ctx, ModuleBuildTargetsProvider, info)
}
}
@@ -1830,24 +1857,37 @@ func (m *ModuleBase) archModuleContextFactory(ctx archModuleContextFactoryContex
} else {
primaryArch = target.Arch.ArchType == config.Targets[target.Os][0].Arch.ArchType
}
+ primaryNativeBridgeArch := false
+ if target.NativeBridge {
+ for _, t := range config.Targets[target.Os] {
+ if t.NativeBridge {
+ if target.Arch.ArchType == t.Arch.ArchType {
+ primaryNativeBridgeArch = true
+ }
+ // Don't consider further nativebridge targets
+ break
+ }
+ }
+ }
return archModuleContext{
- ready: m.commonProperties.ArchReady,
- os: m.commonProperties.CompileOS,
- target: m.commonProperties.CompileTarget,
- targetPrimary: m.commonProperties.CompilePrimary,
- multiTargets: m.commonProperties.CompileMultiTargets,
- primaryArch: primaryArch,
+ ready: m.commonProperties.ArchReady,
+ os: m.commonProperties.CompileOS,
+ target: m.commonProperties.CompileTarget,
+ targetPrimary: m.commonProperties.CompilePrimary,
+ multiTargets: m.commonProperties.CompileMultiTargets,
+ primaryArch: primaryArch,
+ primaryNativeBridgeArch: primaryNativeBridgeArch,
}
}
+// @auto-generate: gob
type InstallFilesInfo struct {
- InstallFiles InstallPaths
- CheckbuildFiles Paths
- CheckbuildTarget Path
- UncheckedModule bool
- PackagingSpecs []PackagingSpec
+ InstallFiles InstallPaths
+ CheckbuildFiles Paths
+ UncheckedModule bool
+ PackagingSpecs []PackagingSpec
// katiInstalls tracks the install rules that were created by Soong but are being exported
// to Make to convert to ninja rules so that Make can add additional dependencies.
KatiInstalls katiInstalls
@@ -1882,18 +1922,19 @@ var SourceFilesInfoProvider = blueprint.NewProvider[SourceFilesInfo]()
// ModuleBuildTargetsInfo is used by buildTargetSingleton to create checkbuild and
// per-directory build targets.
+// @auto-generate: gob
type ModuleBuildTargetsInfo struct {
InstallTarget WritablePath
CheckbuildTarget WritablePath
BlueprintDir string
+ AllDeps Paths
}
var ModuleBuildTargetsProvider = blueprint.NewProvider[ModuleBuildTargetsInfo]()
+// @auto-generate: gob
type CommonModuleInfo struct {
Enabled bool
- // Whether the module has been replaced by a prebuilt
- ReplacedByPrebuilt bool
// The Target of artifacts that this module variant is responsible for creating.
Target Target
SkipAndroidMkProcessing bool
@@ -1901,7 +1942,6 @@ type CommonModuleInfo struct {
CanHaveApexVariants bool
MinSdkVersion ApiLevelOrPlatform
SdkVersion string
- NotAvailableForPlatform bool
// There some subtle differences between this one and the one above.
NotInPlatform bool
// UninstallableApexPlatformVariant is set by MakeUninstallable called by the apex
@@ -1921,7 +1961,7 @@ type CommonModuleInfo struct {
Host bool
IsApexModule bool
// The primary licenses property, may be nil, records license metadata for the module.
- PrimaryLicensesProperty applicableLicensesProperty
+ PrimaryLicensesProperty *applicableLicensesProperty
Owner string
Vendor bool
Proprietary bool
@@ -1929,6 +1969,7 @@ type CommonModuleInfo struct {
ProductSpecific bool
SystemExtSpecific bool
DeviceSpecific bool
+ UseGenericConfig bool
// When set to true, this module is not installed to the full install path (ex: under
// out/target/product/<name>/<partition>). It can be installed only to the packaging
// modules like android_filesystem.
@@ -1943,8 +1984,14 @@ type CommonModuleInfo struct {
ExportedToMake bool
Team string
PartitionTag string
+ ApexAvailable []string
+ // This field is different from the above one as it can have different values
+ // for cc, java library and sdkLibraryXml.
+ ApexAvailableFor []string
+ ImageVariation blueprint.Variation
}
+// @auto-generate: gob
type ApiLevelOrPlatform struct {
ApiLevel *ApiLevel
IsPlatform bool
@@ -1952,13 +1999,7 @@ type ApiLevelOrPlatform struct {
var CommonModuleInfoProvider = blueprint.NewProvider[*CommonModuleInfo]()
-type PrebuiltModuleInfo struct {
- SourceExists bool
- UsePrebuilt bool
-}
-
-var PrebuiltModuleInfoProvider = blueprint.NewProvider[PrebuiltModuleInfo]()
-
+// @auto-generate: gob
type HostToolProviderInfo struct {
HostToolPath OptionalPath
}
@@ -1994,6 +2035,12 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
phonies: make(map[string]Paths),
}
+ blueprintCtx.RegisterConfigurableEvaluator(ctx)
+
+ if ctx.config.captureBuild {
+ ctx.config.modulesForTests.Insert(ctx.ModuleName(), ctx.Module())
+ }
+
setContainerInfo(ctx)
if ctx.Config().Getenv("DISABLE_CONTAINER_CHECK") != "true" {
checkContainerViolations(ctx)
@@ -2012,6 +2059,8 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
// TODO: This will be removed once defaults modules handle missing dependency errors
blueprintCtx.GetMissingDependencies()
+ checkVintfFragmentDeps(ctx)
+
// For the final GenerateAndroidBuildActions pass, require that all visited dependencies Soong modules and
// are enabled. Unless the module is a CommonOS variant which may have dependencies on disabled variants
// (because the dependencies are added before the modules are disabled). The
@@ -2064,7 +2113,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
// so only a single rule is created for each init.rc or vintf fragment file.
if !m.InVendorRamdisk() {
- ctx.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc.GetOrDefault(ctx, nil))
+ ctx.initRcPaths = PathsForModuleSrc(ctx, m.baseProperties.Init_rc.GetOrDefault(ctx, nil))
rcDir := PathForModuleInstall(ctx, "etc", "init")
for _, src := range ctx.initRcPaths {
installedInitRc := rcDir.Join(ctx, src.Base())
@@ -2080,7 +2129,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
installFiles.InstalledInitRcPaths = ctx.installedInitRcPaths
}
- ctx.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments.GetOrDefault(ctx, nil))
+ ctx.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.baseProperties.Vintf_fragments.GetOrDefault(ctx, nil))
vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest")
for _, src := range ctx.vintfFragmentsPaths {
installedVintfFragment := vintfDir.Join(ctx, src.Base())
@@ -2120,6 +2169,8 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
return
}
+ m.module.base().hooks.runPostGenerateAndroidBuildActionsHooks(ctx)
+
if x, ok := m.module.(IDEInfo); ok {
var result IdeInfo
x.IDEInfo(ctx, &result)
@@ -2136,17 +2187,18 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
return
}
- m.generateVariantTarget(ctx)
+ testData := FirstUniqueFunc(ctx.testData, func(a, b DataPath) bool {
+ return a == b
+ })
installFiles.LicenseMetadataFile = ctx.licenseMetadataFile
installFiles.InstallFiles = ctx.installFiles
installFiles.CheckbuildFiles = ctx.checkbuildFiles
- installFiles.CheckbuildTarget = ctx.checkbuildTarget
installFiles.UncheckedModule = ctx.uncheckedModule
installFiles.PackagingSpecs = ctx.packagingSpecs
installFiles.KatiInstalls = ctx.katiInstalls
installFiles.KatiSymlinks = ctx.katiSymlinks
- installFiles.TestData = ctx.testData
+ installFiles.TestData = testData
} else if ctx.Config().AllowMissingDependencies() {
// If the module is not enabled it will not create any build rules, nothing will call
// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled
@@ -2166,18 +2218,27 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
SetProvider(ctx, SourceFilesInfoProvider, SourceFilesInfo{Srcs: sourceFileProducer.Srcs()})
}
- m.generateModuleTarget(ctx)
- if ctx.Failed() {
- return
- }
-
ctx.TransitiveInstallFiles = depset.New[InstallPath](depset.TOPOLOGICAL, ctx.installFiles, dependencyInstallFiles)
installFiles.TransitiveInstallFiles = ctx.TransitiveInstallFiles
installFiles.TransitivePackagingSpecs = depset.New[PackagingSpec](depset.TOPOLOGICAL, ctx.packagingSpecs, dependencyPackagingSpecs)
- SetProvider(ctx, InstallFilesProvider, installFiles)
+ if m.Enabled(ctx) {
+ SetProvider(ctx, InstallFilesProvider, installFiles)
+ }
buildLicenseMetadata(ctx, ctx.licenseMetadataFile)
+ var testSuiteInstalls []filePair
+ if ctx.testSuiteInfoSet {
+ testSuiteInstalls = m.setupTestSuites(ctx, ctx.testSuiteInfo)
+ }
+
+ if m.Enabled(ctx) {
+ m.generateModuleTarget(ctx, testSuiteInstalls)
+ }
+ if ctx.Failed() {
+ return
+ }
+
if len(ctx.moduleInfoJSON) > 0 {
for _, moduleInfoJSON := range ctx.moduleInfoJSON {
if moduleInfoJSON.Disabled {
@@ -2257,7 +2318,9 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
}
}
- SetProvider(ctx, ModuleInfoJSONProvider, ctx.moduleInfoJSON)
+ SetProvider(ctx, ModuleInfoJSONProvider, ModuleInfoJSONInfo{
+ Data: ctx.moduleInfoJSON,
+ })
}
m.buildParams = ctx.buildParams
@@ -2285,7 +2348,6 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
commonData := CommonModuleInfo{
Enabled: m.Enabled(ctx),
- ReplacedByPrebuilt: m.commonProperties.ReplacedByPrebuilt,
Target: m.commonProperties.CompileTarget,
SkipAndroidMkProcessing: shouldSkipAndroidMkProcessing(ctx, m),
UninstallableApexPlatformVariant: m.commonProperties.UninstallableApexPlatformVariant,
@@ -2300,6 +2362,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
ProductSpecific: Bool(m.commonProperties.Product_specific),
SystemExtSpecific: Bool(m.commonProperties.System_ext_specific),
DeviceSpecific: Bool(m.commonProperties.Device_specific),
+ UseGenericConfig: m.module.UseGenericConfig(),
NoFullInstall: proptools.Bool(m.commonProperties.No_full_install),
InVendorRamdisk: m.InVendorRamdisk(),
ExemptFromRequiredApplicableLicensesProperty: exemptFromRequiredApplicableLicensesProperty(m.module),
@@ -2311,6 +2374,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
ExportedToMake: m.ExportedToMake(),
Team: m.Team(),
PartitionTag: m.PartitionTag(ctx.DeviceConfig()),
+ ImageVariation: m.module.ImageVariation(),
}
if mm, ok := m.module.(interface {
MinSdkVersion(ctx EarlyModuleContext) ApiLevel
@@ -2341,11 +2405,12 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
if am, ok := m.module.(ApexModule); ok {
commonData.CanHaveApexVariants = am.CanHaveApexVariants()
- commonData.NotAvailableForPlatform = am.NotAvailableForPlatform()
commonData.NotInPlatform = am.NotInPlatform()
commonData.MinSdkVersionSupported = am.MinSdkVersionSupported(ctx)
commonData.IsInstallableToApex = am.IsInstallableToApex()
commonData.IsApexModule = true
+ commonData.ApexAvailable = am.apexModuleBase().ApexAvailable()
+ commonData.ApexAvailableFor = am.ApexAvailableFor()
}
if _, ok := m.module.(ModuleWithMinSdkVersionCheck); ok {
@@ -2359,12 +2424,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
commonData.BaseModuleName = mm.BaseModuleName()
}
SetProvider(ctx, CommonModuleInfoProvider, &commonData)
- if p, ok := m.module.(PrebuiltInterface); ok && p.Prebuilt() != nil {
- SetProvider(ctx, PrebuiltModuleInfoProvider, PrebuiltModuleInfo{
- SourceExists: p.Prebuilt().SourceExists(),
- UsePrebuilt: p.Prebuilt().UsePrebuilt(),
- })
- }
+
if h, ok := m.module.(HostToolProvider); ok {
SetProvider(ctx, HostToolProviderInfoProvider, HostToolProviderInfo{
HostToolPath: h.HostToolPath()})
@@ -2393,6 +2453,185 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
})
}
}
+
+ if mm, ok := m.module.(RequiredFilesFromPrebuiltApex); ok {
+ SetProvider(ctx, RequiredFilesFromPrebuiltApexInfoProvider, RequiredFilesFromPrebuiltApexInfo{
+ RequiredFilesFromPrebuiltApex: mm.RequiredFilesFromPrebuiltApex(ctx),
+ UseProfileGuidedDexpreopt: mm.UseProfileGuidedDexpreopt(),
+ })
+ }
+
+ m.module.CleanupAfterBuildActions()
+}
+
+func (m *ModuleBase) CleanupAfterBuildActions() {}
+
+func (m *ModuleBase) setupTestSuites(ctx ModuleContext, info TestSuiteInfo) []filePair {
+ // We skip test suites when using the ndk or aml abis, as the extra archs (x86_64 + arm64)
+ // both try to install to the same test file. This could be fixed by always using a per-module
+ // folder and an arch folder, but as you see later in this function we only conditionally use
+ // those.
+ if ctx.Config().NdkAbis() || ctx.Config().AmlAbis() || shouldSkipAndroidMkProcessing(ctx, m) || m.IsSkipInstall() {
+ return nil
+ }
+ overriddenBy := ""
+ if b, ok := ctx.Module().(OverridableModule); ok {
+ overriddenBy = b.GetOverriddenBy()
+ }
+
+ // M(C)TS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}.
+ // To reduce repetition, if we find a partial M(C)TS test suite without an full M(C)TS test suite,
+ // we add the full test suite to our list.
+ if PrefixInList(info.TestSuites, "mts-") && !InList("mts", info.TestSuites) {
+ info.TestSuites = append(info.TestSuites, "mts")
+ }
+ if PrefixInList(info.TestSuites, "mcts-") && !InList("mcts", info.TestSuites) {
+ info.TestSuites = append(info.TestSuites, "mcts")
+ }
+
+ if len(info.TestSuites) == 0 {
+ info.TestSuites = []string{"null-suite"}
+ }
+ info.TestSuites = SortedUniqueStrings(info.TestSuites)
+
+ name := ctx.ModuleName()
+ if overriddenBy != "" {
+ name = overriddenBy
+ }
+ name += info.NameSuffix
+
+ type testSuiteInfo struct {
+ name string
+ dir WritablePath
+ includeModuleFolder bool
+ }
+
+ suites := []testSuiteInfo{{
+ dir: PathForModuleInPartitionInstall(ctx, "testcases", name),
+ includeModuleFolder: true,
+ }}
+ for _, suite := range info.TestSuites {
+ if suiteInfo, ok := ctx.Config().productVariables.CompatibilityTestcases[suite]; ok {
+ rel, err := filepath.Rel(ctx.Config().OutDir(), suiteInfo.OutDir)
+ if err != nil {
+ panic(fmt.Sprintf("Could not make COMPATIBILITY_TESTCASES_OUT_%s (%s) relative to the out dir (%s)", suite, suiteInfo.OutDir, ctx.Config().OutDir()))
+ }
+ if suiteInfo.IncludeModuleFolder || info.PerTestcaseDirectory {
+ rel = filepath.Join(rel, name)
+ }
+ suites = append(suites, testSuiteInfo{
+ name: suite,
+ dir: PathForArbitraryOutput(ctx, rel),
+ includeModuleFolder: suiteInfo.IncludeModuleFolder || info.PerTestcaseDirectory,
+ })
+ }
+ }
+
+ var archDir string
+ if info.NeedsArchFolder {
+ archDir = ctx.Arch().ArchType.Name
+ if archDir == "common" {
+ archDir = ctx.DeviceConfig().DeviceArch()
+ }
+ if ctx.Target().NativeBridge {
+ archDir = ctx.Target().NativeBridgeHostArchName
+ }
+ }
+
+ var installs []filePair
+ var oneVariantInstalls []filePair
+
+ for _, suite := range suites {
+ mainFileName := name
+ if info.MainFileStem != "" {
+ mainFileName = info.MainFileStem
+ }
+ mainFileName += info.MainFileExt
+ mainFileInstall := joinWriteablePath(ctx, suite.dir, archDir, mainFileName)
+ if !suite.includeModuleFolder {
+ mainFileInstall = joinWriteablePath(ctx, suite.dir, mainFileName)
+ }
+ if info.MainFile == nil {
+ panic("mainfile was nil")
+ }
+
+ installs = append(installs, filePair{
+ src: info.MainFile,
+ dst: mainFileInstall,
+ })
+
+ for _, data := range info.Data {
+ dataOut := joinWriteablePath(ctx, suite.dir, archDir, data.ToRelativeInstallPath())
+ if !suite.includeModuleFolder {
+ dataOut = joinWriteablePath(ctx, suite.dir, data.ToRelativeInstallPath())
+ }
+ installs = append(installs, filePair{
+ src: data.SrcPath,
+ dst: dataOut,
+ })
+ }
+ for _, data := range info.NonArchData {
+ dataOut := joinWriteablePath(ctx, suite.dir, data.ToRelativeInstallPath())
+ installs = append(installs, filePair{
+ src: data.SrcPath,
+ dst: dataOut,
+ })
+ }
+ for _, data := range info.CompatibilitySupportFiles {
+ dataOut := joinWriteablePath(ctx, suite.dir, data.Rel())
+ installs = append(installs, filePair{
+ src: data,
+ dst: dataOut,
+ })
+ }
+
+ if !info.DisableTestConfig {
+ if info.ConfigFile != nil {
+ oneVariantInstalls = append(oneVariantInstalls, filePair{
+ src: info.ConfigFile,
+ dst: joinWriteablePath(ctx, suite.dir, name+".config"+info.ConfigFileSuffix),
+ })
+ } else if config := ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml"); config.Valid() {
+ oneVariantInstalls = append(oneVariantInstalls, filePair{
+ src: config.Path(),
+ dst: joinWriteablePath(ctx, suite.dir, name+".config"),
+ })
+ }
+ }
+
+ dynamicConfig := ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+ if dynamicConfig.Valid() {
+ oneVariantInstalls = append(oneVariantInstalls, filePair{
+ src: dynamicConfig.Path(),
+ dst: joinWriteablePath(ctx, suite.dir, name+".dynamic"),
+ })
+ }
+ for _, extraTestConfig := range info.ExtraConfigs {
+ if extraTestConfig == nil {
+ panic("ExtraTestConfig was nil")
+ }
+ oneVariantInstalls = append(oneVariantInstalls, filePair{
+ src: extraTestConfig,
+ dst: joinWriteablePath(ctx, suite.dir, pathtools.ReplaceExtension(extraTestConfig.Base(), "config")),
+ })
+ }
+ }
+
+ SetProvider(ctx, TestSuiteInfoProvider, info)
+ SetProvider(ctx, testSuiteInstallsInfoProvider, testSuiteInstallsInfo{installs, oneVariantInstalls})
+
+ return slices.Concat(installs, oneVariantInstalls)
+}
+
+func joinWriteablePath(ctx PathContext, path WritablePath, toJoin ...string) WritablePath {
+ switch p := path.(type) {
+ case InstallPath:
+ return p.Join(ctx, toJoin...)
+ case OutputPath:
+ return p.Join(ctx, toJoin...)
+ default:
+ panic("unhandled path type")
+ }
}
func SetJarJarPrefixHandler(handler func(ModuleContext)) {
@@ -2465,6 +2704,7 @@ func checkDistProperties(ctx *moduleContext, property string, dist *Dist) {
}
// katiInstall stores a request from Soong to Make to create an install rule.
+// @auto-generate: gob
type katiInstall struct {
from Path
to InstallPath
@@ -2475,76 +2715,12 @@ type katiInstall struct {
absFrom string
}
-type katiInstallGob struct {
- From Path
- To InstallPath
- ImplicitDeps Paths
- OrderOnlyDeps Paths
- Executable bool
- ExtraFiles *extraFilesZip
- AbsFrom string
-}
-
-func (k *katiInstall) ToGob() *katiInstallGob {
- return &katiInstallGob{
- From: k.from,
- To: k.to,
- ImplicitDeps: k.implicitDeps,
- OrderOnlyDeps: k.orderOnlyDeps,
- Executable: k.executable,
- ExtraFiles: k.extraFiles,
- AbsFrom: k.absFrom,
- }
-}
-
-func (k *katiInstall) FromGob(data *katiInstallGob) {
- k.from = data.From
- k.to = data.To
- k.implicitDeps = data.ImplicitDeps
- k.orderOnlyDeps = data.OrderOnlyDeps
- k.executable = data.Executable
- k.extraFiles = data.ExtraFiles
- k.absFrom = data.AbsFrom
-}
-
-func (k *katiInstall) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[katiInstallGob](k)
-}
-
-func (k *katiInstall) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[katiInstallGob](data, k)
-}
-
+// @auto-generate: gob
type extraFilesZip struct {
zip Path
dir InstallPath
}
-type extraFilesZipGob struct {
- Zip Path
- Dir InstallPath
-}
-
-func (e *extraFilesZip) ToGob() *extraFilesZipGob {
- return &extraFilesZipGob{
- Zip: e.zip,
- Dir: e.dir,
- }
-}
-
-func (e *extraFilesZip) FromGob(data *extraFilesZipGob) {
- e.zip = data.Zip
- e.dir = data.Dir
-}
-
-func (e *extraFilesZip) GobEncode() ([]byte, error) {
- return gobtools.CustomGobEncode[extraFilesZipGob](e)
-}
-
-func (e *extraFilesZip) GobDecode(data []byte) error {
- return gobtools.CustomGobDecode[extraFilesZipGob](data, e)
-}
-
type katiInstalls []katiInstall
// BuiltInstalled returns the katiInstalls in the form used by $(call copy-many-files) in Make, a
@@ -2599,11 +2775,13 @@ func (m *ModuleBase) DecodeMultilib(ctx ConfigContext) (string, string) {
}
func (m *ModuleBase) Overrides() []string {
- return m.commonProperties.Overrides
+ return m.baseProperties.Overrides
}
func (m *ModuleBase) UseGenericConfig() bool {
- return proptools.Bool(m.commonProperties.Use_generic_config)
+ // Platform module installed in the device must use generic config by default
+ defaultUseGenericConfig := m.Platform() && !m.Host() && !m.InstallInRamdisk() && !m.InstallInVendorRamdisk() && !m.InstallInRecovery()
+ return proptools.BoolDefault(m.commonProperties.Use_generic_config, defaultUseGenericConfig)
}
type ConfigContext interface {
@@ -2613,7 +2791,7 @@ type ConfigContext interface {
type ConfigurableEvaluatorContext interface {
OtherModuleProviderContext
Config() Config
- OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{})
+ OtherModulePropertyErrorf(module ModuleOrProxy, property string, fmt string, args ...interface{})
HasMutatorFinished(mutatorName string) bool
}
@@ -2783,6 +2961,16 @@ func ModuleNameWithPossibleOverride(ctx BaseModuleContext) string {
return ctx.ModuleName()
}
+// OtherModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the
+// current variant of the given module, or ctx.ModuleName() if the given module is not an
+// OverridableModule or if this variant is not overridden.
+func OtherModuleNameWithPossibleOverride(ctx BaseModuleContext, m ModuleOrProxy) string {
+ if overrideInfo, ok := OtherModuleProvider(ctx, m, OverrideInfoProvider); ok && overrideInfo.OverriddenBy != "" {
+ return overrideInfo.OverriddenBy
+ }
+ return ctx.OtherModuleName(m)
+}
+
// SrcIsModule decodes module references in the format ":unqualified-name" or "//namespace:name"
// into the module name, or empty string if the input was not a module reference.
func SrcIsModule(s string) (module string) {
@@ -2911,7 +3099,7 @@ type SourceFileProducer interface {
// OutputFilesForModule returns the output file paths with the given tag. On error, including if the
// module produced zero paths, it reports errors to the ctx and returns nil.
-func OutputFilesForModule(ctx PathContext, module Module, tag string) Paths {
+func OutputFilesForModule(ctx PathContext, module ModuleOrProxy, tag string) Paths {
paths, err := outputFilesForModule(ctx, module, tag)
if err != nil {
reportPathError(ctx, err)
@@ -2924,7 +3112,7 @@ func OutputFilesForModule(ctx PathContext, module Module, tag string) Paths {
// module produced zero or multiple paths, it reports errors to the ctx and returns nil.
// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
-func OutputFileForModule(ctx PathContext, module Module, tag string) Path {
+func OutputFileForModule(ctx PathContext, module ModuleOrProxy, tag string) Path {
paths, err := outputFilesForModule(ctx, module, tag)
if err != nil {
reportPathError(ctx, err)
@@ -2933,7 +3121,7 @@ func OutputFileForModule(ctx PathContext, module Module, tag string) Path {
if len(paths) == 0 {
type addMissingDependenciesIntf interface {
AddMissingDependencies([]string)
- OtherModuleName(blueprint.Module) string
+ OtherModuleName(ModuleOrProxy) string
}
if mctx, ok := ctx.(addMissingDependenciesIntf); ok && ctx.Config().AllowMissingDependencies() {
mctx.AddMissingDependencies([]string{mctx.OtherModuleName(module)})
@@ -2957,6 +3145,12 @@ func OutputFileForModule(ctx PathContext, module Module, tag string) Path {
return paths[0]
}
+// OutputFilesForModuleOrErr is the same as OutputFilesForModule except that it returns the
+// error instead of reporting it to the context
+func OutputFilesForModuleOrErr(ctx PathContext, module ModuleOrProxy, tag string) (Paths, error) {
+ return outputFilesForModule(ctx, module, tag)
+}
+
type OutputFilesProviderModuleContext interface {
OtherModuleProviderContext
Module() Module
@@ -2965,7 +3159,7 @@ type OutputFilesProviderModuleContext interface {
// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
-func outputFilesForModule(ctx PathContext, module Module, tag string) (Paths, error) {
+func outputFilesForModule(ctx PathContext, module ModuleOrProxy, tag string) (Paths, error) {
outputFilesFromProvider, err := outputFilesForModuleFromProvider(ctx, module, tag)
if outputFilesFromProvider != nil || err != OutputFilesProviderNotSet {
return outputFilesFromProvider, err
@@ -2995,7 +3189,7 @@ func outputFilesForModule(ctx PathContext, module Module, tag string) (Paths, er
// from outputFiles property of module base, to avoid both setting and
// reading OutputFilesProvider before GenerateBuildActions is finished.
// If a module doesn't have the OutputFilesProvider, nil is returned.
-func outputFilesForModuleFromProvider(ctx PathContext, module Module, tag string) (Paths, error) {
+func outputFilesForModuleFromProvider(ctx PathContext, module ModuleOrProxy, tag string) (Paths, error) {
var outputFiles OutputFilesInfo
if mctx, isMctx := ctx.(OutputFilesProviderModuleContext); isMctx {
@@ -3029,6 +3223,7 @@ func (o OutputFilesInfo) isEmpty() bool {
return o.DefaultOutputFiles == nil && o.TaggedOutputFiles == nil
}
+// @auto-generate: gob
type OutputFilesInfo struct {
// default output files when tag is an empty string ""
DefaultOutputFiles Paths
@@ -3163,9 +3358,10 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
hostCross bool
}
osDeps := map[osAndCross]Paths{}
- ctx.VisitAllModules(func(module Module) {
- if module.Enabled(ctx) {
- key := osAndCross{os: module.Target().Os, hostCross: module.Target().HostCross}
+ ctx.VisitAllModuleProxies(func(module ModuleProxy) {
+ info := OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoProvider)
+ if info.Enabled {
+ key := osAndCross{os: info.Target.Os, hostCross: info.Target.HostCross}
osDeps[key] = append(osDeps[key], OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider).CheckbuildFiles...)
}
})
@@ -3219,6 +3415,8 @@ type IdeInfo struct {
Paths []string `json:"path,omitempty"`
Static_libs []string `json:"static_libs,omitempty"`
Libs []string `json:"libs,omitempty"`
+ Asset_dirs []string `json:"asset_dirs,omitempty"`
+ Resource_dirs []string `json:"resource_dirs,omitempty"`
}
// Merge merges two IdeInfos and produces a new one, leaving the origional unchanged
@@ -3235,6 +3433,8 @@ func (i IdeInfo) Merge(other IdeInfo) IdeInfo {
Paths: mergeStringLists(i.Paths, other.Paths),
Static_libs: mergeStringLists(i.Static_libs, other.Static_libs),
Libs: mergeStringLists(i.Libs, other.Libs),
+ Asset_dirs: mergeStringLists(i.Asset_dirs, other.Asset_dirs),
+ Resource_dirs: mergeStringLists(i.Resource_dirs, other.Resource_dirs),
}
}
@@ -3250,3 +3450,9 @@ func CheckBlueprintSyntax(ctx BaseModuleContext, filename string, contents strin
bpctx := ctx.blueprintBaseModuleContext()
return blueprint.CheckBlueprintSyntax(bpctx.ModuleFactories(), filename, contents)
}
+
+type HideApexVariantFromMakeInfo struct {
+ HideApexVariantFromMake bool
+}
+
+var HideApexVariantFromMakeProvider = blueprint.NewProvider[HideApexVariantFromMakeInfo]()