blob: 1c2b5552abd09f4c580116e6ee8972ab18d38c05 [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}
31
Paul Duffind0890452021-03-17 21:57:08 +000032func registerPythonBinaryComponents(ctx android.RegistrationContext) {
33 ctx.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
34}
35
Jingwen Chen13b9b422021-03-08 07:32:28 -050036type bazelPythonBinaryAttributes struct {
Wei Li7d8f6182022-10-11 14:38:16 -070037 Main *bazel.Label
Jingwen Chen07027912021-03-15 06:02:43 -040038 Srcs bazel.LabelListAttribute
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux560cb662021-08-26 20:13:29 +000039 Deps bazel.LabelListAttribute
Liz Kammer46fb7ab2021-12-01 10:09:34 -050040 Python_version *string
Cole Faust01243362022-06-02 12:11:12 -070041 Imports bazel.StringListAttribute
Jingwen Chen13b9b422021-03-08 07:32:28 -050042}
43
Liz Kammerbe46fcc2021-11-01 15:32:43 -040044func pythonBinaryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
Jingwen Chen13b9b422021-03-08 07:32:28 -050045 // TODO(b/182306917): this doesn't fully handle all nested props versioned
46 // by the python version, which would have been handled by the version split
47 // mutator. This is sufficient for very simple python_binary_host modules
48 // under Bionic.
49 py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, false)
50 py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
Liz Kammer46fb7ab2021-12-01 10:09:34 -050051 var python_version *string
Jingwen Chen13b9b422021-03-08 07:32:28 -050052 if py3Enabled && py2Enabled {
53 panic(fmt.Errorf(
54 "error for '%s' module: bp2build's python_binary_host converter does not support "+
55 "converting a module that is enabled for both Python 2 and 3 at the same time.", m.Name()))
56 } else if py2Enabled {
Liz Kammer46fb7ab2021-12-01 10:09:34 -050057 python_version = &pyVersion2
Jingwen Chen13b9b422021-03-08 07:32:28 -050058 } else {
59 // do nothing, since python_version defaults to PY3.
60 }
61
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux19d399d2021-09-17 20:30:21 +000062 baseAttrs := m.makeArchVariantBaseAttributes(ctx)
Jingwen Chen13b9b422021-03-08 07:32:28 -050063 attrs := &bazelPythonBinaryAttributes{
Wei Li7d8f6182022-10-11 14:38:16 -070064 Main: nil,
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux19d399d2021-09-17 20:30:21 +000065 Srcs: baseAttrs.Srcs,
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux19d399d2021-09-17 20:30:21 +000066 Deps: baseAttrs.Deps,
Jingwen Chen13b9b422021-03-08 07:32:28 -050067 Python_version: python_version,
Cole Faust01243362022-06-02 12:11:12 -070068 Imports: baseAttrs.Imports,
Jingwen Chen13b9b422021-03-08 07:32:28 -050069 }
70
Wei Li7d8f6182022-10-11 14:38:16 -070071 for _, propIntf := range m.GetProperties() {
72 if props, ok := propIntf.(*BinaryProperties); ok {
73 // main is optional.
74 if props.Main != nil {
75 main := android.BazelLabelForModuleSrcSingle(ctx, *props.Main)
76 attrs.Main = &main
77 break
78 }
79 }
80 }
81
Jingwen Chen13b9b422021-03-08 07:32:28 -050082 props := bazel.BazelTargetModuleProperties{
83 // Use the native py_binary rule.
84 Rule_class: "py_binary",
85 }
86
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux447f6c92021-08-31 20:30:36 +000087 ctx.CreateBazelTargetModule(props, android.CommonAttributes{
88 Name: m.Name(),
89 Data: baseAttrs.Data,
90 }, attrs)
Nan Zhangdb0b9a32017-02-27 10:12:13 -080091}
92
Nan Zhangd4e641b2017-07-12 12:55:28 -070093type BinaryProperties struct {
Nan Zhangdb0b9a32017-02-27 10:12:13 -080094 // the name of the source file that is the main entry point of the program.
95 // this file must also be listed in srcs.
96 // If left unspecified, module name is used instead.
97 // If name doesn’t match any filename in srcs, main must be specified.
Nan Zhangea568a42017-11-08 21:20:04 -080098 Main *string `android:"arch_variant"`
Nan Zhangdb0b9a32017-02-27 10:12:13 -080099
100 // set the name of the output binary.
Nan Zhangea568a42017-11-08 21:20:04 -0800101 Stem *string `android:"arch_variant"`
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800102
103 // append to the name of the output binary.
Nan Zhangea568a42017-11-08 21:20:04 -0800104 Suffix *string `android:"arch_variant"`
Nan Zhangc9c6cb72017-11-03 16:54:05 -0700105
106 // list of compatibility suites (for example "cts", "vts") that the module should be
107 // installed into.
108 Test_suites []string `android:"arch_variant"`
Dan Willemsen6ca390f2019-02-14 23:17:08 -0800109
110 // whether to use `main` when starting the executable. The default is true, when set to
111 // false it will act much like the normal `python` executable, but with the sources and
112 // libraries automatically included in the PYTHONPATH.
113 Autorun *bool `android:"arch_variant"`
Dan Shi6ffaaa82019-09-26 11:41:36 -0700114
115 // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
116 // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
117 // explicitly.
118 Auto_gen_config *bool
Cole Faustaf4b13d2022-09-14 15:25:15 -0700119
120 // Currently, both the root of the zipfile and all the directories 1 level
121 // below that are added to the python path. When this flag is set to true,
122 // only the root of the zipfile will be added to the python path. This flag
123 // will be removed after all the python modules in the tree have been updated
124 // to support it. When using embedded_launcher: true, this is already the
125 // behavior. The default is currently false.
126 Dont_add_top_level_directories_to_path *bool
Cole Fausteb3a9002022-09-22 18:25:09 -0700127
128 // Setting this to true will mimic Python 3.11+'s PYTHON_SAFE_PATH environment
129 // variable or -P flag, even on older python versions. This is a temporary
130 // flag while modules are changed to support it, eventually true will be the
131 // default and the flag will be removed. The default is currently false. It
132 // is only applicable when embedded_launcher is false, when embedded_launcher
133 // is true this is already implied.
134 Dont_add_entrypoint_folder_to_path *bool
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800135}
136
Nan Zhangd4e641b2017-07-12 12:55:28 -0700137type binaryDecorator struct {
138 binaryProperties BinaryProperties
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800139
Nan Zhangd9ec5e72017-12-01 20:00:31 +0000140 *pythonInstaller
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800141}
142
Nan Zhangd4e641b2017-07-12 12:55:28 -0700143type IntermPathProvider interface {
144 IntermPathForModuleOut() android.OptionalPath
Nan Zhang5323f8e2017-05-10 13:37:54 -0700145}
146
Nan Zhangd4e641b2017-07-12 12:55:28 -0700147func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
148 module := newModule(hod, android.MultilibFirst)
Rupert Shuttleworthffc4cc42021-11-03 09:07:26 +0000149 decorator := &binaryDecorator{pythonInstaller: NewPythonInstaller("bin", "")}
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800150
Nan Zhangd4e641b2017-07-12 12:55:28 -0700151 module.bootstrapper = decorator
152 module.installer = decorator
Nan Zhang5323f8e2017-05-10 13:37:54 -0700153
Nan Zhangd4e641b2017-07-12 12:55:28 -0700154 return module, decorator
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800155}
156
Nan Zhangd4e641b2017-07-12 12:55:28 -0700157func PythonBinaryHostFactory() android.Module {
Jiyong Park1613e552020-09-14 19:43:17 +0900158 module, _ := NewBinary(android.HostSupported)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800159
Jingwen Chen13b9b422021-03-08 07:32:28 -0500160 android.InitBazelModule(module)
161
Liz Kammerd737d022020-11-16 15:42:51 -0800162 return module.init()
Nan Zhangd4e641b2017-07-12 12:55:28 -0700163}
164
Dan Willemsen6ca390f2019-02-14 23:17:08 -0800165func (binary *binaryDecorator) autorun() bool {
166 return BoolDefault(binary.binaryProperties.Autorun, true)
167}
168
Nan Zhangd4e641b2017-07-12 12:55:28 -0700169func (binary *binaryDecorator) bootstrapperProps() []interface{} {
170 return []interface{}{&binary.binaryProperties}
171}
172
Nan Zhang1db85402017-12-18 13:20:23 -0800173func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actualVersion string,
174 embeddedLauncher bool, srcsPathMappings []pathMapping, srcsZip android.Path,
175 depsSrcsZips android.Paths) android.OptionalPath {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800176
Dan Willemsen6ca390f2019-02-14 23:17:08 -0800177 main := ""
178 if binary.autorun() {
179 main = binary.getPyMainFile(ctx, srcsPathMappings)
180 }
Nan Zhangd4e641b2017-07-12 12:55:28 -0700181
Nan Zhangcba97e62018-09-26 15:14:10 -0700182 var launcherPath android.OptionalPath
Nan Zhang1db85402017-12-18 13:20:23 -0800183 if embeddedLauncher {
Colin Crossee6143c2017-12-30 17:54:27 -0800184 ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) {
Nan Zhangd4e641b2017-07-12 12:55:28 -0700185 if provider, ok := m.(IntermPathProvider); ok {
Nan Zhangcba97e62018-09-26 15:14:10 -0700186 if launcherPath.Valid() {
Nan Zhangd4e641b2017-07-12 12:55:28 -0700187 panic(fmt.Errorf("launcher path was found before: %q",
Nan Zhang1db85402017-12-18 13:20:23 -0800188 launcherPath))
Nan Zhangd4e641b2017-07-12 12:55:28 -0700189 }
Nan Zhangcba97e62018-09-26 15:14:10 -0700190 launcherPath = provider.IntermPathForModuleOut()
Nan Zhangd4e641b2017-07-12 12:55:28 -0700191 }
192 })
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800193 }
194
Lais Andrade4d5cc702022-10-07 10:09:09 +0000195 addTopDirectoriesToPath := !proptools.BoolDefault(binary.binaryProperties.Dont_add_top_level_directories_to_path, false)
196 dontAddEntrypointFolderToPath := proptools.BoolDefault(binary.binaryProperties.Dont_add_entrypoint_folder_to_path, false)
Cole Faustaf4b13d2022-09-14 15:25:15 -0700197
Nan Zhang1db85402017-12-18 13:20:23 -0800198 binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
199 binary.getHostInterpreterName(ctx, actualVersion),
Cole Faustaf4b13d2022-09-14 15:25:15 -0700200 main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...),
Cole Fausteb3a9002022-09-22 18:25:09 -0700201 addTopDirectoriesToPath, dontAddEntrypointFolderToPath)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800202
Nan Zhang5323f8e2017-05-10 13:37:54 -0700203 return android.OptionalPathForPath(binFile)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800204}
205
Nan Zhangd4e641b2017-07-12 12:55:28 -0700206// get host interpreter name.
207func (binary *binaryDecorator) getHostInterpreterName(ctx android.ModuleContext,
Nan Zhang1db85402017-12-18 13:20:23 -0800208 actualVersion string) string {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800209 var interp string
Nan Zhang1db85402017-12-18 13:20:23 -0800210 switch actualVersion {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800211 case pyVersion2:
Dan Willemsen7d1681a2017-09-25 13:47:40 -0700212 interp = "python2.7"
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800213 case pyVersion3:
214 interp = "python3"
215 default:
216 panic(fmt.Errorf("unknown Python actualVersion: %q for module: %q.",
Nan Zhang1db85402017-12-18 13:20:23 -0800217 actualVersion, ctx.ModuleName()))
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800218 }
219
220 return interp
221}
222
223// find main program path within runfiles tree.
Nan Zhangd4e641b2017-07-12 12:55:28 -0700224func (binary *binaryDecorator) getPyMainFile(ctx android.ModuleContext,
225 srcsPathMappings []pathMapping) string {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800226 var main string
Nan Zhangea568a42017-11-08 21:20:04 -0800227 if String(binary.binaryProperties.Main) == "" {
Nan Zhangd4e641b2017-07-12 12:55:28 -0700228 main = ctx.ModuleName() + pyExt
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800229 } else {
Nan Zhangea568a42017-11-08 21:20:04 -0800230 main = String(binary.binaryProperties.Main)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800231 }
232
Nan Zhangd4e641b2017-07-12 12:55:28 -0700233 for _, path := range srcsPathMappings {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800234 if main == path.src.Rel() {
235 return path.dest
236 }
237 }
238 ctx.PropertyErrorf("main", "%q is not listed in srcs.", main)
239
240 return ""
241}
242
Nan Zhangd4e641b2017-07-12 12:55:28 -0700243func (binary *binaryDecorator) getStem(ctx android.ModuleContext) string {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800244 stem := ctx.ModuleName()
Nan Zhangea568a42017-11-08 21:20:04 -0800245 if String(binary.binaryProperties.Stem) != "" {
246 stem = String(binary.binaryProperties.Stem)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800247 }
248
Nan Zhangea568a42017-11-08 21:20:04 -0800249 return stem + String(binary.binaryProperties.Suffix)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800250}