summaryrefslogtreecommitdiff
path: root/android/module.go
diff options
context:
space:
mode:
Diffstat (limited to 'android/module.go')
-rw-r--r--android/module.go1305
1 files changed, 1069 insertions, 236 deletions
diff --git a/android/module.go b/android/module.go
index 880915377..ce7fd0ca0 100644
--- a/android/module.go
+++ b/android/module.go
@@ -15,10 +15,12 @@
package android
import (
+ "android/soong/bazel"
"fmt"
"os"
"path"
"path/filepath"
+ "regexp"
"strings"
"text/scanner"
@@ -42,6 +44,8 @@ type BuildParams struct {
Description string
Output WritablePath
Outputs WritablePaths
+ SymlinkOutput WritablePath
+ SymlinkOutputs WritablePaths
ImplicitOutput WritablePath
ImplicitOutputs WritablePaths
Input Path
@@ -49,6 +53,8 @@ type BuildParams struct {
Implicit Path
Implicits Paths
OrderOnly Paths
+ Validation Path
+ Validations Paths
Default bool
Args map[string]string
}
@@ -58,18 +64,44 @@ type ModuleBuildParams BuildParams
// EarlyModuleContext provides methods that can be called early, as soon as the properties have
// been parsed into the module and before any mutators have run.
type EarlyModuleContext interface {
+ // Module returns the current module as a Module. It should rarely be necessary, as the module already has a
+ // reference to itself.
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.
ModuleName() string
+
+ // ModuleDir returns the path to the directory that contains the definition of the module.
ModuleDir() string
+
+ // ModuleType returns the name of the module type that was used to create the module, as specified in
+ // RegisterModuleType.
ModuleType() string
+
+ // BlueprintFile returns the name of the blueprint file that contains the definition of this
+ // module.
BlueprintsFile() string
+ // ContainsProperty returns true if the specified property name was set in the module definition.
ContainsProperty(name string) bool
+
+ // Errorf reports an error at the specified position of the module definition file.
Errorf(pos scanner.Position, fmt string, args ...interface{})
+
+ // ModuleErrorf reports an error at the line number of the module type in the module definition.
ModuleErrorf(fmt string, args ...interface{})
+
+ // PropertyErrorf reports an error at the line number of a property in the module definition.
PropertyErrorf(property, fmt string, args ...interface{})
+
+ // Failed returns true if any errors have been reported. In most cases the module can continue with generating
+ // build rules after an error, allowing it to report additional errors in a single run, but in cases where the error
+ // has prevented the module from creating necessary data it can return early when Failed returns true.
Failed() bool
+ // AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest. The
+ // primary builder will be rerun whenever the specified files are modified.
AddNinjaFileDeps(deps ...string)
DeviceSpecific() bool
@@ -94,6 +126,10 @@ type EarlyModuleContext interface {
GlobFiles(globPattern string, excludes []string) Paths
IsSymlink(path Path) bool
Readlink(path Path) string
+
+ // Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the
+ // default SimpleNameInterface if Context.SetNameInterface was not called.
+ Namespace() *Namespace
}
// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
@@ -103,31 +139,165 @@ type EarlyModuleContext interface {
type BaseModuleContext interface {
EarlyModuleContext
+ blueprintBaseModuleContext() blueprint.BaseModuleContext
+
+ // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
+ // It is intended for use inside the visit functions of Visit* and WalkDeps.
OtherModuleName(m blueprint.Module) string
+
+ // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information.
+ // It is intended for use inside the visit functions of Visit* and WalkDeps.
OtherModuleDir(m blueprint.Module) string
+
+ // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information.
+ // It is intended for use inside the visit functions of Visit* and WalkDeps.
OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
+
+ // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
+ // on the module. When called inside a Visit* method with current module being visited, and there are multiple
+ // dependencies on the module being visited, it returns the dependency tag used for the current dependency.
OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
+
+ // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
+ // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
OtherModuleExists(name string) bool
+
+ // OtherModuleDependencyVariantExists returns true if a module with the
+ // specified name and variant exists. The variant must match the given
+ // variations. It must also match all the non-local variations of the current
+ // module. In other words, it checks for the module that AddVariationDependencies
+ // would add a dependency on with the same arguments.
+ OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
+
+ // OtherModuleFarDependencyVariantExists returns true if a module with the
+ // specified name and variant exists. The variant must match the given
+ // variations, but not the non-local variations of the current module. In
+ // other words, it checks for the module that AddFarVariationDependencies
+ // would add a dependency on with the same arguments.
+ OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
+
+ // OtherModuleReverseDependencyVariantExists returns true if a module with the
+ // specified name exists with the same variations as the current module. In
+ // other words, it checks for the module that AddReverseDependency would add a
+ // dependency on with the same argument.
+ OtherModuleReverseDependencyVariantExists(name string) bool
+
+ // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
+ // It is intended for use inside the visit functions of Visit* and WalkDeps.
OtherModuleType(m blueprint.Module) string
+ // OtherModuleProvider returns the value for a provider for the given module. If the value is
+ // not set it returns the zero value of the type of the provider, so the return value can always
+ // be type asserted to the type of the provider. The value returned may be a deep copy of the
+ // value originally passed to SetProvider.
+ OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{}
+
+ // OtherModuleHasProvider returns true if the provider for the given module has been set.
+ OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool
+
+ // Provider returns the value for a provider for the current module. If the value is
+ // not set it returns the zero value of the type of the provider, so the return value can always
+ // be type asserted to the type of the provider. It panics if called before the appropriate
+ // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep
+ // copy of the value originally passed to SetProvider.
+ Provider(provider blueprint.ProviderKey) interface{}
+
+ // HasProvider returns true if the provider for the current module has been set.
+ HasProvider(provider blueprint.ProviderKey) bool
+
+ // SetProvider sets the value for a provider for the current module. It panics if not called
+ // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
+ // is not of the appropriate type, or if the value has already been set. The value should not
+ // be modified after being passed to SetProvider.
+ SetProvider(provider blueprint.ProviderKey, value interface{})
+
GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
+
+ // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
+ // none exists. It panics if the dependency does not have the specified tag. It skips any
+ // dependencies that are not an android.Module.
GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
+
+ // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
+ // name, or nil if none exists. If there are multiple dependencies on the same module it returns
+ // the first DependencyTag.
GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
+ // VisitDirectDepsBlueprint calls visit for each direct dependency. If there are multiple
+ // direct dependencies on the same module visit will be called multiple times on that module
+ // and OtherModuleDependencyTag will return a different tag for each.
+ //
+ // The Module passed to the visit function should not be retained outside of the visit
+ // function, it may be invalidated by future mutators.
VisitDirectDepsBlueprint(visit func(blueprint.Module))
+
+ // VisitDirectDeps calls visit for each direct dependency. If there are multiple
+ // direct dependencies on the same module visit will be called multiple times on that module
+ // and OtherModuleDependencyTag will return a different tag for each. It skips any
+ // dependencies that are not an android.Module.
+ //
+ // The Module passed to the visit function should not be retained outside of the visit
+ // function, it may be invalidated by future mutators.
VisitDirectDeps(visit func(Module))
+
VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
+
+ // 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
+ // dependencies that are not an android.Module.
+ //
+ // The Module passed to the visit function should not be retained outside of the visit function, it may be
+ // invalidated by future mutators.
VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
VisitDepsDepthFirst(visit func(Module))
// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
+
+ // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
+ // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
+ // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
+ // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
+ // any dependencies that are not an android.Module.
+ //
+ // The Modules passed to the visit function should not be retained outside of the visit function, they may be
+ // invalidated by future mutators.
WalkDeps(visit func(Module, Module) bool)
+
+ // WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency
+ // tree in top down order. visit may be called multiple times for the same (child, parent)
+ // pair if there are multiple direct dependencies between the child and parent with different
+ // tags. OtherModuleDependencyTag will return the tag for the currently visited
+ // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down
+ // to child.
+ //
+ // The Modules passed to the visit function should not be retained outside of the visit function, they may be
+ // invalidated by future mutators.
WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool)
+
// GetWalkPath is supposed to be called in visit function passed in WalkDeps()
// and returns a top-down dependency path from a start module to current child module.
GetWalkPath() []Module
+ // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in
+ // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
+ // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
+ // only done once for all variants of a module.
+ PrimaryModule() Module
+
+ // FinalModule returns the last variant of the current module. Variants of a module are always visited in
+ // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
+ // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
+ // singleton actions that are only done once for all variants of a module.
+ FinalModule() Module
+
+ // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
+ // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
+ // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any
+ // data modified by the current mutator.
+ VisitAllModuleVariants(visit func(Module))
+
// GetTagPath is supposed to be called in visit function passed in WalkDeps()
// and returns a top-down dependency tags path from a start module to current child module.
// It has one less entry than GetWalkPath() as it contains the dependency tags that
@@ -135,6 +305,13 @@ type BaseModuleContext interface {
// GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
GetTagPath() []blueprint.DependencyTag
+ // GetPathString is supposed to be called in visit function passed in WalkDeps()
+ // and returns a multi-line string showing the modules and dependency tags
+ // among them along the top-down dependency path from a start module to current child module.
+ // skipFirst when set to true, the output doesn't include the start module,
+ // which is already printed when this function is used along with ModuleErrorf().
+ GetPathString(skipFirst bool) string
+
AddMissingDependencies(missingDeps []string)
Target() Target
@@ -162,6 +339,8 @@ type BaseContext interface {
type ModuleContext interface {
BaseModuleContext
+ blueprintModuleContext() blueprint.ModuleContext
+
// Deprecated: use ModuleContext.Build instead.
ModuleBuild(pctx PackageContext, params ModuleBuildParams)
@@ -169,19 +348,63 @@ type ModuleContext interface {
ExpandSource(srcFile, prop string) Path
ExpandOptionalSource(srcFile *string, prop string) OptionalPath
+ // InstallExecutable creates a rule to copy srcPath to name in the installPath directory,
+ // with the given additional dependencies. The file is marked executable after copying.
+ //
+ // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
+ // installed file will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
InstallExecutable(installPath InstallPath, name string, srcPath Path, deps ...Path) InstallPath
+
+ // InstallFile creates a rule to copy srcPath to name in the installPath directory,
+ // with the given additional dependencies.
+ //
+ // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
+ // installed file will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
InstallFile(installPath InstallPath, name string, srcPath Path, deps ...Path) InstallPath
+
+ // InstallSymlink creates a rule to create a symlink from src srcPath to name in the installPath
+ // directory.
+ //
+ // The installed symlink will be returned by FilesToInstall(), and the PackagingSpec for the
+ // installed file will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath
+
+ // InstallAbsoluteSymlink creates a rule to create an absolute symlink from src srcPath to name
+ // in the installPath directory.
+ //
+ // The installed symlink will be returned by FilesToInstall(), and the PackagingSpec for the
+ // installed file will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath
+
+ // PackageFile creates a PackagingSpec as if InstallFile was called, but without creating
+ // the rule to copy the file. This is useful to define how a module would be packaged
+ // without installing it into the global installation directories.
+ //
+ // The created PackagingSpec for the will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
+ PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec
+
CheckbuildFile(srcPath Path)
InstallInData() bool
InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRamdisk() bool
+ InstallInVendorRamdisk() bool
+ InstallInDebugRamdisk() bool
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
+ InstallForceOS() (*OsType, *ArchType)
RequiredModuleNames() []string
HostRequiredModuleNames() []string
@@ -199,12 +422,9 @@ type ModuleContext interface {
// additional dependencies.
Phony(phony string, deps ...Path)
- PrimaryModule() Module
- FinalModule() Module
- VisitAllModuleVariants(visit func(Module))
-
+ // GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
+ // but do not exist.
GetMissingDependencies() []string
- Namespace() blueprint.Namespace
}
type Module interface {
@@ -215,28 +435,45 @@ type Module interface {
// For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go
GenerateAndroidBuildActions(ModuleContext)
+ // 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.
+ //
+ // This is called before prebuilts are renamed so as to allow a dependency to be
+ // added directly to a prebuilt child module instead of depending on a source module
+ // and relying on prebuilt processing to switch to the prebuilt module if preferred.
+ //
+ // A dependency on a prebuilt must include the "prebuilt_" prefix.
+ ComponentDepsMutator(ctx BottomUpMutatorContext)
+
DepsMutator(BottomUpMutatorContext)
base() *ModuleBase
Disable()
Enabled() bool
Target() Target
+ MultiTargets() []Target
Owner() string
InstallInData() bool
InstallInTestcases() bool
InstallInSanitizerDir() bool
InstallInRamdisk() bool
+ InstallInVendorRamdisk() bool
+ InstallInDebugRamdisk() bool
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
- SkipInstall()
+ InstallForceOS() (*OsType, *ArchType)
+ HideFromMake()
+ IsHideFromMake() bool
IsSkipInstall() bool
+ MakeUninstallable()
ReplacedByPrebuilt()
IsReplacedByPrebuilt() bool
ExportedToMake() bool
InitRc() Paths
VintfFragments() Paths
- NoticeFile() OptionalPath
+ NoticeFiles() Paths
+ EffectiveLicenseFiles() Paths
AddProperties(props ...interface{})
GetProperties() []interface{}
@@ -257,6 +494,69 @@ type Module interface {
RequiredModuleNames() []string
HostRequiredModuleNames() []string
TargetRequiredModuleNames() []string
+
+ FilesToInstall() InstallPaths
+ PackagingSpecs() []PackagingSpec
+
+ // TransitivePackagingSpecs returns the PackagingSpecs for this module and any transitive
+ // dependencies with dependency tags for which IsInstallDepNeeded() returns true.
+ TransitivePackagingSpecs() []PackagingSpec
+}
+
+// BazelTargetModule is a lightweight wrapper interface around Module for
+// bp2build conversion purposes.
+//
+// In bp2build's bootstrap.Main execution, Soong runs an alternate pipeline of
+// mutators that creates BazelTargetModules from regular Module objects,
+// performing the mapping from Soong properties to Bazel rule attributes in the
+// process. This process may optionally create additional BazelTargetModules,
+// resulting in a 1:many mapping.
+//
+// bp2build.Codegen is then responsible for visiting all modules in the graph,
+// filtering for BazelTargetModules, and code-generating BUILD targets from
+// them.
+type BazelTargetModule interface {
+ Module
+
+ bazelTargetModuleProperties() *bazel.BazelTargetModuleProperties
+ SetBazelTargetModuleProperties(props bazel.BazelTargetModuleProperties)
+
+ RuleClass() string
+ BzlLoadLocation() string
+}
+
+// InitBazelTargetModule is a wrapper function that decorates BazelTargetModule
+// with property structs containing metadata for bp2build conversion.
+func InitBazelTargetModule(module BazelTargetModule) {
+ module.AddProperties(module.bazelTargetModuleProperties())
+ InitAndroidModule(module)
+}
+
+// BazelTargetModuleBase contains the property structs with metadata for
+// bp2build conversion.
+type BazelTargetModuleBase struct {
+ ModuleBase
+ Properties bazel.BazelTargetModuleProperties
+}
+
+// bazelTargetModuleProperties getter.
+func (btmb *BazelTargetModuleBase) bazelTargetModuleProperties() *bazel.BazelTargetModuleProperties {
+ return &btmb.Properties
+}
+
+// SetBazelTargetModuleProperties setter for BazelTargetModuleProperties
+func (btmb *BazelTargetModuleBase) SetBazelTargetModuleProperties(props bazel.BazelTargetModuleProperties) {
+ btmb.Properties = props
+}
+
+// RuleClass returns the rule class for this Bazel target
+func (b *BazelTargetModuleBase) RuleClass() string {
+ return b.bazelTargetModuleProperties().Rule_class
+}
+
+// BzlLoadLocation returns the rule class for this Bazel target
+func (b *BazelTargetModuleBase) BzlLoadLocation() string {
+ return b.bazelTargetModuleProperties().Bzl_load_location
}
// Qualified id for a module
@@ -302,6 +602,32 @@ func newPackageId(pkg string) qualifiedModuleName {
return qualifiedModuleName{pkg: pkg, name: ""}
}
+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
+ // built
+ Targets []string `android:"arch_variant"`
+
+ // The name of the output artifact. This defaults to the basename of the output of
+ // the module.
+ Dest *string `android:"arch_variant"`
+
+ // The directory within the dist directory to store the artifact. Defaults to the
+ // top level directory ("").
+ Dir *string `android:"arch_variant"`
+
+ // A suffix to add to the artifact file name (before any extension).
+ Suffix *string `android:"arch_variant"`
+
+ // A string tag to select the OutputFiles associated with the tag.
+ //
+ // If no tag is specified then it will select the default dist paths provided
+ // by the module type. If a tag of "" is specified then it will return the
+ // default output files provided by the modules, i.e. the result of calling
+ // OutputFiles("").
+ Tag *string `android:"arch_variant"`
+}
+
type nameProperties struct {
// The name of the module. Must be unique across all modules.
Name *string
@@ -362,13 +688,24 @@ type commonProperties struct {
// more details.
Visibility []string
- // Names of the licenses that apply to this module.
+ // Describes the licenses applicable to this module. Must reference license modules.
Licenses []string
+ // Flattened from direct license dependencies. Equal to Licenses unless particular module adds more.
+ Effective_licenses []string `blueprint:"mutated"`
+ // Override of module name when reporting licenses
+ Effective_package_name *string `blueprint:"mutated"`
+ // Notice files
+ Effective_license_text Paths `blueprint:"mutated"`
+ // License names
+ Effective_license_kinds []string `blueprint:"mutated"`
+ // License conditions
+ Effective_license_conditions []string `blueprint:"mutated"`
+
// control whether this module compiles for 32-bit, 64-bit, or both. Possible values
// are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
// architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
- // platform
+ // platform).
Compile_multilib *string `android:"arch_variant"`
Target struct {
@@ -423,11 +760,17 @@ type commonProperties struct {
// Whether this module is installed to ramdisk
Ramdisk *bool
- // Whether this module is built for non-native architecures (also known as native bridge binary)
+ // Whether this module is installed to vendor ramdisk
+ Vendor_ramdisk *bool
+
+ // Whether this module is installed to debug ramdisk
+ Debug_ramdisk *bool
+
+ // 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 []string `android:"path"`
+ Init_rc []string `android:"arch_variant,path"`
// VINTF manifest fragments to be installed if this module is installed
Vintf_fragments []string `android:"path"`
@@ -444,24 +787,6 @@ type commonProperties struct {
// relative path to a file to include in the list of notices for the device
Notice *string `android:"path"`
- 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
- // built
- Targets []string `android:"arch_variant"`
-
- // The name of the output artifact. This defaults to the basename of the output of
- // the module.
- Dest *string `android:"arch_variant"`
-
- // The directory within the dist directory to store the artifact. Defaults to the
- // top level directory ("").
- Dir *string `android:"arch_variant"`
-
- // A suffix to add to the artifact file name (before any extension).
- Suffix *string `android:"arch_variant"`
- } `android:"arch_variant"`
-
// The OsType of artifacts that this module variant is responsible for creating.
//
// Set by osMutator
@@ -512,6 +837,13 @@ type commonProperties struct {
// Set by osMutator.
CommonOSVariant bool `blueprint:"mutated"`
+ // When HideFromMake is set to true, no entry for this variant will be emitted in the
+ // generated Android.mk file.
+ HideFromMake bool `blueprint:"mutated"`
+
+ // When SkipInstall is set to true, calls to ctx.InstallFile, ctx.InstallExecutable,
+ // ctx.InstallSymlink and ctx.InstallAbsoluteSymlink act like calls to ctx.PackageFile
+ // and don't create a rule to install the file.
SkipInstall bool `blueprint:"mutated"`
// Whether the module has been replaced by a prebuilt
@@ -529,10 +861,72 @@ type commonProperties struct {
DebugMutators []string `blueprint:"mutated"`
DebugVariations []string `blueprint:"mutated"`
- // set by ImageMutator
+ // ImageVariation is set by ImageMutator to specify which image this variation is for,
+ // for example "" for core or "recovery" for recovery. It will often be set to one of the
+ // constants in image.go, but can also be set to a custom value by individual module types.
ImageVariation string `blueprint:"mutated"`
}
+type distProperties struct {
+ // configuration to distribute output files from this module to the distribution
+ // directory (default: $OUT/dist, configurable with $DIST_DIR)
+ Dist Dist `android:"arch_variant"`
+
+ // a list of configurations to distribute output files from this module to the
+ // distribution directory (default: $OUT/dist, configurable with $DIST_DIR)
+ Dists []Dist `android:"arch_variant"`
+}
+
+// The key to use in TaggedDistFiles when a Dist structure does not specify a
+// tag property. This intentionally does not use "" as the default because that
+// would mean that an empty tag would have a different meaning when used in a dist
+// structure that when used to reference a specific set of output paths using the
+// :module{tag} syntax, which passes tag to the OutputFiles(tag) method.
+const DefaultDistTag = "<default-dist-tag>"
+
+// A map of OutputFile tag keys to Paths, for disting purposes.
+type TaggedDistFiles map[string]Paths
+
+// addPathsForTag adds a mapping from the tag to the paths. If the map is nil
+// then it will create a map, update it and then return it. If a mapping already
+// exists for the tag then the paths are appended to the end of the current list
+// of paths, ignoring any duplicates.
+func (t TaggedDistFiles) addPathsForTag(tag string, paths ...Path) TaggedDistFiles {
+ if t == nil {
+ t = make(TaggedDistFiles)
+ }
+
+ for _, distFile := range paths {
+ if distFile != nil && !t[tag].containsPath(distFile) {
+ t[tag] = append(t[tag], distFile)
+ }
+ }
+
+ return t
+}
+
+// merge merges the entries from the other TaggedDistFiles object into this one.
+// If the TaggedDistFiles is nil then it will create a new instance, merge the
+// other into it, and then return it.
+func (t TaggedDistFiles) merge(other TaggedDistFiles) TaggedDistFiles {
+ for tag, paths := range other {
+ t = t.addPathsForTag(tag, paths...)
+ }
+
+ return t
+}
+
+func MakeDefaultDistFiles(paths ...Path) TaggedDistFiles {
+ for _, path := range paths {
+ if path == nil {
+ panic("The path to a dist file cannot be nil.")
+ }
+ }
+
+ // The default OutputFile tag is the empty "" string.
+ return TaggedDistFiles{DefaultDistTag: paths}
+}
+
type hostAndDeviceProperties struct {
// If set to true, build a variant of the module for the host. Defaults to false.
Host_supported *bool
@@ -554,27 +948,32 @@ const (
type HostOrDeviceSupported int
const (
- _ HostOrDeviceSupported = iota
+ hostSupported = 1 << iota
+ hostCrossSupported
+ deviceSupported
+ hostDefault
+ deviceDefault
// Host and HostCross are built by default. Device is not supported.
- HostSupported
+ HostSupported = hostSupported | hostCrossSupported | hostDefault
// Host is built by default. HostCross and Device are not supported.
- HostSupportedNoCross
+ HostSupportedNoCross = hostSupported | hostDefault
// Device is built by default. Host and HostCross are not supported.
- DeviceSupported
+ DeviceSupported = deviceSupported | deviceDefault
// Device is built by default. Host and HostCross are supported.
- HostAndDeviceSupported
+ HostAndDeviceSupported = hostSupported | hostCrossSupported | deviceSupported | deviceDefault
// Host, HostCross, and Device are built by default.
- HostAndDeviceDefault
+ HostAndDeviceDefault = hostSupported | hostCrossSupported | hostDefault |
+ deviceSupported | deviceDefault
// Nothing is supported. This is not exposed to the user, but used to mark a
// host only module as unsupported when the module type is not supported on
// the host OS. E.g. benchmarks are supported on Linux but not Darwin.
- NeitherHostNorDeviceSupported
+ NeitherHostNorDeviceSupported = 0
)
type moduleKind int
@@ -608,13 +1007,16 @@ func initAndroidModuleBase(m Module) {
m.base().module = m
}
+// InitAndroidModule initializes the Module as an Android module that is not architecture-specific.
+// It adds the common properties, for example "name" and "enabled".
func InitAndroidModule(m Module) {
initAndroidModuleBase(m)
base := m.base()
m.AddProperties(
&base.nameProperties,
- &base.commonProperties)
+ &base.commonProperties,
+ &base.distProperties)
initProductVariableModule(m)
@@ -624,8 +1026,18 @@ func InitAndroidModule(m Module) {
// The default_visibility property needs to be checked and parsed by the visibility module during
// its checking and parsing phases so make it the primary visibility property.
setPrimaryVisibilityProperty(m, "visibility", &base.commonProperties.Visibility)
+
+ // The default_applicable_licenses property needs to be checked and parsed by the licenses module during
+ // its checking and parsing phases so make it the primary licenses property.
+ setPrimaryLicensesProperty(m, "licenses", &base.commonProperties.Licenses)
}
+// InitAndroidArchModule initializes the Module as an Android module that is architecture-specific.
+// It adds the common properties, for example "name" and "enabled", as well as runtime generated
+// property structs for architecture-specific versions of generic properties tagged with
+// `android:"arch_variant"`.
+//
+// InitAndroidModule should not be called if InitAndroidArchModule was called.
func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
InitAndroidModule(m)
@@ -635,21 +1047,37 @@ func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib
base.commonProperties.ArchSpecific = true
base.commonProperties.UseTargetVariants = true
- switch hod {
- case HostAndDeviceSupported, HostAndDeviceDefault:
+ if hod&hostSupported != 0 && hod&deviceSupported != 0 {
m.AddProperties(&base.hostAndDeviceProperties)
}
- InitArchModule(m)
+ initArchModule(m)
}
+// InitAndroidMultiTargetsArchModule initializes the Module as an Android module that is
+// architecture-specific, but will only have a single variant per OS that handles all the
+// architectures simultaneously. The list of Targets that it must handle will be available from
+// ModuleContext.MultiTargets. It adds the common properties, for example "name" and "enabled", as
+// well as runtime generated property structs for architecture-specific versions of generic
+// properties tagged with `android:"arch_variant"`.
+//
+// InitAndroidModule or InitAndroidArchModule should not be called if
+// InitAndroidMultiTargetsArchModule was called.
func InitAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
InitAndroidArchModule(m, hod, defaultMultilib)
m.base().commonProperties.UseTargetVariants = false
}
-// As InitAndroidMultiTargetsArchModule except it creates an additional CommonOS variant that
-// has dependencies on all the OsType specific variants.
+// InitCommonOSAndroidMultiTargetsArchModule initializes the Module as an Android module that is
+// architecture-specific, but will only have a single variant per OS that handles all the
+// architectures simultaneously, and will also have an additional CommonOS variant that has
+// dependencies on all the OS-specific variants. The list of Targets that it must handle will be
+// available from ModuleContext.MultiTargets. It adds the common properties, for example "name" and
+// "enabled", as well as runtime generated property structs for architecture-specific versions of
+// generic properties tagged with `android:"arch_variant"`.
+//
+// InitAndroidModule, InitAndroidArchModule or InitAndroidMultiTargetsArchModule should not be
+// called if InitCommonOSAndroidMultiTargetsArchModule was called.
func InitCommonOSAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
InitAndroidArchModule(m, hod, defaultMultilib)
m.base().commonProperties.UseTargetVariants = false
@@ -705,11 +1133,22 @@ type ModuleBase struct {
nameProperties nameProperties
commonProperties commonProperties
+ distProperties distProperties
variableProperties interface{}
hostAndDeviceProperties hostAndDeviceProperties
generalProperties []interface{}
- archProperties [][]interface{}
- customizableProperties []interface{}
+
+ // Arch specific versions of structs in generalProperties. The outer index
+ // has the same order as generalProperties as initialized in
+ // InitAndroidArchModule, and the inner index chooses the props specific to
+ // the architecture. The interface{} value is an archPropRoot that is
+ // filled with arch specific values by the arch mutator.
+ archProperties [][]interface{}
+
+ customizableProperties []interface{}
+
+ // Properties specific to the Blueprint to BUILD migration.
+ bazelTargetModuleProperties bazel.BazelTargetModuleProperties
// Information about all the properties on the module that contains visibility rules that need
// checking.
@@ -718,11 +1157,20 @@ type ModuleBase struct {
// The primary visibility property, may be nil, that controls access to the module.
primaryVisibilityProperty visibilityProperty
- noAddressSanitizer bool
- installFiles Paths
- checkbuildFiles Paths
- noticeFile OptionalPath
- phonies map[string]Paths
+ // The primary licenses property, may be nil, records license metadata for the module.
+ primaryLicensesProperty applicableLicensesProperty
+
+ noAddressSanitizer bool
+ installFiles InstallPaths
+ installFilesDepSet *installPathsDepSet
+ checkbuildFiles Paths
+ packagingSpecs []PackagingSpec
+ packagingSpecsDepSet *packagingSpecsDepSet
+ noticeFiles Paths
+ phonies map[string]Paths
+
+ // The files to copy to the dist as explicitly specified in the .bp file.
+ distFiles TaggedDistFiles
// Used by buildTargetSingleton to create checkbuild and per-directory build targets
// Only set on the final variant of each module
@@ -741,10 +1189,10 @@ type ModuleBase struct {
initRcPaths Paths
vintfFragmentsPaths Paths
-
- prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool
}
+func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {}
+
func (m *ModuleBase) DepsMutator(BottomUpMutatorContext) {}
func (m *ModuleBase) AddProperties(props ...interface{}) {
@@ -767,10 +1215,6 @@ func (m *ModuleBase) VariablesForTests() map[string]string {
return m.variables
}
-func (m *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool) {
- m.prefer32 = prefer32
-}
-
// Name returns the name of the module. It may be overridden by individual module types, for
// example prebuilts will prepend prebuilt_ to the name.
func (m *ModuleBase) Name() string {
@@ -811,6 +1255,48 @@ func (m *ModuleBase) visibilityProperties() []visibilityProperty {
return m.visibilityPropertyInfo
}
+func (m *ModuleBase) Dists() []Dist {
+ if len(m.distProperties.Dist.Targets) > 0 {
+ // Make a copy of the underlying Dists slice to protect against
+ // backing array modifications with repeated calls to this method.
+ distsCopy := append([]Dist(nil), m.distProperties.Dists...)
+ return append(distsCopy, m.distProperties.Dist)
+ } else {
+ return m.distProperties.Dists
+ }
+}
+
+func (m *ModuleBase) GenerateTaggedDistFiles(ctx BaseModuleContext) TaggedDistFiles {
+ var distFiles TaggedDistFiles
+ for _, dist := range m.Dists() {
+ // If no tag is specified then it means to use the default dist paths so use
+ // the special tag name which represents that.
+ tag := proptools.StringDefault(dist.Tag, DefaultDistTag)
+
+ if outputFileProducer, ok := m.module.(OutputFileProducer); ok {
+ // Call the OutputFiles(tag) method to get the paths associated with the tag.
+ distFilesForTag, err := outputFileProducer.OutputFiles(tag)
+
+ // If the tag was not supported and is not DefaultDistTag then it is an error.
+ // Failing to find paths for DefaultDistTag is not an error. It just means
+ // that the module type requires the legacy behavior.
+ if err != nil && tag != DefaultDistTag {
+ ctx.PropertyErrorf("dist.tag", "%s", err.Error())
+ }
+
+ distFiles = distFiles.addPathsForTag(tag, distFilesForTag...)
+ } else if tag != DefaultDistTag {
+ // If the tag was specified then it is an error if the module does not
+ // implement OutputFileProducer because there is no other way of accessing
+ // the paths for the specified tag.
+ ctx.PropertyErrorf("dist.tag",
+ "tag %s not supported because the module does not implement OutputFileProducer", tag)
+ }
+ }
+
+ return distFiles
+}
+
func (m *ModuleBase) Target() Target {
return m.commonProperties.CompileTarget
}
@@ -828,7 +1314,7 @@ func (m *ModuleBase) Os() OsType {
}
func (m *ModuleBase) Host() bool {
- return m.Os().Class == Host || m.Os().Class == HostCross
+ return m.Os().Class == Host
}
func (m *ModuleBase) Device() bool {
@@ -848,43 +1334,54 @@ func (m *ModuleBase) IsCommonOSVariant() bool {
return m.commonProperties.CommonOSVariant
}
-func (m *ModuleBase) OsClassSupported() []OsClass {
- switch m.commonProperties.HostOrDeviceSupported {
- case HostSupported:
- return []OsClass{Host, HostCross}
- case HostSupportedNoCross:
- return []OsClass{Host}
- case DeviceSupported:
- return []OsClass{Device}
- case HostAndDeviceSupported, HostAndDeviceDefault:
- var supported []OsClass
- if Bool(m.hostAndDeviceProperties.Host_supported) ||
- (m.commonProperties.HostOrDeviceSupported == HostAndDeviceDefault &&
- m.hostAndDeviceProperties.Host_supported == nil) {
- supported = append(supported, Host, HostCross)
- }
- if m.hostAndDeviceProperties.Device_supported == nil ||
- *m.hostAndDeviceProperties.Device_supported {
- supported = append(supported, Device)
+// supportsTarget returns true if the given Target is supported by the current module.
+func (m *ModuleBase) supportsTarget(target Target) bool {
+ switch target.Os.Class {
+ case Host:
+ if target.HostCross {
+ return m.HostCrossSupported()
+ } else {
+ return m.HostSupported()
}
- return supported
+ case Device:
+ return m.DeviceSupported()
default:
- return nil
+ return false
}
}
+// DeviceSupported returns true if the current module is supported and enabled for device targets,
+// i.e. the factory method set the HostOrDeviceSupported value to include device support and
+// the device support is enabled by default or enabled by the device_supported property.
func (m *ModuleBase) DeviceSupported() bool {
- return m.commonProperties.HostOrDeviceSupported == DeviceSupported ||
- m.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
- (m.hostAndDeviceProperties.Device_supported == nil ||
- *m.hostAndDeviceProperties.Device_supported)
+ hod := m.commonProperties.HostOrDeviceSupported
+ // deviceEnabled is true if the device_supported property is true or the HostOrDeviceSupported
+ // value has the deviceDefault bit set.
+ deviceEnabled := proptools.BoolDefault(m.hostAndDeviceProperties.Device_supported, hod&deviceDefault != 0)
+ return hod&deviceSupported != 0 && deviceEnabled
}
+// HostSupported returns true if the current module is supported and enabled for host targets,
+// i.e. the factory method set the HostOrDeviceSupported value to include host support and
+// the host support is enabled by default or enabled by the host_supported property.
func (m *ModuleBase) HostSupported() bool {
- return m.commonProperties.HostOrDeviceSupported == HostSupported ||
- m.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
- (m.hostAndDeviceProperties.Host_supported != nil &&
- *m.hostAndDeviceProperties.Host_supported)
+ hod := m.commonProperties.HostOrDeviceSupported
+ // hostEnabled is true if the host_supported property is true or the HostOrDeviceSupported
+ // value has the hostDefault bit set.
+ hostEnabled := proptools.BoolDefault(m.hostAndDeviceProperties.Host_supported, hod&hostDefault != 0)
+ return hod&hostSupported != 0 && hostEnabled
+}
+
+// HostCrossSupported returns true if the current module is supported and enabled for host cross
+// targets, i.e. the factory method set the HostOrDeviceSupported value to include host cross
+// support and the host cross support is enabled by default or enabled by the
+// host_supported property.
+func (m *ModuleBase) HostCrossSupported() bool {
+ hod := m.commonProperties.HostOrDeviceSupported
+ // hostEnabled is true if the host_supported property is true or the HostOrDeviceSupported
+ // value has the hostDefault bit set.
+ hostEnabled := proptools.BoolDefault(m.hostAndDeviceProperties.Host_supported, hod&hostDefault != 0)
+ return hod&hostCrossSupported != 0 && hostEnabled
}
func (m *ModuleBase) Platform() bool {
@@ -962,17 +1459,39 @@ func (m *ModuleBase) Disable() {
m.commonProperties.ForcedDisabled = true
}
+// HideFromMake marks this variant so that it is not emitted in the generated Android.mk file.
+func (m *ModuleBase) HideFromMake() {
+ m.commonProperties.HideFromMake = true
+}
+
+// IsHideFromMake returns true if HideFromMake was previously called.
+func (m *ModuleBase) IsHideFromMake() bool {
+ return m.commonProperties.HideFromMake == true
+}
+
+// SkipInstall marks this variant to not create install rules when ctx.Install* are called.
func (m *ModuleBase) SkipInstall() {
m.commonProperties.SkipInstall = true
}
+// IsSkipInstall returns true if this variant is marked to not create install
+// rules when ctx.Install* are called.
func (m *ModuleBase) IsSkipInstall() bool {
- return m.commonProperties.SkipInstall == true
+ return m.commonProperties.SkipInstall
+}
+
+// Similar to HideFromMake, but if the AndroidMk entry would set
+// LOCAL_UNINSTALLABLE_MODULE then this variant may still output that entry
+// rather than leaving it out altogether. That happens in cases where it would
+// have other side effects, in particular when it adds a NOTICE file target,
+// which other install targets might depend on.
+func (m *ModuleBase) MakeUninstallable() {
+ m.HideFromMake()
}
func (m *ModuleBase) ReplacedByPrebuilt() {
m.commonProperties.ReplacedByPrebuilt = true
- m.SkipInstall()
+ m.HideFromMake()
}
func (m *ModuleBase) IsReplacedByPrebuilt() bool {
@@ -983,25 +1502,37 @@ func (m *ModuleBase) ExportedToMake() bool {
return m.commonProperties.NamespaceExportedToMake
}
-func (m *ModuleBase) computeInstallDeps(
- ctx blueprint.ModuleContext) Paths {
+func (m *ModuleBase) EffectiveLicenseFiles() Paths {
+ return m.commonProperties.Effective_license_text
+}
- result := Paths{}
- // TODO(ccross): we need to use WalkDeps and have some way to know which dependencies require installation
- ctx.VisitDepsDepthFirstIf(isFileInstaller,
- func(m blueprint.Module) {
- fileInstaller := m.(fileInstaller)
- files := fileInstaller.filesToInstall()
- result = append(result, files...)
- })
+// computeInstallDeps finds the installed paths of all dependencies that have a dependency
+// tag that is annotated as needing installation via the IsInstallDepNeeded method.
+func (m *ModuleBase) computeInstallDeps(ctx ModuleContext) ([]*installPathsDepSet, []*packagingSpecsDepSet) {
+ var installDeps []*installPathsDepSet
+ var packagingSpecs []*packagingSpecsDepSet
+ ctx.VisitDirectDeps(func(dep Module) {
+ if IsInstallDepNeeded(ctx.OtherModuleDependencyTag(dep)) && !dep.IsHideFromMake() {
+ installDeps = append(installDeps, dep.base().installFilesDepSet)
+ packagingSpecs = append(packagingSpecs, dep.base().packagingSpecsDepSet)
+ }
+ })
- return result
+ return installDeps, packagingSpecs
}
-func (m *ModuleBase) filesToInstall() Paths {
+func (m *ModuleBase) FilesToInstall() InstallPaths {
return m.installFiles
}
+func (m *ModuleBase) PackagingSpecs() []PackagingSpec {
+ return m.packagingSpecs
+}
+
+func (m *ModuleBase) TransitivePackagingSpecs() []PackagingSpec {
+ return m.packagingSpecsDepSet.ToList()
+}
+
func (m *ModuleBase) NoAddressSanitizer() bool {
return m.noAddressSanitizer
}
@@ -1022,6 +1553,14 @@ func (m *ModuleBase) InstallInRamdisk() bool {
return Bool(m.commonProperties.Ramdisk)
}
+func (m *ModuleBase) InstallInVendorRamdisk() bool {
+ return Bool(m.commonProperties.Vendor_ramdisk)
+}
+
+func (m *ModuleBase) InstallInDebugRamdisk() bool {
+ return Bool(m.commonProperties.Debug_ramdisk)
+}
+
func (m *ModuleBase) InstallInRecovery() bool {
return Bool(m.commonProperties.Recovery)
}
@@ -1034,12 +1573,16 @@ func (m *ModuleBase) InstallBypassMake() bool {
return false
}
+func (m *ModuleBase) InstallForceOS() (*OsType, *ArchType) {
+ return nil, nil
+}
+
func (m *ModuleBase) Owner() string {
return String(m.commonProperties.Owner)
}
-func (m *ModuleBase) NoticeFile() OptionalPath {
- return m.noticeFile
+func (m *ModuleBase) NoticeFiles() Paths {
+ return m.noticeFiles
}
func (m *ModuleBase) setImageVariation(variant string) {
@@ -1067,6 +1610,14 @@ func (m *ModuleBase) InRamdisk() bool {
return m.base().commonProperties.ImageVariation == RamdiskVariation
}
+func (m *ModuleBase) InVendorRamdisk() bool {
+ return m.base().commonProperties.ImageVariation == VendorRamdiskVariation
+}
+
+func (m *ModuleBase) InDebugRamdisk() bool {
+ return m.base().commonProperties.ImageVariation == DebugRamdiskVariation
+}
+
func (m *ModuleBase) InRecovery() bool {
return m.base().commonProperties.ImageVariation == RecoveryVariation
}
@@ -1092,8 +1643,8 @@ func (m *ModuleBase) VintfFragments() Paths {
}
func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
- allInstalledFiles := Paths{}
- allCheckbuildFiles := Paths{}
+ var allInstalledFiles InstallPaths
+ var allCheckbuildFiles Paths
ctx.VisitAllModuleVariants(func(module Module) {
a := module.base()
allInstalledFiles = append(allInstalledFiles, a.installFiles...)
@@ -1102,14 +1653,14 @@ func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
var deps Paths
- namespacePrefix := ctx.Namespace().(*Namespace).id
+ namespacePrefix := ctx.Namespace().id
if namespacePrefix != "" {
namespacePrefix = namespacePrefix + "-"
}
if len(allInstalledFiles) > 0 {
name := namespacePrefix + ctx.ModuleName() + "-install"
- ctx.Phony(name, allInstalledFiles...)
+ ctx.Phony(name, allInstalledFiles.Paths()...)
m.installTarget = PathForPhony(ctx, name)
deps = append(deps, m.installTarget)
}
@@ -1123,7 +1674,7 @@ func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
if len(deps) > 0 {
suffix := ""
- if ctx.Config().EmbeddedInMake() {
+ if ctx.Config().KatiEnabled() {
suffix = "-soong"
}
@@ -1216,11 +1767,15 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
module: m.module,
bp: blueprintCtx,
baseModuleContext: m.baseModuleContextFactory(blueprintCtx),
- installDeps: m.computeInstallDeps(blueprintCtx),
- installFiles: m.installFiles,
variables: make(map[string]string),
}
+ dependencyInstallFiles, dependencyPackagingSpecs := m.computeInstallDeps(ctx)
+ // set m.installFilesDepSet to only the transitive dependencies to be used as the dependencies
+ // of installed files of this module. It will be replaced by a depset including the installed
+ // files of this module at the end for use by modules that depend on this one.
+ m.installFilesDepSet = newInstallPathsDepSet(nil, dependencyInstallFiles)
+
// Temporarily continue to call blueprintCtx.GetMissingDependencies() to maintain the previous behavior of never
// reporting missing dependency errors in Blueprint when AllowMissingDependencies == true.
// TODO: This will be removed once defaults modules handle missing dependency errors
@@ -1245,8 +1800,8 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
if !ctx.PrimaryArch() {
suffix = append(suffix, ctx.Arch().ArchType.String())
}
- if apex, ok := m.module.(ApexModule); ok && !apex.IsForPlatform() {
- suffix = append(suffix, apex.ApexName())
+ if apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo); !apexInfo.IsForPlatform() {
+ suffix = append(suffix, apexInfo.ApexVariationName)
}
ctx.Variable(pctx, "moduleDesc", desc)
@@ -1258,38 +1813,43 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
ctx.Variable(pctx, "moduleDescSuffix", s)
// Some common property checks for properties that will be used later in androidmk.go
- if m.commonProperties.Dist.Dest != nil {
- _, err := validateSafePath(*m.commonProperties.Dist.Dest)
- if err != nil {
- ctx.PropertyErrorf("dist.dest", "%s", err.Error())
- }
- }
- if m.commonProperties.Dist.Dir != nil {
- _, err := validateSafePath(*m.commonProperties.Dist.Dir)
- if err != nil {
- ctx.PropertyErrorf("dist.dir", "%s", err.Error())
- }
- }
- if m.commonProperties.Dist.Suffix != nil {
- if strings.Contains(*m.commonProperties.Dist.Suffix, "/") {
- ctx.PropertyErrorf("dist.suffix", "Suffix may not contain a '/' character.")
- }
+ checkDistProperties(ctx, "dist", &m.distProperties.Dist)
+ for i, _ := range m.distProperties.Dists {
+ checkDistProperties(ctx, fmt.Sprintf("dists[%d]", i), &m.distProperties.Dists[i])
}
if m.Enabled() {
// ensure all direct android.Module deps are enabled
ctx.VisitDirectDepsBlueprint(func(bm blueprint.Module) {
- if _, ok := bm.(Module); ok {
- ctx.validateAndroidModule(bm, ctx.baseModuleContext.strictVisitDeps)
+ if m, ok := bm.(Module); ok {
+ ctx.validateAndroidModule(bm, ctx.OtherModuleDependencyTag(m), ctx.baseModuleContext.strictVisitDeps)
}
})
- notice := proptools.StringDefault(m.commonProperties.Notice, "NOTICE")
+ m.noticeFiles = make([]Path, 0)
+ optPath := OptionalPath{}
+ notice := proptools.StringDefault(m.commonProperties.Notice, "")
if module := SrcIsModule(notice); module != "" {
- m.noticeFile = ctx.ExpandOptionalSource(&notice, "notice")
- } else {
+ optPath = ctx.ExpandOptionalSource(&notice, "notice")
+ } else if notice != "" {
noticePath := filepath.Join(ctx.ModuleDir(), notice)
- m.noticeFile = ExistentPathForSource(ctx, noticePath)
+ optPath = ExistentPathForSource(ctx, noticePath)
+ }
+ if optPath.Valid() {
+ m.noticeFiles = append(m.noticeFiles, optPath.Path())
+ } else {
+ for _, notice = range []string{"LICENSE", "LICENCE", "NOTICE"} {
+ noticePath := filepath.Join(ctx.ModuleDir(), notice)
+ optPath = ExistentPathForSource(ctx, noticePath)
+ if optPath.Valid() {
+ m.noticeFiles = append(m.noticeFiles, optPath.Path())
+ }
+ }
+ }
+
+ licensesPropertyFlattener(ctx)
+ if ctx.Failed() {
+ return
}
m.module.GenerateAndroidBuildActions(ctx)
@@ -1297,10 +1857,30 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
return
}
- m.installFiles = append(m.installFiles, ctx.installFiles...)
- m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
+ rcDir := PathForModuleInstall(ctx, "etc", "init")
+ for _, src := range m.initRcPaths {
+ ctx.PackageFile(rcDir, filepath.Base(src.String()), src)
+ }
+
m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
+ vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest")
+ for _, src := range m.vintfFragmentsPaths {
+ ctx.PackageFile(vintfDir, filepath.Base(src.String()), src)
+ }
+
+ // Create the set of tagged dist files after calling GenerateAndroidBuildActions
+ // as GenerateTaggedDistFiles() calls OutputFiles(tag) and so relies on the
+ // output paths being set which must be done before or during
+ // GenerateAndroidBuildActions.
+ m.distFiles = m.GenerateTaggedDistFiles(ctx)
+ if ctx.Failed() {
+ return
+ }
+
+ m.installFiles = append(m.installFiles, ctx.installFiles...)
+ m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
+ m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...)
for k, v := range ctx.phonies {
m.phonies[k] = append(m.phonies[k], v...)
}
@@ -1319,11 +1899,40 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
}
}
+ m.installFilesDepSet = newInstallPathsDepSet(m.installFiles, dependencyInstallFiles)
+ m.packagingSpecsDepSet = newPackagingSpecsDepSet(m.packagingSpecs, dependencyPackagingSpecs)
+
m.buildParams = ctx.buildParams
m.ruleParams = ctx.ruleParams
m.variables = ctx.variables
}
+// Check the supplied dist structure to make sure that it is valid.
+//
+// property - the base property, e.g. dist or dists[1], which is combined with the
+// name of the nested property to produce the full property, e.g. dist.dest or
+// dists[1].dir.
+func checkDistProperties(ctx *moduleContext, property string, dist *Dist) {
+ if dist.Dest != nil {
+ _, err := validateSafePath(*dist.Dest)
+ if err != nil {
+ ctx.PropertyErrorf(property+".dest", "%s", err.Error())
+ }
+ }
+ if dist.Dir != nil {
+ _, err := validateSafePath(*dist.Dir)
+ if err != nil {
+ ctx.PropertyErrorf(property+".dir", "%s", err.Error())
+ }
+ }
+ if dist.Suffix != nil {
+ if strings.Contains(*dist.Suffix, "/") {
+ ctx.PropertyErrorf(property+".suffix", "Suffix may not contain a '/' character.")
+ }
+ }
+
+}
+
type earlyModuleContext struct {
blueprint.EarlyModuleContext
@@ -1332,19 +1941,11 @@ type earlyModuleContext struct {
}
func (e *earlyModuleContext) Glob(globPattern string, excludes []string) Paths {
- ret, err := e.GlobWithDeps(globPattern, excludes)
- if err != nil {
- e.ModuleErrorf("glob: %s", err.Error())
- }
- return pathsForModuleSrcFromFullPath(e, ret, true)
+ return Glob(e, globPattern, excludes)
}
func (e *earlyModuleContext) GlobFiles(globPattern string, excludes []string) Paths {
- ret, err := e.GlobWithDeps(globPattern, excludes)
- if err != nil {
- e.ModuleErrorf("glob: %s", err.Error())
- }
- return pathsForModuleSrcFromFullPath(e, ret, false)
+ return GlobFiles(e, globPattern, excludes)
}
func (b *earlyModuleContext) IsSymlink(path Path) bool {
@@ -1400,6 +2001,10 @@ func (e *earlyModuleContext) SystemExtSpecific() bool {
return e.kind == systemExtSpecificModule
}
+func (e *earlyModuleContext) Namespace() *Namespace {
+ return e.EarlyModuleContext.Namespace().(*Namespace)
+}
+
type baseModuleContext struct {
bp blueprint.BaseModuleContext
earlyModuleContext
@@ -1426,19 +2031,47 @@ func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) bluepri
return b.bp.OtherModuleDependencyTag(m)
}
func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
+func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
+ return b.bp.OtherModuleDependencyVariantExists(variations, name)
+}
+func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
+ return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
+}
+func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
+ return b.bp.OtherModuleReverseDependencyVariantExists(name)
+}
func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
return b.bp.OtherModuleType(m)
}
+func (b *baseModuleContext) OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{} {
+ return b.bp.OtherModuleProvider(m, provider)
+}
+func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool {
+ return b.bp.OtherModuleHasProvider(m, provider)
+}
+func (b *baseModuleContext) Provider(provider blueprint.ProviderKey) interface{} {
+ return b.bp.Provider(provider)
+}
+func (b *baseModuleContext) HasProvider(provider blueprint.ProviderKey) bool {
+ return b.bp.HasProvider(provider)
+}
+func (b *baseModuleContext) SetProvider(provider blueprint.ProviderKey, value interface{}) {
+ b.bp.SetProvider(provider, value)
+}
func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
return b.bp.GetDirectDepWithTag(name, tag)
}
+func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
+ return b.bp
+}
+
type moduleContext struct {
bp blueprint.ModuleContext
baseModuleContext
- installDeps Paths
- installFiles Paths
+ packagingSpecs []PackagingSpec
+ installFiles InstallPaths
checkbuildFiles Paths
module Module
phonies map[string]Paths
@@ -1467,6 +2100,27 @@ func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParam
m.Build(pctx, BuildParams(params))
}
+func validateBuildParams(params blueprint.BuildParams) error {
+ // Validate that the symlink outputs are declared outputs or implicit outputs
+ allOutputs := map[string]bool{}
+ for _, output := range params.Outputs {
+ allOutputs[output] = true
+ }
+ for _, output := range params.ImplicitOutputs {
+ allOutputs[output] = true
+ }
+ for _, symlinkOutput := range params.SymlinkOutputs {
+ if !allOutputs[symlinkOutput] {
+ return fmt.Errorf(
+ "Symlink output %s is not a declared output or implicit output",
+ symlinkOutput)
+ }
+ }
+ return nil
+}
+
+// Convert build parameters from their concrete Android types into their string representations,
+// and combine the singular and plural fields of the same type (e.g. Output and Outputs).
func convertBuildParams(params BuildParams) blueprint.BuildParams {
bparams := blueprint.BuildParams{
Rule: params.Rule,
@@ -1474,9 +2128,11 @@ func convertBuildParams(params BuildParams) blueprint.BuildParams {
Deps: params.Deps,
Outputs: params.Outputs.Strings(),
ImplicitOutputs: params.ImplicitOutputs.Strings(),
+ SymlinkOutputs: params.SymlinkOutputs.Strings(),
Inputs: params.Inputs.Strings(),
Implicits: params.Implicits.Strings(),
OrderOnly: params.OrderOnly.Strings(),
+ Validations: params.Validations.Strings(),
Args: params.Args,
Optional: !params.Default,
}
@@ -1487,6 +2143,9 @@ func convertBuildParams(params BuildParams) blueprint.BuildParams {
if params.Output != nil {
bparams.Outputs = append(bparams.Outputs, params.Output.String())
}
+ if params.SymlinkOutput != nil {
+ bparams.SymlinkOutputs = append(bparams.SymlinkOutputs, params.SymlinkOutput.String())
+ }
if params.ImplicitOutput != nil {
bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
}
@@ -1496,13 +2155,18 @@ func convertBuildParams(params BuildParams) blueprint.BuildParams {
if params.Implicit != nil {
bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
}
+ if params.Validation != nil {
+ bparams.Validations = append(bparams.Validations, params.Validation.String())
+ }
bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs)
bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs)
+ bparams.SymlinkOutputs = proptools.NinjaEscapeList(bparams.SymlinkOutputs)
bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs)
bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits)
bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly)
- bparams.Depfile = proptools.NinjaEscapeList([]string{bparams.Depfile})[0]
+ bparams.Validations = proptools.NinjaEscapeList(bparams.Validations)
+ bparams.Depfile = proptools.NinjaEscape(bparams.Depfile)
return bparams
}
@@ -1554,7 +2218,15 @@ func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
m.buildParams = append(m.buildParams, params)
}
- m.bp.Build(pctx.PackageContext, convertBuildParams(params))
+ bparams := convertBuildParams(params)
+ err := validateBuildParams(bparams)
+ if err != nil {
+ m.ModuleErrorf(
+ "%s: build parameter validation failed: %s",
+ m.ModuleName(),
+ err.Error())
+ }
+ m.bp.Build(pctx.PackageContext, bparams)
}
func (m *moduleContext) Phony(name string, deps ...Path) {
@@ -1577,7 +2249,12 @@ func (b *baseModuleContext) AddMissingDependencies(deps []string) {
}
}
-func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, strict bool) Module {
+type AllowDisabledModuleDependency interface {
+ blueprint.DependencyTag
+ AllowDisabledModuleDependency(target Module) bool
+}
+
+func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
aModule, _ := module.(Module)
if !strict {
@@ -1590,30 +2267,45 @@ func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, stric
}
if !aModule.Enabled() {
- if b.Config().AllowMissingDependencies() {
- b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
- } else {
- b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
+ if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(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
}
-func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
- type dep struct {
- mod blueprint.Module
- tag blueprint.DependencyTag
- }
+type dep struct {
+ mod blueprint.Module
+ tag blueprint.DependencyTag
+}
+
+func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
var deps []dep
b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
- if aModule, _ := module.(Module); aModule != nil && aModule.base().BaseModuleName() == name {
- returnedTag := b.bp.OtherModuleDependencyTag(aModule)
+ if aModule, _ := module.(Module); aModule != nil {
+ if aModule.base().BaseModuleName() == name {
+ returnedTag := b.bp.OtherModuleDependencyTag(aModule)
+ if tag == nil || returnedTag == tag {
+ deps = append(deps, dep{aModule, returnedTag})
+ }
+ }
+ } else if b.bp.OtherModuleName(module) == name {
+ returnedTag := b.bp.OtherModuleDependencyTag(module)
if tag == nil || returnedTag == tag {
- deps = append(deps, dep{aModule, returnedTag})
+ deps = append(deps, dep{module, returnedTag})
}
}
})
+ return deps
+}
+
+func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
+ deps := b.getDirectDepsInternal(name, tag)
if len(deps) == 1 {
return deps[0].mod, deps[0].tag
} else if len(deps) >= 2 {
@@ -1624,6 +2316,25 @@ func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.Depe
}
}
+func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) {
+ foundDeps := b.getDirectDepsInternal(name, nil)
+ deps := map[blueprint.Module]bool{}
+ for _, dep := range foundDeps {
+ deps[dep.mod] = true
+ }
+ if len(deps) == 1 {
+ return foundDeps[0].mod, foundDeps[0].tag
+ } else if len(deps) >= 2 {
+ // this could happen if two dependencies have the same name in different namespaces
+ // TODO(b/186554727): this should not occur if namespaces are handled within
+ // getDirectDepsInternal.
+ panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
+ name, b.ModuleName()))
+ } else {
+ return nil, nil
+ }
+}
+
func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
var deps []Module
b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
@@ -1641,8 +2352,11 @@ func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.Dependenc
return module
}
+// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
+// name, or nil if none exists. If there are multiple dependencies on the same module it returns the
+// first DependencyTag.
func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
- return b.getDirectDepInternal(name, nil)
+ return b.getDirectDepFirstTag(name)
}
func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
@@ -1651,7 +2365,7 @@ func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module
func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
b.bp.VisitDirectDeps(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
visit(aModule)
}
})
@@ -1659,7 +2373,7 @@ func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
b.bp.VisitDirectDeps(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
if b.bp.OtherModuleDependencyTag(aModule) == tag {
visit(aModule)
}
@@ -1671,7 +2385,7 @@ func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func
b.bp.VisitDirectDepsIf(
// pred
func(module blueprint.Module) bool {
- if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
return pred(aModule)
} else {
return false
@@ -1685,7 +2399,7 @@ func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func
func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
visit(aModule)
}
})
@@ -1695,7 +2409,7 @@ func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit
b.bp.VisitDepsDepthFirstIf(
// pred
func(module blueprint.Module) bool {
- if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
return pred(aModule)
} else {
return false
@@ -1740,18 +2454,63 @@ func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
return b.tagPath
}
-func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) {
- m.bp.VisitAllModuleVariants(func(module blueprint.Module) {
+func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
+ b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
visit(module.(Module))
})
}
-func (m *moduleContext) PrimaryModule() Module {
- return m.bp.PrimaryModule().(Module)
+func (b *baseModuleContext) PrimaryModule() Module {
+ return b.bp.PrimaryModule().(Module)
+}
+
+func (b *baseModuleContext) FinalModule() Module {
+ return b.bp.FinalModule().(Module)
+}
+
+// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
+func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
+ if tag == licenseKindTag {
+ return true
+ } else if tag == licensesTag {
+ return true
+ }
+ return false
}
-func (m *moduleContext) FinalModule() Module {
- return m.bp.FinalModule().(Module)
+// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
+// a dependency tag.
+var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
+
+// PrettyPrintTag returns string representation of the tag, but prefers
+// custom String() method if available.
+func PrettyPrintTag(tag blueprint.DependencyTag) string {
+ // Use tag's custom String() method if available.
+ if stringer, ok := tag.(fmt.Stringer); ok {
+ return stringer.String()
+ }
+
+ // Otherwise, get a default string representation of the tag's struct.
+ tagString := fmt.Sprintf("%T: %+v", tag, tag)
+
+ // Remove the boilerplate from BaseDependencyTag as it adds no value.
+ tagString = tagCleaner.ReplaceAllString(tagString, "")
+ return tagString
+}
+
+func (b *baseModuleContext) GetPathString(skipFirst bool) string {
+ sb := strings.Builder{}
+ tagPath := b.GetTagPath()
+ walkPath := b.GetWalkPath()
+ if !skipFirst {
+ sb.WriteString(walkPath[0].String())
+ }
+ for i, m := range walkPath[1:] {
+ sb.WriteString("\n")
+ sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
+ sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
+ }
+ return sb.String()
}
func (m *moduleContext) ModuleSubDir() string {
@@ -1779,7 +2538,7 @@ func (b *baseModuleContext) Os() OsType {
}
func (b *baseModuleContext) Host() bool {
- return b.os.Class == Host || b.os.Class == HostCross
+ return b.os.Class == Host
}
func (b *baseModuleContext) Device() bool {
@@ -1819,10 +2578,6 @@ func (m *ModuleBase) MakeAsPlatform() {
m.commonProperties.System_ext_specific = boolPtr(false)
}
-func (m *ModuleBase) EnableNativeBridgeSupportByDefault() {
- m.commonProperties.Native_bridge_supported = boolPtr(true)
-}
-
func (m *ModuleBase) MakeAsSystemExt() {
m.commonProperties.Vendor = boolPtr(false)
m.commonProperties.Proprietary = boolPtr(false)
@@ -1852,6 +2607,14 @@ func (m *moduleContext) InstallInRamdisk() bool {
return m.module.InstallInRamdisk()
}
+func (m *moduleContext) InstallInVendorRamdisk() bool {
+ return m.module.InstallInVendorRamdisk()
+}
+
+func (m *moduleContext) InstallInDebugRamdisk() bool {
+ return m.module.InstallInDebugRamdisk()
+}
+
func (m *moduleContext) InstallInRecovery() bool {
return m.module.InstallInRecovery()
}
@@ -1864,11 +2627,19 @@ func (m *moduleContext) InstallBypassMake() bool {
return m.module.InstallBypassMake()
}
-func (m *moduleContext) skipInstall(fullInstallPath InstallPath) bool {
+func (m *moduleContext) InstallForceOS() (*OsType, *ArchType) {
+ return m.module.InstallForceOS()
+}
+
+func (m *moduleContext) skipInstall() bool {
if m.module.base().commonProperties.SkipInstall {
return true
}
+ if m.module.base().commonProperties.HideFromMake {
+ return true
+ }
+
// We'll need a solution for choosing which of modules with the same name in different
// namespaces to install. For now, reuse the list of namespaces exported to Make as the
// list of namespaces to install in a Soong-only build.
@@ -1877,11 +2648,7 @@ func (m *moduleContext) skipInstall(fullInstallPath InstallPath) bool {
}
if m.Device() {
- if m.Config().EmbeddedInMake() && !m.InstallBypassMake() {
- return true
- }
-
- if m.Config().SkipMegaDeviceInstall(fullInstallPath.String()) {
+ if m.Config().KatiEnabled() && !m.InstallBypassMake() {
return true
}
}
@@ -1891,23 +2658,37 @@ func (m *moduleContext) skipInstall(fullInstallPath InstallPath) bool {
func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
deps ...Path) InstallPath {
- return m.installFile(installPath, name, srcPath, Cp, deps)
+ return m.installFile(installPath, name, srcPath, deps, false)
}
func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
deps ...Path) InstallPath {
- return m.installFile(installPath, name, srcPath, CpExecutable, deps)
+ return m.installFile(installPath, name, srcPath, deps, true)
}
-func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path,
- rule blueprint.Rule, deps []Path) InstallPath {
-
+func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec {
fullInstallPath := installPath.Join(m, name)
- m.module.base().hooks.runInstallHooks(m, fullInstallPath, false)
+ return m.packageFile(fullInstallPath, srcPath, false)
+}
- if !m.skipInstall(fullInstallPath) {
+func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
+ spec := PackagingSpec{
+ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
+ srcPath: srcPath,
+ symlinkTarget: "",
+ executable: executable,
+ }
+ m.packagingSpecs = append(m.packagingSpecs, spec)
+ return spec
+}
- deps = append(deps, m.installDeps...)
+func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []Path, executable bool) InstallPath {
+
+ fullInstallPath := installPath.Join(m, name)
+ m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
+
+ if !m.skipInstall() {
+ deps = append(deps, m.module.base().installFilesDepSet.ToList().Paths()...)
var implicitDeps, orderOnlyDeps Paths
@@ -1919,6 +2700,11 @@ func (m *moduleContext) installFile(installPath InstallPath, name string, srcPat
orderOnlyDeps = deps
}
+ rule := Cp
+ if executable {
+ rule = CpExecutable
+ }
+
m.Build(pctx, BuildParams{
Rule: rule,
Description: "install " + fullInstallPath.Base(),
@@ -1926,31 +2712,35 @@ func (m *moduleContext) installFile(installPath InstallPath, name string, srcPat
Input: srcPath,
Implicits: implicitDeps,
OrderOnly: orderOnlyDeps,
- Default: !m.Config().EmbeddedInMake(),
+ Default: !m.Config().KatiEnabled(),
})
m.installFiles = append(m.installFiles, fullInstallPath)
}
+
+ m.packageFile(fullInstallPath, srcPath, executable)
+
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
+
return fullInstallPath
}
func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath {
fullInstallPath := installPath.Join(m, name)
- m.module.base().hooks.runInstallHooks(m, fullInstallPath, true)
+ m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, true)
- if !m.skipInstall(fullInstallPath) {
+ relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
+ if err != nil {
+ panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
+ }
+ if !m.skipInstall() {
- relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
- if err != nil {
- panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
- }
m.Build(pctx, BuildParams{
Rule: Symlink,
Description: "install symlink " + fullInstallPath.Base(),
Output: fullInstallPath,
Input: srcPath,
- Default: !m.Config().EmbeddedInMake(),
+ Default: !m.Config().KatiEnabled(),
Args: map[string]string{
"fromPath": relPath,
},
@@ -1959,6 +2749,14 @@ func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, src
m.installFiles = append(m.installFiles, fullInstallPath)
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
}
+
+ m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
+ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
+ srcPath: nil,
+ symlinkTarget: relPath,
+ executable: false,
+ })
+
return fullInstallPath
}
@@ -1966,14 +2764,14 @@ func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, src
// (e.g. /apex/...)
func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath {
fullInstallPath := installPath.Join(m, name)
- m.module.base().hooks.runInstallHooks(m, fullInstallPath, true)
+ m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
- if !m.skipInstall(fullInstallPath) {
+ if !m.skipInstall() {
m.Build(pctx, BuildParams{
Rule: Symlink,
Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
Output: fullInstallPath,
- Default: !m.Config().EmbeddedInMake(),
+ Default: !m.Config().KatiEnabled(),
Args: map[string]string{
"fromPath": absPath,
},
@@ -1981,6 +2779,14 @@ func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name str
m.installFiles = append(m.installFiles, fullInstallPath)
}
+
+ m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
+ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
+ srcPath: nil,
+ symlinkTarget: absPath,
+ executable: false,
+ })
+
return fullInstallPath
}
@@ -1988,27 +2794,8 @@ func (m *moduleContext) CheckbuildFile(srcPath Path) {
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
}
-type fileInstaller interface {
- filesToInstall() Paths
-}
-
-func isFileInstaller(m blueprint.Module) bool {
- _, ok := m.(fileInstaller)
- return ok
-}
-
-func isAndroidModule(m blueprint.Module) bool {
- _, ok := m.(Module)
- return ok
-}
-
-func findStringInSlice(str string, slice []string) int {
- for i, s := range slice {
- if s == str {
- return i
- }
- }
- return -1
+func (m *moduleContext) blueprintModuleContext() blueprint.ModuleContext {
+ return m.bp
}
// SrcIsModule decodes module references in the format ":name" into the module name, or empty string if the input
@@ -2112,7 +2899,7 @@ func OutputFileForModule(ctx PathContext, module blueprint.Module, tag string) P
return nil
}
if len(paths) > 1 {
- reportPathErrorf(ctx, "got multiple output files from module %q, expected exactly one",
+ ReportPathErrorf(ctx, "got multiple output files from module %q, expected exactly one",
pathContextName(ctx, module))
return nil
}
@@ -2130,12 +2917,26 @@ func outputFilesForModule(ctx PathContext, module blueprint.Module, tag string)
return nil, fmt.Errorf("failed to get output files from module %q", pathContextName(ctx, module))
}
return paths, nil
+ } else if sourceFileProducer, ok := module.(SourceFileProducer); ok {
+ if tag != "" {
+ return nil, fmt.Errorf("module %q is a SourceFileProducer, not an OutputFileProducer, and so does not support tag %q", pathContextName(ctx, module), tag)
+ }
+ paths := sourceFileProducer.Srcs()
+ if len(paths) == 0 {
+ return nil, fmt.Errorf("failed to get output files from module %q", pathContextName(ctx, module))
+ }
+ return paths, nil
} else {
return nil, fmt.Errorf("module %q is not an OutputFileProducer", pathContextName(ctx, module))
}
}
+// Modules can implement HostToolProvider and return a valid OptionalPath from HostToolPath() to
+// specify that they can be used as a tool by a genrule module.
type HostToolProvider interface {
+ Module
+ // HostToolPath returns the path to the host tool for the module if it is one, or an invalid
+ // OptionalPath.
HostToolPath() OptionalPath
}
@@ -2217,7 +3018,7 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
})
suffix := ""
- if ctx.Config().EmbeddedInMake() {
+ if ctx.Config().KatiEnabled() {
suffix = "-soong"
}
@@ -2225,7 +3026,7 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
ctx.Phony("checkbuild"+suffix, checkbuildDeps...)
// Make will generate the MODULES-IN-* targets
- if ctx.Config().EmbeddedInMake() {
+ if ctx.Config().KatiEnabled() {
return
}
@@ -2258,30 +3059,36 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
}
// Create (host|host-cross|target)-<OS> phony rules to build a reduced checkbuild.
- osDeps := map[OsType]Paths{}
+ type osAndCross struct {
+ os OsType
+ hostCross bool
+ }
+ osDeps := map[osAndCross]Paths{}
ctx.VisitAllModules(func(module Module) {
if module.Enabled() {
- os := module.Target().Os
- osDeps[os] = append(osDeps[os], module.base().checkbuildFiles...)
+ key := osAndCross{os: module.Target().Os, hostCross: module.Target().HostCross}
+ osDeps[key] = append(osDeps[key], module.base().checkbuildFiles...)
}
})
osClass := make(map[string]Paths)
- for os, deps := range osDeps {
+ for key, deps := range osDeps {
var className string
- switch os.Class {
+ switch key.os.Class {
case Host:
- className = "host"
- case HostCross:
- className = "host-cross"
+ if key.hostCross {
+ className = "host-cross"
+ } else {
+ className = "host"
+ }
case Device:
className = "target"
default:
continue
}
- name := className + "-" + os.Name
+ name := className + "-" + key.os.Name
osClass[className] = append(osClass[className], PathForPhony(ctx, name))
ctx.Phony(name, deps...)
@@ -2316,4 +3123,30 @@ type IdeInfo struct {
Classes []string `json:"class,omitempty"`
Installed_paths []string `json:"installed,omitempty"`
SrcJars []string `json:"srcjars,omitempty"`
+ Paths []string `json:"path,omitempty"`
+}
+
+func CheckBlueprintSyntax(ctx BaseModuleContext, filename string, contents string) []error {
+ bpctx := ctx.blueprintBaseModuleContext()
+ return blueprint.CheckBlueprintSyntax(bpctx.ModuleFactories(), filename, contents)
+}
+
+// installPathsDepSet is a thin type-safe wrapper around the generic depSet. It always uses
+// topological order.
+type installPathsDepSet struct {
+ depSet
+}
+
+// newInstallPathsDepSet returns an immutable packagingSpecsDepSet with the given direct and
+// transitive contents.
+func newInstallPathsDepSet(direct InstallPaths, transitive []*installPathsDepSet) *installPathsDepSet {
+ return &installPathsDepSet{*newDepSet(TOPOLOGICAL, direct, transitive)}
+}
+
+// ToList returns the installPathsDepSet flattened to a list in topological order.
+func (d *installPathsDepSet) ToList() InstallPaths {
+ if d == nil {
+ return nil
+ }
+ return d.depSet.ToList().(InstallPaths)
}