2017-02-27 19:12:13 +01:00
|
|
|
|
// Copyright 2017 Google Inc. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
|
|
package python
|
|
|
|
|
|
|
|
|
|
// This file contains the module types for building Python binary.
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
2023-01-23 19:14:58 +01:00
|
|
|
|
"path/filepath"
|
|
|
|
|
"strings"
|
2017-02-27 19:12:13 +01:00
|
|
|
|
|
2023-01-23 19:14:58 +01:00
|
|
|
|
"github.com/google/blueprint"
|
2021-03-08 13:32:28 +01:00
|
|
|
|
|
2023-01-23 19:14:58 +01:00
|
|
|
|
"android/soong/android"
|
2017-02-27 19:12:13 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func init() {
|
2021-03-17 22:57:08 +01:00
|
|
|
|
registerPythonBinaryComponents(android.InitRegistrationContext)
|
2021-03-08 13:32:28 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-17 22:57:08 +01:00
|
|
|
|
func registerPythonBinaryComponents(ctx android.RegistrationContext) {
|
|
|
|
|
ctx.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-12 21:55:28 +02:00
|
|
|
|
type BinaryProperties struct {
|
2017-02-27 19:12:13 +01:00
|
|
|
|
// the name of the source file that is the main entry point of the program.
|
|
|
|
|
// this file must also be listed in srcs.
|
|
|
|
|
// If left unspecified, module name is used instead.
|
|
|
|
|
// If name doesn’t match any filename in srcs, main must be specified.
|
2017-11-09 06:20:04 +01:00
|
|
|
|
Main *string `android:"arch_variant"`
|
2017-02-27 19:12:13 +01:00
|
|
|
|
|
|
|
|
|
// set the name of the output binary.
|
2017-11-09 06:20:04 +01:00
|
|
|
|
Stem *string `android:"arch_variant"`
|
2017-02-27 19:12:13 +01:00
|
|
|
|
|
|
|
|
|
// append to the name of the output binary.
|
2017-11-09 06:20:04 +01:00
|
|
|
|
Suffix *string `android:"arch_variant"`
|
2017-11-04 00:54:05 +01:00
|
|
|
|
|
|
|
|
|
// list of compatibility suites (for example "cts", "vts") that the module should be
|
|
|
|
|
// installed into.
|
|
|
|
|
Test_suites []string `android:"arch_variant"`
|
2019-02-15 08:17:08 +01:00
|
|
|
|
|
|
|
|
|
// whether to use `main` when starting the executable. The default is true, when set to
|
|
|
|
|
// false it will act much like the normal `python` executable, but with the sources and
|
|
|
|
|
// libraries automatically included in the PYTHONPATH.
|
|
|
|
|
Autorun *bool `android:"arch_variant"`
|
2019-09-26 20:41:36 +02:00
|
|
|
|
|
|
|
|
|
// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
|
|
|
|
|
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
|
|
|
|
|
// explicitly.
|
|
|
|
|
Auto_gen_config *bool
|
2017-02-27 19:12:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-23 19:14:58 +01:00
|
|
|
|
type PythonBinaryModule struct {
|
|
|
|
|
PythonLibraryModule
|
2017-07-12 21:55:28 +02:00
|
|
|
|
binaryProperties BinaryProperties
|
2017-02-27 19:12:13 +01:00
|
|
|
|
|
2023-01-23 19:14:58 +01:00
|
|
|
|
// (.intermediate) module output path as installation source.
|
|
|
|
|
installSource android.Path
|
|
|
|
|
|
|
|
|
|
// Final installation path.
|
|
|
|
|
installedDest android.Path
|
|
|
|
|
|
|
|
|
|
androidMkSharedLibs []string
|
2017-05-10 22:37:54 +02:00
|
|
|
|
}
|
2017-02-27 19:12:13 +01:00
|
|
|
|
|
2023-01-23 19:14:58 +01:00
|
|
|
|
var _ android.AndroidMkEntriesProvider = (*PythonBinaryModule)(nil)
|
|
|
|
|
var _ android.Module = (*PythonBinaryModule)(nil)
|
|
|
|
|
|
2017-07-12 21:55:28 +02:00
|
|
|
|
type IntermPathProvider interface {
|
|
|
|
|
IntermPathForModuleOut() android.OptionalPath
|
2017-02-27 19:12:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-23 19:14:58 +01:00
|
|
|
|
func NewBinary(hod android.HostOrDeviceSupported) *PythonBinaryModule {
|
|
|
|
|
return &PythonBinaryModule{
|
|
|
|
|
PythonLibraryModule: *newModule(hod, android.MultilibFirst),
|
|
|
|
|
}
|
2017-02-27 19:12:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-12 21:55:28 +02:00
|
|
|
|
func PythonBinaryHostFactory() android.Module {
|
2023-01-23 19:14:58 +01:00
|
|
|
|
return NewBinary(android.HostSupported).init()
|
2017-07-12 21:55:28 +02:00
|
|
|
|
}
|
2017-02-27 19:12:13 +01:00
|
|
|
|
|
2023-01-23 19:14:58 +01:00
|
|
|
|
func (p *PythonBinaryModule) init() android.Module {
|
|
|
|
|
p.AddProperties(&p.properties, &p.protoProperties)
|
|
|
|
|
p.AddProperties(&p.binaryProperties)
|
|
|
|
|
android.InitAndroidArchModule(p, p.hod, p.multilib)
|
|
|
|
|
android.InitDefaultableModule(p)
|
|
|
|
|
android.InitBazelModule(p)
|
|
|
|
|
return p
|
2019-02-15 08:17:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-23 19:14:58 +01:00
|
|
|
|
func (p *PythonBinaryModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
|
|
|
p.PythonLibraryModule.GenerateAndroidBuildActions(ctx)
|
|
|
|
|
p.buildBinary(ctx)
|
|
|
|
|
p.installedDest = ctx.InstallFile(installDir(ctx, "bin", "", ""),
|
|
|
|
|
p.installSource.Base(), p.installSource)
|
2017-07-12 21:55:28 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-23 19:14:58 +01:00
|
|
|
|
func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) {
|
|
|
|
|
depsSrcsZips := p.collectPathsFromTransitiveDeps(ctx)
|
2019-02-15 08:17:08 +01:00
|
|
|
|
main := ""
|
2023-01-23 19:14:58 +01:00
|
|
|
|
if p.autorun() {
|
|
|
|
|
main = p.getPyMainFile(ctx, p.srcsPathMappings)
|
2019-02-15 08:17:08 +01:00
|
|
|
|
}
|
2017-07-12 21:55:28 +02:00
|
|
|
|
|
2018-09-27 00:14:10 +02:00
|
|
|
|
var launcherPath android.OptionalPath
|
2023-01-23 19:14:58 +01:00
|
|
|
|
embeddedLauncher := p.isEmbeddedLauncherEnabled()
|
2017-12-18 22:20:23 +01:00
|
|
|
|
if embeddedLauncher {
|
2017-12-31 02:54:27 +01:00
|
|
|
|
ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) {
|
2017-07-12 21:55:28 +02:00
|
|
|
|
if provider, ok := m.(IntermPathProvider); ok {
|
2018-09-27 00:14:10 +02:00
|
|
|
|
if launcherPath.Valid() {
|
2017-07-12 21:55:28 +02:00
|
|
|
|
panic(fmt.Errorf("launcher path was found before: %q",
|
2017-12-18 22:20:23 +01:00
|
|
|
|
launcherPath))
|
2017-07-12 21:55:28 +02:00
|
|
|
|
}
|
2018-09-27 00:14:10 +02:00
|
|
|
|
launcherPath = provider.IntermPathForModuleOut()
|
2017-07-12 21:55:28 +02:00
|
|
|
|
}
|
|
|
|
|
})
|
2017-02-27 19:12:13 +01:00
|
|
|
|
}
|
2023-01-23 19:14:58 +01:00
|
|
|
|
p.installSource = registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
|
|
|
|
|
p.getHostInterpreterName(ctx, p.properties.Actual_version),
|
|
|
|
|
main, p.getStem(ctx), append(android.Paths{p.srcsZip}, depsSrcsZips...))
|
|
|
|
|
|
|
|
|
|
var sharedLibs []string
|
|
|
|
|
// if embedded launcher is enabled, we need to collect the shared library dependencies of the
|
|
|
|
|
// launcher
|
|
|
|
|
for _, dep := range ctx.GetDirectDepsWithTag(launcherSharedLibTag) {
|
|
|
|
|
sharedLibs = append(sharedLibs, ctx.OtherModuleName(dep))
|
|
|
|
|
}
|
|
|
|
|
p.androidMkSharedLibs = sharedLibs
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PythonBinaryModule) AndroidMkEntries() []android.AndroidMkEntries {
|
|
|
|
|
entries := android.AndroidMkEntries{OutputFile: android.OptionalPathForPath(p.installSource)}
|
|
|
|
|
|
|
|
|
|
entries.Class = "EXECUTABLES"
|
|
|
|
|
|
|
|
|
|
entries.ExtraEntries = append(entries.ExtraEntries,
|
|
|
|
|
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
|
|
|
|
|
entries.AddCompatibilityTestSuites(p.binaryProperties.Test_suites...)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
entries.Required = append(entries.Required, "libc++")
|
|
|
|
|
entries.ExtraEntries = append(entries.ExtraEntries,
|
|
|
|
|
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
|
|
|
|
|
path, file := filepath.Split(p.installedDest.String())
|
|
|
|
|
stem := strings.TrimSuffix(file, filepath.Ext(file))
|
|
|
|
|
|
|
|
|
|
entries.SetString("LOCAL_MODULE_SUFFIX", filepath.Ext(file))
|
|
|
|
|
entries.SetString("LOCAL_MODULE_PATH", path)
|
|
|
|
|
entries.SetString("LOCAL_MODULE_STEM", stem)
|
|
|
|
|
entries.AddStrings("LOCAL_SHARED_LIBRARIES", p.androidMkSharedLibs...)
|
|
|
|
|
entries.SetBool("LOCAL_CHECK_ELF_FILES", false)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return []android.AndroidMkEntries{entries}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PythonBinaryModule) DepsMutator(ctx android.BottomUpMutatorContext) {
|
|
|
|
|
p.PythonLibraryModule.DepsMutator(ctx)
|
|
|
|
|
|
|
|
|
|
versionVariation := []blueprint.Variation{
|
|
|
|
|
{"python_version", p.properties.Actual_version},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If this module will be installed and has an embedded launcher, we need to add dependencies for:
|
|
|
|
|
// * standard library
|
|
|
|
|
// * launcher
|
|
|
|
|
// * shared dependencies of the launcher
|
|
|
|
|
if p.isEmbeddedLauncherEnabled() {
|
|
|
|
|
var stdLib string
|
|
|
|
|
var launcherModule string
|
|
|
|
|
// Add launcher shared lib dependencies. Ideally, these should be
|
|
|
|
|
// derived from the `shared_libs` property of the launcher. However, we
|
|
|
|
|
// cannot read the property at this stage and it will be too late to add
|
|
|
|
|
// dependencies later.
|
|
|
|
|
launcherSharedLibDeps := []string{
|
|
|
|
|
"libsqlite",
|
|
|
|
|
}
|
|
|
|
|
// Add launcher-specific dependencies for bionic
|
|
|
|
|
if ctx.Target().Os.Bionic() {
|
|
|
|
|
launcherSharedLibDeps = append(launcherSharedLibDeps, "libc", "libdl", "libm")
|
|
|
|
|
}
|
|
|
|
|
if ctx.Target().Os == android.LinuxMusl && !ctx.Config().HostStaticBinaries() {
|
|
|
|
|
launcherSharedLibDeps = append(launcherSharedLibDeps, "libc_musl")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch p.properties.Actual_version {
|
|
|
|
|
case pyVersion2:
|
|
|
|
|
stdLib = "py2-stdlib"
|
2017-02-27 19:12:13 +01:00
|
|
|
|
|
2023-01-23 19:14:58 +01:00
|
|
|
|
launcherModule = "py2-launcher"
|
|
|
|
|
if p.autorun() {
|
|
|
|
|
launcherModule = "py2-launcher-autorun"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
launcherSharedLibDeps = append(launcherSharedLibDeps, "libc++")
|
|
|
|
|
|
|
|
|
|
case pyVersion3:
|
|
|
|
|
stdLib = "py3-stdlib"
|
|
|
|
|
|
|
|
|
|
launcherModule = "py3-launcher"
|
|
|
|
|
if p.autorun() {
|
|
|
|
|
launcherModule = "py3-launcher-autorun"
|
|
|
|
|
}
|
|
|
|
|
if ctx.Config().HostStaticBinaries() && ctx.Target().Os == android.LinuxMusl {
|
|
|
|
|
launcherModule += "-static"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ctx.Device() {
|
|
|
|
|
launcherSharedLibDeps = append(launcherSharedLibDeps, "liblog")
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
panic(fmt.Errorf("unknown Python Actual_version: %q for module: %q.",
|
|
|
|
|
p.properties.Actual_version, ctx.ModuleName()))
|
|
|
|
|
}
|
|
|
|
|
ctx.AddVariationDependencies(versionVariation, pythonLibTag, stdLib)
|
|
|
|
|
ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherTag, launcherModule)
|
|
|
|
|
ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag, launcherSharedLibDeps...)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// HostToolPath returns a path if appropriate such that this module can be used as a host tool,
|
|
|
|
|
// fulfilling the android.HostToolProvider interface.
|
|
|
|
|
func (p *PythonBinaryModule) HostToolPath() android.OptionalPath {
|
|
|
|
|
// TODO: This should only be set when building host binaries -- tests built for device would be
|
|
|
|
|
// setting this incorrectly.
|
|
|
|
|
return android.OptionalPathForPath(p.installedDest)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// OutputFiles returns output files based on given tag, returns an error if tag is unsupported.
|
|
|
|
|
func (p *PythonBinaryModule) OutputFiles(tag string) (android.Paths, error) {
|
|
|
|
|
switch tag {
|
|
|
|
|
case "":
|
|
|
|
|
return android.Paths{p.installSource}, nil
|
|
|
|
|
default:
|
|
|
|
|
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PythonBinaryModule) isEmbeddedLauncherEnabled() bool {
|
|
|
|
|
return Bool(p.properties.Embedded_launcher)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *PythonBinaryModule) autorun() bool {
|
|
|
|
|
return BoolDefault(b.binaryProperties.Autorun, true)
|
2017-02-27 19:12:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-12 21:55:28 +02:00
|
|
|
|
// get host interpreter name.
|
2023-01-23 19:14:58 +01:00
|
|
|
|
func (p *PythonBinaryModule) getHostInterpreterName(ctx android.ModuleContext,
|
2017-12-18 22:20:23 +01:00
|
|
|
|
actualVersion string) string {
|
2017-02-27 19:12:13 +01:00
|
|
|
|
var interp string
|
2017-12-18 22:20:23 +01:00
|
|
|
|
switch actualVersion {
|
2017-02-27 19:12:13 +01:00
|
|
|
|
case pyVersion2:
|
2017-09-25 22:47:40 +02:00
|
|
|
|
interp = "python2.7"
|
2017-02-27 19:12:13 +01:00
|
|
|
|
case pyVersion3:
|
|
|
|
|
interp = "python3"
|
|
|
|
|
default:
|
|
|
|
|
panic(fmt.Errorf("unknown Python actualVersion: %q for module: %q.",
|
2017-12-18 22:20:23 +01:00
|
|
|
|
actualVersion, ctx.ModuleName()))
|
2017-02-27 19:12:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return interp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// find main program path within runfiles tree.
|
2023-01-23 19:14:58 +01:00
|
|
|
|
func (p *PythonBinaryModule) getPyMainFile(ctx android.ModuleContext,
|
2017-07-12 21:55:28 +02:00
|
|
|
|
srcsPathMappings []pathMapping) string {
|
2017-02-27 19:12:13 +01:00
|
|
|
|
var main string
|
2023-01-23 19:14:58 +01:00
|
|
|
|
if String(p.binaryProperties.Main) == "" {
|
2017-07-12 21:55:28 +02:00
|
|
|
|
main = ctx.ModuleName() + pyExt
|
2017-02-27 19:12:13 +01:00
|
|
|
|
} else {
|
2023-01-23 19:14:58 +01:00
|
|
|
|
main = String(p.binaryProperties.Main)
|
2017-02-27 19:12:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-12 21:55:28 +02:00
|
|
|
|
for _, path := range srcsPathMappings {
|
2017-02-27 19:12:13 +01:00
|
|
|
|
if main == path.src.Rel() {
|
|
|
|
|
return path.dest
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ctx.PropertyErrorf("main", "%q is not listed in srcs.", main)
|
|
|
|
|
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-23 19:14:58 +01:00
|
|
|
|
func (p *PythonBinaryModule) getStem(ctx android.ModuleContext) string {
|
2017-02-27 19:12:13 +01:00
|
|
|
|
stem := ctx.ModuleName()
|
2023-01-23 19:14:58 +01:00
|
|
|
|
if String(p.binaryProperties.Stem) != "" {
|
|
|
|
|
stem = String(p.binaryProperties.Stem)
|
2017-02-27 19:12:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-23 19:14:58 +01:00
|
|
|
|
return stem + String(p.binaryProperties.Suffix)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func installDir(ctx android.ModuleContext, dir, dir64, relative string) android.InstallPath {
|
|
|
|
|
if ctx.Arch().ArchType.Multilib == "lib64" && dir64 != "" {
|
|
|
|
|
dir = dir64
|
|
|
|
|
}
|
|
|
|
|
if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
|
|
|
|
|
dir = filepath.Join(dir, ctx.Arch().ArchType.String())
|
|
|
|
|
}
|
|
|
|
|
return android.PathForModuleInstall(ctx, dir, relative)
|
2017-02-27 19:12:13 +01:00
|
|
|
|
}
|