summaryrefslogtreecommitdiff
path: root/python/python.go
diff options
context:
space:
mode:
Diffstat (limited to 'python/python.go')
-rw-r--r--python/python.go194
1 files changed, 112 insertions, 82 deletions
diff --git a/python/python.go b/python/python.go
index 1ee533fa8..09af62ea5 100644
--- a/python/python.go
+++ b/python/python.go
@@ -22,12 +22,23 @@ import (
"regexp"
"strings"
+ "android/soong/cc"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
)
+type PythonLibraryInfo struct {
+ SrcsPathMappings []pathMapping
+ DataPathMappings []pathMapping
+ SrcsZip android.Path
+ PrecompiledSrcsZip android.Path
+ PkgPath string
+}
+
+var PythonLibraryInfoProvider = blueprint.NewProvider[PythonLibraryInfo]()
+
func init() {
registerPythonMutators(android.InitRegistrationContext)
}
@@ -38,7 +49,7 @@ func registerPythonMutators(ctx android.RegistrationContext) {
// Exported to support other packages using Python modules in tests.
func RegisterPythonPreDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("python_version", versionSplitMutator()).Parallel()
+ ctx.Transition("python_version", &versionSplitTransitionMutator{})
}
// the version-specific properties that apply to python modules.
@@ -90,6 +101,16 @@ type BaseProperties struct {
// the test. the file extension can be arbitrary except for (.py).
Data []string `android:"path,arch_variant"`
+ // Same as data, but will add dependencies on modules using the device's os variation and
+ // the common arch variation. Useful for a host test that wants to embed a module built for
+ // device.
+ Device_common_data []string `android:"path_device_common"`
+
+ // Same as data, but will add dependencies on modules via a device os variation and the
+ // device's first supported arch's variation. Useful for a host test that wants to embed a
+ // module built for device.
+ Device_first_data []string `android:"path_device_first"`
+
// list of java modules that provide data that should be installed alongside the test.
Java_data []string
@@ -163,16 +184,6 @@ func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Py
}
}
-// interface implemented by Python modules to provide source and data mappings and zip to python
-// modules that depend on it
-type pythonDependency interface {
- getSrcsPathMappings() []pathMapping
- getDataPathMappings() []pathMapping
- getSrcsZip() android.Path
- getPrecompiledSrcsZip() android.Path
- getPkgPath() string
-}
-
// getSrcsPathMappings gets this module's path mapping of src source path : runfiles destination
func (p *PythonLibraryModule) getSrcsPathMappings() []pathMapping {
return p.srcsPathMappings
@@ -202,8 +213,6 @@ func (p *PythonLibraryModule) getBaseProperties() *BaseProperties {
return &p.properties
}
-var _ pythonDependency = (*PythonLibraryModule)(nil)
-
func (p *PythonLibraryModule) init() android.Module {
p.AddProperties(&p.properties, &p.protoProperties, &p.sourceProperties)
android.InitAndroidArchModule(p, p.hod, p.multilib)
@@ -245,7 +254,6 @@ var (
protoExt = ".proto"
pyVersion2 = "PY2"
pyVersion3 = "PY3"
- pyVersion2And3 = "PY2ANDPY3"
internalPath = "internal"
)
@@ -253,46 +261,67 @@ type basePropertiesProvider interface {
getBaseProperties() *BaseProperties
}
-// versionSplitMutator creates version variants for modules and appends the version-specific
-// properties for a given variant to the properties in the variant module
-func versionSplitMutator() func(android.BottomUpMutatorContext) {
- return func(mctx android.BottomUpMutatorContext) {
- if base, ok := mctx.Module().(basePropertiesProvider); ok {
- props := base.getBaseProperties()
- var versionNames []string
- // collect version specific properties, so that we can merge version-specific properties
- // into the module's overall properties
- var versionProps []VersionProperties
- // PY3 is first so that we alias the PY3 variant rather than PY2 if both
- // are available
- if proptools.BoolDefault(props.Version.Py3.Enabled, true) {
- versionNames = append(versionNames, pyVersion3)
- versionProps = append(versionProps, props.Version.Py3)
- }
- if proptools.BoolDefault(props.Version.Py2.Enabled, false) {
- if !mctx.DeviceConfig().BuildBrokenUsesSoongPython2Modules() &&
- mctx.ModuleName() != "py2-cmd" &&
- mctx.ModuleName() != "py2-stdlib" {
- mctx.PropertyErrorf("version.py2.enabled", "Python 2 is no longer supported, please convert to python 3. This error can be temporarily overridden by setting BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES := true in the product configuration")
- }
- versionNames = append(versionNames, pyVersion2)
- versionProps = append(versionProps, props.Version.Py2)
- }
- modules := mctx.CreateLocalVariations(versionNames...)
- // Alias module to the first variant
- if len(versionNames) > 0 {
- mctx.AliasVariation(versionNames[0])
- }
- for i, v := range versionNames {
- // set the actual version for Python module.
- newProps := modules[i].(basePropertiesProvider).getBaseProperties()
- newProps.Actual_version = v
- // append versioned properties for the Python module to the overall properties
- err := proptools.AppendMatchingProperties([]interface{}{newProps}, &versionProps[i], nil)
- if err != nil {
- panic(err)
- }
+type versionSplitTransitionMutator struct{}
+
+func (versionSplitTransitionMutator) Split(ctx android.BaseModuleContext) []string {
+ if base, ok := ctx.Module().(basePropertiesProvider); ok {
+ props := base.getBaseProperties()
+ var variants []string
+ // PY3 is first so that we alias the PY3 variant rather than PY2 if both
+ // are available
+ if proptools.BoolDefault(props.Version.Py3.Enabled, true) {
+ variants = append(variants, pyVersion3)
+ }
+ if proptools.BoolDefault(props.Version.Py2.Enabled, false) {
+ if ctx.ModuleName() != "py2-cmd" &&
+ ctx.ModuleName() != "py2-stdlib" {
+ ctx.PropertyErrorf("version.py2.enabled", "Python 2 is no longer supported, please convert to python 3.")
}
+ variants = append(variants, pyVersion2)
+ }
+ return variants
+ }
+ return []string{""}
+}
+
+func (versionSplitTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ return ""
+}
+
+func (versionSplitTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ if incomingVariation != "" {
+ return incomingVariation
+ }
+ if base, ok := ctx.Module().(basePropertiesProvider); ok {
+ props := base.getBaseProperties()
+ if proptools.BoolDefault(props.Version.Py3.Enabled, true) {
+ return pyVersion3
+ } else {
+ return pyVersion2
+ }
+ }
+
+ return ""
+}
+
+func (versionSplitTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ if variation == "" {
+ return
+ }
+ if base, ok := ctx.Module().(basePropertiesProvider); ok {
+ props := base.getBaseProperties()
+ props.Actual_version = variation
+
+ var versionProps *VersionProperties
+ if variation == pyVersion3 {
+ versionProps = &props.Version.Py3
+ } else if variation == pyVersion2 {
+ versionProps = &props.Version.Py2
+ }
+
+ err := proptools.AppendMatchingProperties([]interface{}{props}, versionProps, nil)
+ if err != nil {
+ panic(err)
}
}
}
@@ -422,7 +451,6 @@ func (p *PythonLibraryModule) AddDepsOnPythonLauncherAndStdlib(ctx android.Botto
// GenerateAndroidBuildActions performs build actions common to all Python modules
func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
expandedSrcs := android.PathsForModuleSrcExcludes(ctx, p.properties.Srcs, p.properties.Exclude_srcs)
- android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: expandedSrcs.Strings()})
// Keep before any early returns.
android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
TestOnly: Bool(p.sourceProperties.Test_only),
@@ -431,9 +459,11 @@ func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleCont
// expand data files from "data" property.
expandedData := android.PathsForModuleSrc(ctx, p.properties.Data)
+ expandedData = append(expandedData, android.PathsForModuleSrc(ctx, p.properties.Device_common_data)...)
+ expandedData = append(expandedData, android.PathsForModuleSrc(ctx, p.properties.Device_first_data)...)
// Emulate the data property for java_data dependencies.
- for _, javaData := range ctx.GetDirectDepsWithTag(javaDataTag) {
+ for _, javaData := range ctx.GetDirectDepsProxyWithTag(javaDataTag) {
expandedData = append(expandedData, android.OutputFilesForModule(ctx, javaData, "")...)
}
@@ -461,6 +491,14 @@ func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleCont
// generate the zipfile of all source and data files
p.srcsZip = p.createSrcsZip(ctx, pkgPath)
p.precompiledSrcsZip = p.precompileSrcs(ctx)
+
+ android.SetProvider(ctx, PythonLibraryInfoProvider, PythonLibraryInfo{
+ SrcsPathMappings: p.getSrcsPathMappings(),
+ DataPathMappings: p.getDataPathMappings(),
+ SrcsZip: p.getSrcsZip(),
+ PkgPath: p.getPkgPath(),
+ PrecompiledSrcsZip: p.getPrecompiledSrcsZip(),
+ })
}
func isValidPythonPath(path string) error {
@@ -626,16 +664,16 @@ func (p *PythonLibraryModule) precompileSrcs(ctx android.ModuleContext) android.
stdLib = p.srcsZip
stdLibPkg = p.getPkgPath()
} else {
- ctx.VisitDirectDepsWithTag(hostStdLibTag, func(module android.Module) {
- if dep, ok := module.(pythonDependency); ok {
- stdLib = dep.getPrecompiledSrcsZip()
- stdLibPkg = dep.getPkgPath()
+ ctx.VisitDirectDepsProxyWithTag(hostStdLibTag, func(module android.ModuleProxy) {
+ if dep, ok := android.OtherModuleProvider(ctx, module, PythonLibraryInfoProvider); ok {
+ stdLib = dep.PrecompiledSrcsZip
+ stdLibPkg = dep.PkgPath
}
})
}
- ctx.VisitDirectDepsWithTag(hostLauncherTag, func(module android.Module) {
- if dep, ok := module.(IntermPathProvider); ok {
- optionalLauncher := dep.IntermPathForModuleOut()
+ ctx.VisitDirectDepsProxyWithTag(hostLauncherTag, func(module android.ModuleProxy) {
+ if dep, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok {
+ optionalLauncher := dep.OutputFile
if optionalLauncher.Valid() {
launcher = optionalLauncher.Path()
}
@@ -643,9 +681,9 @@ func (p *PythonLibraryModule) precompileSrcs(ctx android.ModuleContext) android.
})
var launcherSharedLibs android.Paths
var ldLibraryPath []string
- ctx.VisitDirectDepsWithTag(hostlauncherSharedLibTag, func(module android.Module) {
- if dep, ok := module.(IntermPathProvider); ok {
- optionalPath := dep.IntermPathForModuleOut()
+ ctx.VisitDirectDepsProxyWithTag(hostlauncherSharedLibTag, func(module android.ModuleProxy) {
+ if dep, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok {
+ optionalPath := dep.OutputFile
if optionalPath.Valid() {
launcherSharedLibs = append(launcherSharedLibs, optionalPath.Path())
ldLibraryPath = append(ldLibraryPath, filepath.Dir(optionalPath.Path().String()))
@@ -676,16 +714,6 @@ func (p *PythonLibraryModule) precompileSrcs(ctx android.ModuleContext) android.
return out
}
-// isPythonLibModule returns whether the given module is a Python library PythonLibraryModule or not
-func isPythonLibModule(module blueprint.Module) bool {
- if _, ok := module.(*PythonLibraryModule); ok {
- if _, ok := module.(*PythonBinaryModule); !ok {
- return true
- }
- }
- return false
-}
-
// collectPathsFromTransitiveDeps checks for source/data files for duplicate paths
// for module and its transitive dependencies and collects list of data/source file
// zips for transitive dependencies.
@@ -706,7 +734,7 @@ func (p *PythonLibraryModule) collectPathsFromTransitiveDeps(ctx android.ModuleC
var result android.Paths
// visit all its dependencies in depth first.
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(child, _ android.ModuleProxy) bool {
// we only collect dependencies tagged as python library deps
if ctx.OtherModuleDependencyTag(child) != pythonLibTag {
return false
@@ -716,27 +744,29 @@ func (p *PythonLibraryModule) collectPathsFromTransitiveDeps(ctx android.ModuleC
}
seen[child] = true
// Python modules only can depend on Python libraries.
- if !isPythonLibModule(child) {
+ dep, isLibrary := android.OtherModuleProvider(ctx, child, PythonLibraryInfoProvider)
+ _, isBinary := android.OtherModuleProvider(ctx, child, PythonBinaryInfoProvider)
+ if !isLibrary || isBinary {
ctx.PropertyErrorf("libs",
"the dependency %q of module %q is not Python library!",
ctx.OtherModuleName(child), ctx.ModuleName())
}
// collect source and data paths, checking that there are no duplicate output file conflicts
- if dep, ok := child.(pythonDependency); ok {
- srcs := dep.getSrcsPathMappings()
+ if isLibrary {
+ srcs := dep.SrcsPathMappings
for _, path := range srcs {
checkForDuplicateOutputPath(ctx, destToPySrcs,
path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(child))
}
- data := dep.getDataPathMappings()
+ data := dep.DataPathMappings
for _, path := range data {
checkForDuplicateOutputPath(ctx, destToPyData,
path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(child))
}
if precompiled {
- result = append(result, dep.getPrecompiledSrcsZip())
+ result = append(result, dep.PrecompiledSrcsZip)
} else {
- result = append(result, dep.getSrcsZip())
+ result = append(result, dep.SrcsZip)
}
}
return true