| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 1 | // 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 |  | 
 | 15 | package python | 
 | 16 |  | 
 | 17 | // This file contains the module types for building Python binary. | 
 | 18 |  | 
 | 19 | import ( | 
 | 20 | 	"fmt" | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 21 |  | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 22 | 	"android/soong/android" | 
| Jingwen Chen | 13b9b42 | 2021-03-08 07:32:28 -0500 | [diff] [blame] | 23 | 	"android/soong/bazel" | 
 | 24 |  | 
 | 25 | 	"github.com/google/blueprint/proptools" | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 26 | ) | 
 | 27 |  | 
 | 28 | func init() { | 
| Paul Duffin | d089045 | 2021-03-17 21:57:08 +0000 | [diff] [blame] | 29 | 	registerPythonBinaryComponents(android.InitRegistrationContext) | 
| Jingwen Chen | 13b9b42 | 2021-03-08 07:32:28 -0500 | [diff] [blame] | 30 | 	android.RegisterBp2BuildMutator("python_binary_host", PythonBinaryBp2Build) | 
 | 31 | } | 
 | 32 |  | 
| Paul Duffin | d089045 | 2021-03-17 21:57:08 +0000 | [diff] [blame] | 33 | func registerPythonBinaryComponents(ctx android.RegistrationContext) { | 
 | 34 | 	ctx.RegisterModuleType("python_binary_host", PythonBinaryHostFactory) | 
 | 35 | } | 
 | 36 |  | 
| Jingwen Chen | 13b9b42 | 2021-03-08 07:32:28 -0500 | [diff] [blame] | 37 | type bazelPythonBinaryAttributes struct { | 
 | 38 | 	Main           string | 
| Jingwen Chen | 0702791 | 2021-03-15 06:02:43 -0400 | [diff] [blame] | 39 | 	Srcs           bazel.LabelListAttribute | 
 | 40 | 	Data           bazel.LabelListAttribute | 
| Jingwen Chen | 13b9b42 | 2021-03-08 07:32:28 -0500 | [diff] [blame] | 41 | 	Python_version string | 
 | 42 | } | 
 | 43 |  | 
 | 44 | type bazelPythonBinary struct { | 
 | 45 | 	android.BazelTargetModuleBase | 
 | 46 | 	bazelPythonBinaryAttributes | 
 | 47 | } | 
 | 48 |  | 
 | 49 | func BazelPythonBinaryFactory() android.Module { | 
 | 50 | 	module := &bazelPythonBinary{} | 
 | 51 | 	module.AddProperties(&module.bazelPythonBinaryAttributes) | 
 | 52 | 	android.InitBazelTargetModule(module) | 
 | 53 | 	return module | 
 | 54 | } | 
 | 55 |  | 
 | 56 | func (m *bazelPythonBinary) Name() string { | 
 | 57 | 	return m.BaseModuleName() | 
 | 58 | } | 
 | 59 |  | 
 | 60 | func (m *bazelPythonBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {} | 
 | 61 |  | 
 | 62 | func PythonBinaryBp2Build(ctx android.TopDownMutatorContext) { | 
 | 63 | 	m, ok := ctx.Module().(*Module) | 
| Jingwen Chen | 12b4c27 | 2021-03-10 02:05:59 -0500 | [diff] [blame] | 64 | 	if !ok || !m.ConvertWithBp2build(ctx) { | 
| Jingwen Chen | 13b9b42 | 2021-03-08 07:32:28 -0500 | [diff] [blame] | 65 | 		return | 
 | 66 | 	} | 
 | 67 |  | 
 | 68 | 	// a Module can be something other than a python_binary_host | 
 | 69 | 	if ctx.ModuleType() != "python_binary_host" { | 
 | 70 | 		return | 
 | 71 | 	} | 
 | 72 |  | 
 | 73 | 	var main string | 
 | 74 | 	for _, propIntf := range m.GetProperties() { | 
 | 75 | 		if props, ok := propIntf.(*BinaryProperties); ok { | 
 | 76 | 			// main is optional. | 
 | 77 | 			if props.Main != nil { | 
 | 78 | 				main = *props.Main | 
 | 79 | 				break | 
 | 80 | 			} | 
 | 81 | 		} | 
 | 82 | 	} | 
 | 83 | 	// TODO(b/182306917): this doesn't fully handle all nested props versioned | 
 | 84 | 	// by the python version, which would have been handled by the version split | 
 | 85 | 	// mutator. This is sufficient for very simple python_binary_host modules | 
 | 86 | 	// under Bionic. | 
 | 87 | 	py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, false) | 
 | 88 | 	py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false) | 
 | 89 | 	var python_version string | 
 | 90 | 	if py3Enabled && py2Enabled { | 
 | 91 | 		panic(fmt.Errorf( | 
 | 92 | 			"error for '%s' module: bp2build's python_binary_host converter does not support "+ | 
 | 93 | 				"converting a module that is enabled for both Python 2 and 3 at the same time.", m.Name())) | 
 | 94 | 	} else if py2Enabled { | 
 | 95 | 		python_version = "PY2" | 
 | 96 | 	} else { | 
 | 97 | 		// do nothing, since python_version defaults to PY3. | 
 | 98 | 	} | 
 | 99 |  | 
| Jingwen Chen | 0702791 | 2021-03-15 06:02:43 -0400 | [diff] [blame] | 100 | 	srcs := android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs) | 
 | 101 | 	data := android.BazelLabelForModuleSrc(ctx, m.properties.Data) | 
 | 102 |  | 
| Jingwen Chen | 13b9b42 | 2021-03-08 07:32:28 -0500 | [diff] [blame] | 103 | 	attrs := &bazelPythonBinaryAttributes{ | 
 | 104 | 		Main:           main, | 
| Jingwen Chen | 0702791 | 2021-03-15 06:02:43 -0400 | [diff] [blame] | 105 | 		Srcs:           bazel.MakeLabelListAttribute(srcs), | 
 | 106 | 		Data:           bazel.MakeLabelListAttribute(data), | 
| Jingwen Chen | 13b9b42 | 2021-03-08 07:32:28 -0500 | [diff] [blame] | 107 | 		Python_version: python_version, | 
 | 108 | 	} | 
 | 109 |  | 
 | 110 | 	props := bazel.BazelTargetModuleProperties{ | 
 | 111 | 		// Use the native py_binary rule. | 
 | 112 | 		Rule_class: "py_binary", | 
 | 113 | 	} | 
 | 114 |  | 
 | 115 | 	ctx.CreateBazelTargetModule(BazelPythonBinaryFactory, m.Name(), props, attrs) | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 116 | } | 
 | 117 |  | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 118 | type BinaryProperties struct { | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 119 | 	// the name of the source file that is the main entry point of the program. | 
 | 120 | 	// this file must also be listed in srcs. | 
 | 121 | 	// If left unspecified, module name is used instead. | 
 | 122 | 	// If name doesn’t match any filename in srcs, main must be specified. | 
| Nan Zhang | ea568a4 | 2017-11-08 21:20:04 -0800 | [diff] [blame] | 123 | 	Main *string `android:"arch_variant"` | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 124 |  | 
 | 125 | 	// set the name of the output binary. | 
| Nan Zhang | ea568a4 | 2017-11-08 21:20:04 -0800 | [diff] [blame] | 126 | 	Stem *string `android:"arch_variant"` | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 127 |  | 
 | 128 | 	// append to the name of the output binary. | 
| Nan Zhang | ea568a4 | 2017-11-08 21:20:04 -0800 | [diff] [blame] | 129 | 	Suffix *string `android:"arch_variant"` | 
| Nan Zhang | c9c6cb7 | 2017-11-03 16:54:05 -0700 | [diff] [blame] | 130 |  | 
 | 131 | 	// list of compatibility suites (for example "cts", "vts") that the module should be | 
 | 132 | 	// installed into. | 
 | 133 | 	Test_suites []string `android:"arch_variant"` | 
| Dan Willemsen | 6ca390f | 2019-02-14 23:17:08 -0800 | [diff] [blame] | 134 |  | 
 | 135 | 	// whether to use `main` when starting the executable. The default is true, when set to | 
 | 136 | 	// false it will act much like the normal `python` executable, but with the sources and | 
 | 137 | 	// libraries automatically included in the PYTHONPATH. | 
 | 138 | 	Autorun *bool `android:"arch_variant"` | 
| Dan Shi | 6ffaaa8 | 2019-09-26 11:41:36 -0700 | [diff] [blame] | 139 |  | 
 | 140 | 	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml | 
 | 141 | 	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true | 
 | 142 | 	// explicitly. | 
 | 143 | 	Auto_gen_config *bool | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 144 | } | 
 | 145 |  | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 146 | type binaryDecorator struct { | 
 | 147 | 	binaryProperties BinaryProperties | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 148 |  | 
| Nan Zhang | d9ec5e7 | 2017-12-01 20:00:31 +0000 | [diff] [blame] | 149 | 	*pythonInstaller | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 150 | } | 
 | 151 |  | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 152 | type IntermPathProvider interface { | 
 | 153 | 	IntermPathForModuleOut() android.OptionalPath | 
| Nan Zhang | 5323f8e | 2017-05-10 13:37:54 -0700 | [diff] [blame] | 154 | } | 
 | 155 |  | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 156 | var ( | 
| Liz Kammer | dd849a8 | 2020-06-12 16:38:45 -0700 | [diff] [blame] | 157 | 	StubTemplateHost = "build/soong/python/scripts/stub_template_host.txt" | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 158 | ) | 
 | 159 |  | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 160 | func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) { | 
 | 161 | 	module := newModule(hod, android.MultilibFirst) | 
| Nan Zhang | d9ec5e7 | 2017-12-01 20:00:31 +0000 | [diff] [blame] | 162 | 	decorator := &binaryDecorator{pythonInstaller: NewPythonInstaller("bin", "")} | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 163 |  | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 164 | 	module.bootstrapper = decorator | 
 | 165 | 	module.installer = decorator | 
| Nan Zhang | 5323f8e | 2017-05-10 13:37:54 -0700 | [diff] [blame] | 166 |  | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 167 | 	return module, decorator | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 168 | } | 
 | 169 |  | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 170 | func PythonBinaryHostFactory() android.Module { | 
| Jiyong Park | 1613e55 | 2020-09-14 19:43:17 +0900 | [diff] [blame] | 171 | 	module, _ := NewBinary(android.HostSupported) | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 172 |  | 
| Jingwen Chen | 13b9b42 | 2021-03-08 07:32:28 -0500 | [diff] [blame] | 173 | 	android.InitBazelModule(module) | 
 | 174 |  | 
| Liz Kammer | d737d02 | 2020-11-16 15:42:51 -0800 | [diff] [blame] | 175 | 	return module.init() | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 176 | } | 
 | 177 |  | 
| Dan Willemsen | 6ca390f | 2019-02-14 23:17:08 -0800 | [diff] [blame] | 178 | func (binary *binaryDecorator) autorun() bool { | 
 | 179 | 	return BoolDefault(binary.binaryProperties.Autorun, true) | 
 | 180 | } | 
 | 181 |  | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 182 | func (binary *binaryDecorator) bootstrapperProps() []interface{} { | 
 | 183 | 	return []interface{}{&binary.binaryProperties} | 
 | 184 | } | 
 | 185 |  | 
| Nan Zhang | 1db8540 | 2017-12-18 13:20:23 -0800 | [diff] [blame] | 186 | func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actualVersion string, | 
 | 187 | 	embeddedLauncher bool, srcsPathMappings []pathMapping, srcsZip android.Path, | 
 | 188 | 	depsSrcsZips android.Paths) android.OptionalPath { | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 189 |  | 
| Dan Willemsen | 6ca390f | 2019-02-14 23:17:08 -0800 | [diff] [blame] | 190 | 	main := "" | 
 | 191 | 	if binary.autorun() { | 
 | 192 | 		main = binary.getPyMainFile(ctx, srcsPathMappings) | 
 | 193 | 	} | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 194 |  | 
| Nan Zhang | cba97e6 | 2018-09-26 15:14:10 -0700 | [diff] [blame] | 195 | 	var launcherPath android.OptionalPath | 
| Nan Zhang | 1db8540 | 2017-12-18 13:20:23 -0800 | [diff] [blame] | 196 | 	if embeddedLauncher { | 
| Colin Cross | ee6143c | 2017-12-30 17:54:27 -0800 | [diff] [blame] | 197 | 		ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) { | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 198 | 			if provider, ok := m.(IntermPathProvider); ok { | 
| Nan Zhang | cba97e6 | 2018-09-26 15:14:10 -0700 | [diff] [blame] | 199 | 				if launcherPath.Valid() { | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 200 | 					panic(fmt.Errorf("launcher path was found before: %q", | 
| Nan Zhang | 1db8540 | 2017-12-18 13:20:23 -0800 | [diff] [blame] | 201 | 						launcherPath)) | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 202 | 				} | 
| Nan Zhang | cba97e6 | 2018-09-26 15:14:10 -0700 | [diff] [blame] | 203 | 				launcherPath = provider.IntermPathForModuleOut() | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 204 | 			} | 
 | 205 | 		}) | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 206 | 	} | 
 | 207 |  | 
| Nan Zhang | 1db8540 | 2017-12-18 13:20:23 -0800 | [diff] [blame] | 208 | 	binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath, | 
 | 209 | 		binary.getHostInterpreterName(ctx, actualVersion), | 
 | 210 | 		main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...)) | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 211 |  | 
| Nan Zhang | 5323f8e | 2017-05-10 13:37:54 -0700 | [diff] [blame] | 212 | 	return android.OptionalPathForPath(binFile) | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 213 | } | 
 | 214 |  | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 215 | // get host interpreter name. | 
 | 216 | func (binary *binaryDecorator) getHostInterpreterName(ctx android.ModuleContext, | 
| Nan Zhang | 1db8540 | 2017-12-18 13:20:23 -0800 | [diff] [blame] | 217 | 	actualVersion string) string { | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 218 | 	var interp string | 
| Nan Zhang | 1db8540 | 2017-12-18 13:20:23 -0800 | [diff] [blame] | 219 | 	switch actualVersion { | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 220 | 	case pyVersion2: | 
| Dan Willemsen | 7d1681a | 2017-09-25 13:47:40 -0700 | [diff] [blame] | 221 | 		interp = "python2.7" | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 222 | 	case pyVersion3: | 
 | 223 | 		interp = "python3" | 
 | 224 | 	default: | 
 | 225 | 		panic(fmt.Errorf("unknown Python actualVersion: %q for module: %q.", | 
| Nan Zhang | 1db8540 | 2017-12-18 13:20:23 -0800 | [diff] [blame] | 226 | 			actualVersion, ctx.ModuleName())) | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 227 | 	} | 
 | 228 |  | 
 | 229 | 	return interp | 
 | 230 | } | 
 | 231 |  | 
 | 232 | // find main program path within runfiles tree. | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 233 | func (binary *binaryDecorator) getPyMainFile(ctx android.ModuleContext, | 
 | 234 | 	srcsPathMappings []pathMapping) string { | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 235 | 	var main string | 
| Nan Zhang | ea568a4 | 2017-11-08 21:20:04 -0800 | [diff] [blame] | 236 | 	if String(binary.binaryProperties.Main) == "" { | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 237 | 		main = ctx.ModuleName() + pyExt | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 238 | 	} else { | 
| Nan Zhang | ea568a4 | 2017-11-08 21:20:04 -0800 | [diff] [blame] | 239 | 		main = String(binary.binaryProperties.Main) | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 240 | 	} | 
 | 241 |  | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 242 | 	for _, path := range srcsPathMappings { | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 243 | 		if main == path.src.Rel() { | 
 | 244 | 			return path.dest | 
 | 245 | 		} | 
 | 246 | 	} | 
 | 247 | 	ctx.PropertyErrorf("main", "%q is not listed in srcs.", main) | 
 | 248 |  | 
 | 249 | 	return "" | 
 | 250 | } | 
 | 251 |  | 
| Nan Zhang | d4e641b | 2017-07-12 12:55:28 -0700 | [diff] [blame] | 252 | func (binary *binaryDecorator) getStem(ctx android.ModuleContext) string { | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 253 | 	stem := ctx.ModuleName() | 
| Nan Zhang | ea568a4 | 2017-11-08 21:20:04 -0800 | [diff] [blame] | 254 | 	if String(binary.binaryProperties.Stem) != "" { | 
 | 255 | 		stem = String(binary.binaryProperties.Stem) | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 256 | 	} | 
 | 257 |  | 
| Nan Zhang | ea568a4 | 2017-11-08 21:20:04 -0800 | [diff] [blame] | 258 | 	return stem + String(binary.binaryProperties.Suffix) | 
| Nan Zhang | db0b9a3 | 2017-02-27 10:12:13 -0800 | [diff] [blame] | 259 | } |