123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- // 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"
- "path/filepath"
- "strings"
- "android/soong/android"
- )
- func init() {
- registerPythonBinaryComponents(android.InitRegistrationContext)
- }
- func registerPythonBinaryComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
- }
- type BinaryProperties struct {
- // 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.
- Main *string
- // set the name of the output binary.
- Stem *string `android:"arch_variant"`
- // append to the name of the output binary.
- Suffix *string `android:"arch_variant"`
- // list of compatibility suites (for example "cts", "vts") that the module should be
- // installed into.
- Test_suites []string `android:"arch_variant"`
- // 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"`
- // 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
- }
- type PythonBinaryModule struct {
- PythonLibraryModule
- binaryProperties BinaryProperties
- // (.intermediate) module output path as installation source.
- installSource android.Path
- // Final installation path.
- installedDest android.Path
- androidMkSharedLibs []string
- }
- var _ android.AndroidMkEntriesProvider = (*PythonBinaryModule)(nil)
- var _ android.Module = (*PythonBinaryModule)(nil)
- type IntermPathProvider interface {
- IntermPathForModuleOut() android.OptionalPath
- }
- func NewBinary(hod android.HostOrDeviceSupported) *PythonBinaryModule {
- return &PythonBinaryModule{
- PythonLibraryModule: *newModule(hod, android.MultilibFirst),
- }
- }
- func PythonBinaryHostFactory() android.Module {
- return NewBinary(android.HostSupported).init()
- }
- 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
- }
- 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)
- }
- func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) {
- embeddedLauncher := p.isEmbeddedLauncherEnabled()
- depsSrcsZips := p.collectPathsFromTransitiveDeps(ctx, embeddedLauncher)
- main := ""
- if p.autorun() {
- main = p.getPyMainFile(ctx, p.srcsPathMappings)
- }
- var launcherPath android.OptionalPath
- if embeddedLauncher {
- ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) {
- if provider, ok := m.(IntermPathProvider); ok {
- if launcherPath.Valid() {
- panic(fmt.Errorf("launcher path was found before: %q",
- launcherPath))
- }
- launcherPath = provider.IntermPathForModuleOut()
- }
- })
- }
- srcsZips := make(android.Paths, 0, len(depsSrcsZips)+1)
- if embeddedLauncher {
- srcsZips = append(srcsZips, p.precompiledSrcsZip)
- } else {
- srcsZips = append(srcsZips, p.srcsZip)
- }
- srcsZips = append(srcsZips, depsSrcsZips...)
- p.installSource = registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
- p.getHostInterpreterName(ctx, p.properties.Actual_version),
- main, p.getStem(ctx), srcsZips)
- 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)
- if p.isEmbeddedLauncherEnabled() {
- p.AddDepsOnPythonLauncherAndStdlib(ctx, pythonLibTag, launcherTag, launcherSharedLibTag, p.autorun(), ctx.Target())
- }
- }
- // 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)
- }
- // get host interpreter name.
- func (p *PythonBinaryModule) getHostInterpreterName(ctx android.ModuleContext,
- actualVersion string) string {
- var interp string
- switch actualVersion {
- case pyVersion2:
- interp = "python2.7"
- case pyVersion3:
- interp = "python3"
- default:
- panic(fmt.Errorf("unknown Python actualVersion: %q for module: %q.",
- actualVersion, ctx.ModuleName()))
- }
- return interp
- }
- // find main program path within runfiles tree.
- func (p *PythonBinaryModule) getPyMainFile(ctx android.ModuleContext,
- srcsPathMappings []pathMapping) string {
- var main string
- if String(p.binaryProperties.Main) == "" {
- main = ctx.ModuleName() + pyExt
- } else {
- main = String(p.binaryProperties.Main)
- }
- for _, path := range srcsPathMappings {
- if main == path.src.Rel() {
- return path.dest
- }
- }
- ctx.PropertyErrorf("main", "%q is not listed in srcs.", main)
- return ""
- }
- func (p *PythonBinaryModule) getStem(ctx android.ModuleContext) string {
- stem := ctx.ModuleName()
- if String(p.binaryProperties.Stem) != "" {
- stem = String(p.binaryProperties.Stem)
- }
- 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)
- }
|