123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- // 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"
- "android/soong/android"
- "android/soong/bazel"
- "github.com/google/blueprint/proptools"
- )
- func init() {
- registerPythonBinaryComponents(android.InitRegistrationContext)
- }
- func registerPythonBinaryComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
- }
- type bazelPythonBinaryAttributes struct {
- Main *bazel.Label
- Srcs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- Python_version *string
- Imports bazel.StringListAttribute
- }
- func pythonBinaryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
- // TODO(b/182306917): this doesn't fully handle all nested props versioned
- // by the python version, which would have been handled by the version split
- // mutator. This is sufficient for very simple python_binary_host modules
- // under Bionic.
- py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, false)
- py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
- var python_version *string
- if py3Enabled && py2Enabled {
- panic(fmt.Errorf(
- "error for '%s' module: bp2build's python_binary_host converter does not support "+
- "converting a module that is enabled for both Python 2 and 3 at the same time.", m.Name()))
- } else if py2Enabled {
- python_version = &pyVersion2
- } else {
- // do nothing, since python_version defaults to PY3.
- }
- baseAttrs := m.makeArchVariantBaseAttributes(ctx)
- attrs := &bazelPythonBinaryAttributes{
- Main: nil,
- Srcs: baseAttrs.Srcs,
- Deps: baseAttrs.Deps,
- Python_version: python_version,
- Imports: baseAttrs.Imports,
- }
- for _, propIntf := range m.GetProperties() {
- if props, ok := propIntf.(*BinaryProperties); ok {
- // main is optional.
- if props.Main != nil {
- main := android.BazelLabelForModuleSrcSingle(ctx, *props.Main)
- attrs.Main = &main
- break
- }
- }
- }
- props := bazel.BazelTargetModuleProperties{
- // Use the native py_binary rule.
- Rule_class: "py_binary",
- }
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: m.Name(),
- Data: baseAttrs.Data,
- }, attrs)
- }
- 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 `android:"arch_variant"`
- // 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 binaryDecorator struct {
- binaryProperties BinaryProperties
- *pythonInstaller
- }
- type IntermPathProvider interface {
- IntermPathForModuleOut() android.OptionalPath
- }
- func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
- module := newModule(hod, android.MultilibFirst)
- decorator := &binaryDecorator{pythonInstaller: NewPythonInstaller("bin", "")}
- module.bootstrapper = decorator
- module.installer = decorator
- return module, decorator
- }
- func PythonBinaryHostFactory() android.Module {
- module, _ := NewBinary(android.HostSupported)
- android.InitBazelModule(module)
- return module.init()
- }
- func (binary *binaryDecorator) autorun() bool {
- return BoolDefault(binary.binaryProperties.Autorun, true)
- }
- func (binary *binaryDecorator) bootstrapperProps() []interface{} {
- return []interface{}{&binary.binaryProperties}
- }
- func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actualVersion string,
- embeddedLauncher bool, srcsPathMappings []pathMapping, srcsZip android.Path,
- depsSrcsZips android.Paths) android.OptionalPath {
- main := ""
- if binary.autorun() {
- main = binary.getPyMainFile(ctx, 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()
- }
- })
- }
- binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
- binary.getHostInterpreterName(ctx, actualVersion),
- main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...))
- return android.OptionalPathForPath(binFile)
- }
- // get host interpreter name.
- func (binary *binaryDecorator) 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 (binary *binaryDecorator) getPyMainFile(ctx android.ModuleContext,
- srcsPathMappings []pathMapping) string {
- var main string
- if String(binary.binaryProperties.Main) == "" {
- main = ctx.ModuleName() + pyExt
- } else {
- main = String(binary.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 (binary *binaryDecorator) getStem(ctx android.ModuleContext) string {
- stem := ctx.ModuleName()
- if String(binary.binaryProperties.Stem) != "" {
- stem = String(binary.binaryProperties.Stem)
- }
- return stem + String(binary.binaryProperties.Suffix)
- }
|