blob: af02de63d06289bb1684a9d679162dd7a1048d2c [file] [log] [blame]
Nan Zhangdb0b9a32017-02-27 10:12:13 -08001// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package python
16
17// This file contains the module types for building Python binary.
18
19import (
20 "fmt"
Nan Zhangdb0b9a32017-02-27 10:12:13 -080021
Nan Zhangdb0b9a32017-02-27 10:12:13 -080022 "android/soong/android"
Jingwen Chen13b9b422021-03-08 07:32:28 -050023 "android/soong/bazel"
24
25 "github.com/google/blueprint/proptools"
Nan Zhangdb0b9a32017-02-27 10:12:13 -080026)
27
28func init() {
Paul Duffind0890452021-03-17 21:57:08 +000029 registerPythonBinaryComponents(android.InitRegistrationContext)
Jingwen Chen13b9b422021-03-08 07:32:28 -050030 android.RegisterBp2BuildMutator("python_binary_host", PythonBinaryBp2Build)
31}
32
Paul Duffind0890452021-03-17 21:57:08 +000033func registerPythonBinaryComponents(ctx android.RegistrationContext) {
34 ctx.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
35}
36
Jingwen Chen13b9b422021-03-08 07:32:28 -050037type bazelPythonBinaryAttributes struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -050038 Main *string
Jingwen Chen07027912021-03-15 06:02:43 -040039 Srcs bazel.LabelListAttribute
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux560cb662021-08-26 20:13:29 +000040 Deps bazel.LabelListAttribute
Liz Kammer46fb7ab2021-12-01 10:09:34 -050041 Python_version *string
Jingwen Chen13b9b422021-03-08 07:32:28 -050042}
43
Jingwen Chen13b9b422021-03-08 07:32:28 -050044func PythonBinaryBp2Build(ctx android.TopDownMutatorContext) {
45 m, ok := ctx.Module().(*Module)
Jingwen Chen12b4c272021-03-10 02:05:59 -050046 if !ok || !m.ConvertWithBp2build(ctx) {
Jingwen Chen13b9b422021-03-08 07:32:28 -050047 return
48 }
49
50 // a Module can be something other than a python_binary_host
51 if ctx.ModuleType() != "python_binary_host" {
52 return
53 }
54
Liz Kammer46fb7ab2021-12-01 10:09:34 -050055 var main *string
Jingwen Chen13b9b422021-03-08 07:32:28 -050056 for _, propIntf := range m.GetProperties() {
57 if props, ok := propIntf.(*BinaryProperties); ok {
58 // main is optional.
59 if props.Main != nil {
Liz Kammer46fb7ab2021-12-01 10:09:34 -050060 main = props.Main
Jingwen Chen13b9b422021-03-08 07:32:28 -050061 break
62 }
63 }
64 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux19d399d2021-09-17 20:30:21 +000065
Jingwen Chen13b9b422021-03-08 07:32:28 -050066 // TODO(b/182306917): this doesn't fully handle all nested props versioned
67 // by the python version, which would have been handled by the version split
68 // mutator. This is sufficient for very simple python_binary_host modules
69 // under Bionic.
70 py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, false)
71 py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
Liz Kammer46fb7ab2021-12-01 10:09:34 -050072 var python_version *string
Jingwen Chen13b9b422021-03-08 07:32:28 -050073 if py3Enabled && py2Enabled {
74 panic(fmt.Errorf(
75 "error for '%s' module: bp2build's python_binary_host converter does not support "+
76 "converting a module that is enabled for both Python 2 and 3 at the same time.", m.Name()))
77 } else if py2Enabled {
Liz Kammer46fb7ab2021-12-01 10:09:34 -050078 python_version = &pyVersion2
Jingwen Chen13b9b422021-03-08 07:32:28 -050079 } else {
80 // do nothing, since python_version defaults to PY3.
81 }
82
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux19d399d2021-09-17 20:30:21 +000083 baseAttrs := m.makeArchVariantBaseAttributes(ctx)
Jingwen Chen13b9b422021-03-08 07:32:28 -050084 attrs := &bazelPythonBinaryAttributes{
85 Main: main,
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux19d399d2021-09-17 20:30:21 +000086 Srcs: baseAttrs.Srcs,
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux19d399d2021-09-17 20:30:21 +000087 Deps: baseAttrs.Deps,
Jingwen Chen13b9b422021-03-08 07:32:28 -050088 Python_version: python_version,
89 }
90
91 props := bazel.BazelTargetModuleProperties{
92 // Use the native py_binary rule.
93 Rule_class: "py_binary",
94 }
95
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux447f6c92021-08-31 20:30:36 +000096 ctx.CreateBazelTargetModule(props, android.CommonAttributes{
97 Name: m.Name(),
98 Data: baseAttrs.Data,
99 }, attrs)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800100}
101
Nan Zhangd4e641b2017-07-12 12:55:28 -0700102type BinaryProperties struct {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800103 // the name of the source file that is the main entry point of the program.
104 // this file must also be listed in srcs.
105 // If left unspecified, module name is used instead.
106 // If name doesn’t match any filename in srcs, main must be specified.
Nan Zhangea568a42017-11-08 21:20:04 -0800107 Main *string `android:"arch_variant"`
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800108
109 // set the name of the output binary.
Nan Zhangea568a42017-11-08 21:20:04 -0800110 Stem *string `android:"arch_variant"`
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800111
112 // append to the name of the output binary.
Nan Zhangea568a42017-11-08 21:20:04 -0800113 Suffix *string `android:"arch_variant"`
Nan Zhangc9c6cb72017-11-03 16:54:05 -0700114
115 // list of compatibility suites (for example "cts", "vts") that the module should be
116 // installed into.
117 Test_suites []string `android:"arch_variant"`
Dan Willemsen6ca390f2019-02-14 23:17:08 -0800118
119 // whether to use `main` when starting the executable. The default is true, when set to
120 // false it will act much like the normal `python` executable, but with the sources and
121 // libraries automatically included in the PYTHONPATH.
122 Autorun *bool `android:"arch_variant"`
Dan Shi6ffaaa82019-09-26 11:41:36 -0700123
124 // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
125 // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
126 // explicitly.
127 Auto_gen_config *bool
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800128}
129
Nan Zhangd4e641b2017-07-12 12:55:28 -0700130type binaryDecorator struct {
131 binaryProperties BinaryProperties
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800132
Nan Zhangd9ec5e72017-12-01 20:00:31 +0000133 *pythonInstaller
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800134}
135
Nan Zhangd4e641b2017-07-12 12:55:28 -0700136type IntermPathProvider interface {
137 IntermPathForModuleOut() android.OptionalPath
Nan Zhang5323f8e2017-05-10 13:37:54 -0700138}
139
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800140var (
Liz Kammerdd849a82020-06-12 16:38:45 -0700141 StubTemplateHost = "build/soong/python/scripts/stub_template_host.txt"
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800142)
143
Nan Zhangd4e641b2017-07-12 12:55:28 -0700144func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
145 module := newModule(hod, android.MultilibFirst)
Rupert Shuttleworthffc4cc42021-11-03 09:07:26 +0000146 decorator := &binaryDecorator{pythonInstaller: NewPythonInstaller("bin", "")}
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800147
Nan Zhangd4e641b2017-07-12 12:55:28 -0700148 module.bootstrapper = decorator
149 module.installer = decorator
Nan Zhang5323f8e2017-05-10 13:37:54 -0700150
Nan Zhangd4e641b2017-07-12 12:55:28 -0700151 return module, decorator
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800152}
153
Nan Zhangd4e641b2017-07-12 12:55:28 -0700154func PythonBinaryHostFactory() android.Module {
Jiyong Park1613e552020-09-14 19:43:17 +0900155 module, _ := NewBinary(android.HostSupported)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800156
Jingwen Chen13b9b422021-03-08 07:32:28 -0500157 android.InitBazelModule(module)
158
Liz Kammerd737d022020-11-16 15:42:51 -0800159 return module.init()
Nan Zhangd4e641b2017-07-12 12:55:28 -0700160}
161
Dan Willemsen6ca390f2019-02-14 23:17:08 -0800162func (binary *binaryDecorator) autorun() bool {
163 return BoolDefault(binary.binaryProperties.Autorun, true)
164}
165
Nan Zhangd4e641b2017-07-12 12:55:28 -0700166func (binary *binaryDecorator) bootstrapperProps() []interface{} {
167 return []interface{}{&binary.binaryProperties}
168}
169
Nan Zhang1db85402017-12-18 13:20:23 -0800170func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actualVersion string,
171 embeddedLauncher bool, srcsPathMappings []pathMapping, srcsZip android.Path,
172 depsSrcsZips android.Paths) android.OptionalPath {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800173
Dan Willemsen6ca390f2019-02-14 23:17:08 -0800174 main := ""
175 if binary.autorun() {
176 main = binary.getPyMainFile(ctx, srcsPathMappings)
177 }
Nan Zhangd4e641b2017-07-12 12:55:28 -0700178
Nan Zhangcba97e62018-09-26 15:14:10 -0700179 var launcherPath android.OptionalPath
Nan Zhang1db85402017-12-18 13:20:23 -0800180 if embeddedLauncher {
Colin Crossee6143c2017-12-30 17:54:27 -0800181 ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) {
Nan Zhangd4e641b2017-07-12 12:55:28 -0700182 if provider, ok := m.(IntermPathProvider); ok {
Nan Zhangcba97e62018-09-26 15:14:10 -0700183 if launcherPath.Valid() {
Nan Zhangd4e641b2017-07-12 12:55:28 -0700184 panic(fmt.Errorf("launcher path was found before: %q",
Nan Zhang1db85402017-12-18 13:20:23 -0800185 launcherPath))
Nan Zhangd4e641b2017-07-12 12:55:28 -0700186 }
Nan Zhangcba97e62018-09-26 15:14:10 -0700187 launcherPath = provider.IntermPathForModuleOut()
Nan Zhangd4e641b2017-07-12 12:55:28 -0700188 }
189 })
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800190 }
191
Nan Zhang1db85402017-12-18 13:20:23 -0800192 binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
193 binary.getHostInterpreterName(ctx, actualVersion),
194 main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...))
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800195
Nan Zhang5323f8e2017-05-10 13:37:54 -0700196 return android.OptionalPathForPath(binFile)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800197}
198
Nan Zhangd4e641b2017-07-12 12:55:28 -0700199// get host interpreter name.
200func (binary *binaryDecorator) getHostInterpreterName(ctx android.ModuleContext,
Nan Zhang1db85402017-12-18 13:20:23 -0800201 actualVersion string) string {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800202 var interp string
Nan Zhang1db85402017-12-18 13:20:23 -0800203 switch actualVersion {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800204 case pyVersion2:
Dan Willemsen7d1681a2017-09-25 13:47:40 -0700205 interp = "python2.7"
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800206 case pyVersion3:
207 interp = "python3"
208 default:
209 panic(fmt.Errorf("unknown Python actualVersion: %q for module: %q.",
Nan Zhang1db85402017-12-18 13:20:23 -0800210 actualVersion, ctx.ModuleName()))
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800211 }
212
213 return interp
214}
215
216// find main program path within runfiles tree.
Nan Zhangd4e641b2017-07-12 12:55:28 -0700217func (binary *binaryDecorator) getPyMainFile(ctx android.ModuleContext,
218 srcsPathMappings []pathMapping) string {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800219 var main string
Nan Zhangea568a42017-11-08 21:20:04 -0800220 if String(binary.binaryProperties.Main) == "" {
Nan Zhangd4e641b2017-07-12 12:55:28 -0700221 main = ctx.ModuleName() + pyExt
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800222 } else {
Nan Zhangea568a42017-11-08 21:20:04 -0800223 main = String(binary.binaryProperties.Main)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800224 }
225
Nan Zhangd4e641b2017-07-12 12:55:28 -0700226 for _, path := range srcsPathMappings {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800227 if main == path.src.Rel() {
228 return path.dest
229 }
230 }
231 ctx.PropertyErrorf("main", "%q is not listed in srcs.", main)
232
233 return ""
234}
235
Nan Zhangd4e641b2017-07-12 12:55:28 -0700236func (binary *binaryDecorator) getStem(ctx android.ModuleContext) string {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800237 stem := ctx.ModuleName()
Nan Zhangea568a42017-11-08 21:20:04 -0800238 if String(binary.binaryProperties.Stem) != "" {
239 stem = String(binary.binaryProperties.Stem)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800240 }
241
Nan Zhangea568a42017-11-08 21:20:04 -0800242 return stem + String(binary.binaryProperties.Suffix)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800243}