1*60517a1eSAndroid Build Coastguard Worker# Copyright 2022 The Bazel Authors. All rights reserved. 2*60517a1eSAndroid Build Coastguard Worker# 3*60517a1eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*60517a1eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*60517a1eSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*60517a1eSAndroid Build Coastguard Worker# 7*60517a1eSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*60517a1eSAndroid Build Coastguard Worker# 9*60517a1eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*60517a1eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*60517a1eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*60517a1eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*60517a1eSAndroid Build Coastguard Worker# limitations under the License. 14*60517a1eSAndroid Build Coastguard Worker"""Providers for Python rules.""" 15*60517a1eSAndroid Build Coastguard Worker 16*60517a1eSAndroid Build Coastguard Workerload("@rules_cc//cc:defs.bzl", "CcInfo") 17*60517a1eSAndroid Build Coastguard Workerload("//python/private:util.bzl", "IS_BAZEL_6_OR_HIGHER") 18*60517a1eSAndroid Build Coastguard Worker 19*60517a1eSAndroid Build Coastguard WorkerDEFAULT_STUB_SHEBANG = "#!/usr/bin/env python3" 20*60517a1eSAndroid Build Coastguard Worker 21*60517a1eSAndroid Build Coastguard WorkerDEFAULT_BOOTSTRAP_TEMPLATE = Label("//python/private:bootstrap_template") 22*60517a1eSAndroid Build Coastguard Worker 23*60517a1eSAndroid Build Coastguard Worker_PYTHON_VERSION_VALUES = ["PY2", "PY3"] 24*60517a1eSAndroid Build Coastguard Worker 25*60517a1eSAndroid Build Coastguard Worker# Helper to make the provider definitions not crash under Bazel 5.4: 26*60517a1eSAndroid Build Coastguard Worker# Bazel 5.4 doesn't support the `init` arg of `provider()`, so we have to 27*60517a1eSAndroid Build Coastguard Worker# not pass that when using Bazel 5.4. But, not passing the `init` arg 28*60517a1eSAndroid Build Coastguard Worker# changes the return value from a two-tuple to a single value, which then 29*60517a1eSAndroid Build Coastguard Worker# breaks Bazel 6+ code. 30*60517a1eSAndroid Build Coastguard Worker# This isn't actually used under Bazel 5.4, so just stub out the values 31*60517a1eSAndroid Build Coastguard Worker# to get past the loading phase. 32*60517a1eSAndroid Build Coastguard Workerdef _define_provider(doc, fields, **kwargs): 33*60517a1eSAndroid Build Coastguard Worker if not IS_BAZEL_6_OR_HIGHER: 34*60517a1eSAndroid Build Coastguard Worker return provider("Stub, not used", fields = []), None 35*60517a1eSAndroid Build Coastguard Worker return provider(doc = doc, fields = fields, **kwargs) 36*60517a1eSAndroid Build Coastguard Worker 37*60517a1eSAndroid Build Coastguard Workerdef _optional_int(value): 38*60517a1eSAndroid Build Coastguard Worker return int(value) if value != None else None 39*60517a1eSAndroid Build Coastguard Worker 40*60517a1eSAndroid Build Coastguard Workerdef interpreter_version_info_struct_from_dict(info_dict): 41*60517a1eSAndroid Build Coastguard Worker """Create a struct of interpreter version info from a dict from an attribute. 42*60517a1eSAndroid Build Coastguard Worker 43*60517a1eSAndroid Build Coastguard Worker Args: 44*60517a1eSAndroid Build Coastguard Worker info_dict: (dict | None) of version info fields. See interpreter_version_info 45*60517a1eSAndroid Build Coastguard Worker provider field docs. 46*60517a1eSAndroid Build Coastguard Worker 47*60517a1eSAndroid Build Coastguard Worker Returns: 48*60517a1eSAndroid Build Coastguard Worker struct of version info; see interpreter_version_info provider field docs. 49*60517a1eSAndroid Build Coastguard Worker """ 50*60517a1eSAndroid Build Coastguard Worker info_dict = dict(info_dict or {}) # Copy in case the original is frozen 51*60517a1eSAndroid Build Coastguard Worker if info_dict: 52*60517a1eSAndroid Build Coastguard Worker if not ("major" in info_dict and "minor" in info_dict): 53*60517a1eSAndroid Build Coastguard Worker fail("interpreter_version_info must have at least two keys, 'major' and 'minor'") 54*60517a1eSAndroid Build Coastguard Worker version_info_struct = struct( 55*60517a1eSAndroid Build Coastguard Worker major = _optional_int(info_dict.pop("major", None)), 56*60517a1eSAndroid Build Coastguard Worker minor = _optional_int(info_dict.pop("minor", None)), 57*60517a1eSAndroid Build Coastguard Worker micro = _optional_int(info_dict.pop("micro", None)), 58*60517a1eSAndroid Build Coastguard Worker releaselevel = str(info_dict.pop("releaselevel")) if "releaselevel" in info_dict else None, 59*60517a1eSAndroid Build Coastguard Worker serial = _optional_int(info_dict.pop("serial", None)), 60*60517a1eSAndroid Build Coastguard Worker ) 61*60517a1eSAndroid Build Coastguard Worker 62*60517a1eSAndroid Build Coastguard Worker if len(info_dict.keys()) > 0: 63*60517a1eSAndroid Build Coastguard Worker fail("unexpected keys {} in interpreter_version_info".format( 64*60517a1eSAndroid Build Coastguard Worker str(info_dict.keys()), 65*60517a1eSAndroid Build Coastguard Worker )) 66*60517a1eSAndroid Build Coastguard Worker 67*60517a1eSAndroid Build Coastguard Worker return version_info_struct 68*60517a1eSAndroid Build Coastguard Worker 69*60517a1eSAndroid Build Coastguard Workerdef _PyRuntimeInfo_init( 70*60517a1eSAndroid Build Coastguard Worker *, 71*60517a1eSAndroid Build Coastguard Worker implementation_name = None, 72*60517a1eSAndroid Build Coastguard Worker interpreter_path = None, 73*60517a1eSAndroid Build Coastguard Worker interpreter = None, 74*60517a1eSAndroid Build Coastguard Worker files = None, 75*60517a1eSAndroid Build Coastguard Worker coverage_tool = None, 76*60517a1eSAndroid Build Coastguard Worker coverage_files = None, 77*60517a1eSAndroid Build Coastguard Worker pyc_tag = None, 78*60517a1eSAndroid Build Coastguard Worker python_version, 79*60517a1eSAndroid Build Coastguard Worker stub_shebang = None, 80*60517a1eSAndroid Build Coastguard Worker bootstrap_template = None, 81*60517a1eSAndroid Build Coastguard Worker interpreter_version_info = None, 82*60517a1eSAndroid Build Coastguard Worker stage2_bootstrap_template = None, 83*60517a1eSAndroid Build Coastguard Worker zip_main_template = None): 84*60517a1eSAndroid Build Coastguard Worker if (interpreter_path and interpreter) or (not interpreter_path and not interpreter): 85*60517a1eSAndroid Build Coastguard Worker fail("exactly one of interpreter or interpreter_path must be specified") 86*60517a1eSAndroid Build Coastguard Worker 87*60517a1eSAndroid Build Coastguard Worker if interpreter_path and files != None: 88*60517a1eSAndroid Build Coastguard Worker fail("cannot specify 'files' if 'interpreter_path' is given") 89*60517a1eSAndroid Build Coastguard Worker 90*60517a1eSAndroid Build Coastguard Worker if (coverage_tool and not coverage_files) or (not coverage_tool and coverage_files): 91*60517a1eSAndroid Build Coastguard Worker fail( 92*60517a1eSAndroid Build Coastguard Worker "coverage_tool and coverage_files must both be set or neither must be set, " + 93*60517a1eSAndroid Build Coastguard Worker "got coverage_tool={}, coverage_files={}".format( 94*60517a1eSAndroid Build Coastguard Worker coverage_tool, 95*60517a1eSAndroid Build Coastguard Worker coverage_files, 96*60517a1eSAndroid Build Coastguard Worker ), 97*60517a1eSAndroid Build Coastguard Worker ) 98*60517a1eSAndroid Build Coastguard Worker 99*60517a1eSAndroid Build Coastguard Worker if python_version not in _PYTHON_VERSION_VALUES: 100*60517a1eSAndroid Build Coastguard Worker fail("invalid python_version: '{}'; must be one of {}".format( 101*60517a1eSAndroid Build Coastguard Worker python_version, 102*60517a1eSAndroid Build Coastguard Worker _PYTHON_VERSION_VALUES, 103*60517a1eSAndroid Build Coastguard Worker )) 104*60517a1eSAndroid Build Coastguard Worker 105*60517a1eSAndroid Build Coastguard Worker if files != None and type(files) != type(depset()): 106*60517a1eSAndroid Build Coastguard Worker fail("invalid files: got value of type {}, want depset".format(type(files))) 107*60517a1eSAndroid Build Coastguard Worker 108*60517a1eSAndroid Build Coastguard Worker if interpreter: 109*60517a1eSAndroid Build Coastguard Worker if files == None: 110*60517a1eSAndroid Build Coastguard Worker files = depset() 111*60517a1eSAndroid Build Coastguard Worker else: 112*60517a1eSAndroid Build Coastguard Worker files = None 113*60517a1eSAndroid Build Coastguard Worker 114*60517a1eSAndroid Build Coastguard Worker if coverage_files == None: 115*60517a1eSAndroid Build Coastguard Worker coverage_files = depset() 116*60517a1eSAndroid Build Coastguard Worker 117*60517a1eSAndroid Build Coastguard Worker if not stub_shebang: 118*60517a1eSAndroid Build Coastguard Worker stub_shebang = DEFAULT_STUB_SHEBANG 119*60517a1eSAndroid Build Coastguard Worker 120*60517a1eSAndroid Build Coastguard Worker return { 121*60517a1eSAndroid Build Coastguard Worker "bootstrap_template": bootstrap_template, 122*60517a1eSAndroid Build Coastguard Worker "coverage_files": coverage_files, 123*60517a1eSAndroid Build Coastguard Worker "coverage_tool": coverage_tool, 124*60517a1eSAndroid Build Coastguard Worker "files": files, 125*60517a1eSAndroid Build Coastguard Worker "implementation_name": implementation_name, 126*60517a1eSAndroid Build Coastguard Worker "interpreter": interpreter, 127*60517a1eSAndroid Build Coastguard Worker "interpreter_path": interpreter_path, 128*60517a1eSAndroid Build Coastguard Worker "interpreter_version_info": interpreter_version_info_struct_from_dict(interpreter_version_info), 129*60517a1eSAndroid Build Coastguard Worker "pyc_tag": pyc_tag, 130*60517a1eSAndroid Build Coastguard Worker "python_version": python_version, 131*60517a1eSAndroid Build Coastguard Worker "stage2_bootstrap_template": stage2_bootstrap_template, 132*60517a1eSAndroid Build Coastguard Worker "stub_shebang": stub_shebang, 133*60517a1eSAndroid Build Coastguard Worker "zip_main_template": zip_main_template, 134*60517a1eSAndroid Build Coastguard Worker } 135*60517a1eSAndroid Build Coastguard Worker 136*60517a1eSAndroid Build Coastguard Worker# TODO(#15897): Rename this to PyRuntimeInfo when we're ready to replace the Java 137*60517a1eSAndroid Build Coastguard Worker# implemented provider with the Starlark one. 138*60517a1eSAndroid Build Coastguard WorkerPyRuntimeInfo, _unused_raw_py_runtime_info_ctor = _define_provider( 139*60517a1eSAndroid Build Coastguard Worker doc = """Contains information about a Python runtime, as returned by the `py_runtime` 140*60517a1eSAndroid Build Coastguard Workerrule. 141*60517a1eSAndroid Build Coastguard Worker 142*60517a1eSAndroid Build Coastguard WorkerA Python runtime describes either a *platform runtime* or an *in-build runtime*. 143*60517a1eSAndroid Build Coastguard WorkerA platform runtime accesses a system-installed interpreter at a known path, 144*60517a1eSAndroid Build Coastguard Workerwhereas an in-build runtime points to a `File` that acts as the interpreter. In 145*60517a1eSAndroid Build Coastguard Workerboth cases, an "interpreter" is really any executable binary or wrapper script 146*60517a1eSAndroid Build Coastguard Workerthat is capable of running a Python script passed on the command line, following 147*60517a1eSAndroid Build Coastguard Workerthe same conventions as the standard CPython interpreter. 148*60517a1eSAndroid Build Coastguard Worker""", 149*60517a1eSAndroid Build Coastguard Worker init = _PyRuntimeInfo_init, 150*60517a1eSAndroid Build Coastguard Worker fields = { 151*60517a1eSAndroid Build Coastguard Worker "bootstrap_template": """ 152*60517a1eSAndroid Build Coastguard Worker:type: File 153*60517a1eSAndroid Build Coastguard Worker 154*60517a1eSAndroid Build Coastguard WorkerA template of code responsible for the initial startup of a program. 155*60517a1eSAndroid Build Coastguard Worker 156*60517a1eSAndroid Build Coastguard WorkerThis code is responsible for: 157*60517a1eSAndroid Build Coastguard Worker 158*60517a1eSAndroid Build Coastguard Worker* Locating the target interpreter. Typically it is in runfiles, but not always. 159*60517a1eSAndroid Build Coastguard Worker* Setting necessary environment variables, command line flags, or other 160*60517a1eSAndroid Build Coastguard Worker configuration that can't be modified after the interpreter starts. 161*60517a1eSAndroid Build Coastguard Worker* Invoking the appropriate entry point. This is usually a second-stage bootstrap 162*60517a1eSAndroid Build Coastguard Worker that performs additional setup prior to running a program's actual entry point. 163*60517a1eSAndroid Build Coastguard Worker 164*60517a1eSAndroid Build Coastguard WorkerThe {obj}`--bootstrap_impl` flag affects how this stage 1 bootstrap 165*60517a1eSAndroid Build Coastguard Workeris expected to behave and the substutitions performed. 166*60517a1eSAndroid Build Coastguard Worker 167*60517a1eSAndroid Build Coastguard Worker* `--bootstrap_impl=system_python` substitutions: `%is_zipfile%`, `%python_binary%`, 168*60517a1eSAndroid Build Coastguard Worker `%target%`, `%workspace_name`, `%coverage_tool%`, `%import_all%`, `%imports%`, 169*60517a1eSAndroid Build Coastguard Worker `%main%`, `%shebang%` 170*60517a1eSAndroid Build Coastguard Worker* `--bootstrap_impl=script` substititions: `%is_zipfile%`, `%python_binary%`, 171*60517a1eSAndroid Build Coastguard Worker `%target%`, `%workspace_name`, `%shebang%, `%stage2_bootstrap%` 172*60517a1eSAndroid Build Coastguard Worker 173*60517a1eSAndroid Build Coastguard WorkerSubstitution definitions: 174*60517a1eSAndroid Build Coastguard Worker 175*60517a1eSAndroid Build Coastguard Worker* `%shebang%`: The shebang to use with the bootstrap; the bootstrap template 176*60517a1eSAndroid Build Coastguard Worker may choose to ignore this. 177*60517a1eSAndroid Build Coastguard Worker* `%stage2_bootstrap%`: A runfiles-relative path to the stage 2 bootstrap. 178*60517a1eSAndroid Build Coastguard Worker* `%python_binary%`: The path to the target Python interpreter. There are three 179*60517a1eSAndroid Build Coastguard Worker types of paths: 180*60517a1eSAndroid Build Coastguard Worker * An absolute path to a system interpreter (e.g. begins with `/`). 181*60517a1eSAndroid Build Coastguard Worker * A runfiles-relative path to an interpreter (e.g. `somerepo/bin/python3`) 182*60517a1eSAndroid Build Coastguard Worker * A program to search for on PATH, i.e. a word without spaces, e.g. `python3`. 183*60517a1eSAndroid Build Coastguard Worker* `%workspace_name%`: The name of the workspace the target belongs to. 184*60517a1eSAndroid Build Coastguard Worker* `%is_zipfile%`: The string `1` if this template is prepended to a zipfile to 185*60517a1eSAndroid Build Coastguard Worker create a self-executable zip file. The string `0` otherwise. 186*60517a1eSAndroid Build Coastguard Worker 187*60517a1eSAndroid Build Coastguard WorkerFor the other substitution definitions, see the {obj}`stage2_bootstrap_template` 188*60517a1eSAndroid Build Coastguard Workerdocs. 189*60517a1eSAndroid Build Coastguard Worker 190*60517a1eSAndroid Build Coastguard Worker:::{versionchanged} 0.33.0 191*60517a1eSAndroid Build Coastguard WorkerThe set of substitutions depends on {obj}`--bootstrap_impl` 192*60517a1eSAndroid Build Coastguard Worker::: 193*60517a1eSAndroid Build Coastguard Worker""", 194*60517a1eSAndroid Build Coastguard Worker "coverage_files": """ 195*60517a1eSAndroid Build Coastguard Worker:type: depset[File] | None 196*60517a1eSAndroid Build Coastguard Worker 197*60517a1eSAndroid Build Coastguard WorkerThe files required at runtime for using `coverage_tool`. Will be `None` if no 198*60517a1eSAndroid Build Coastguard Worker`coverage_tool` was provided. 199*60517a1eSAndroid Build Coastguard Worker""", 200*60517a1eSAndroid Build Coastguard Worker "coverage_tool": """ 201*60517a1eSAndroid Build Coastguard Worker:type: File | None 202*60517a1eSAndroid Build Coastguard Worker 203*60517a1eSAndroid Build Coastguard WorkerIf set, this field is a `File` representing tool used for collecting code 204*60517a1eSAndroid Build Coastguard Workercoverage information from python tests. Otherwise, this is `None`. 205*60517a1eSAndroid Build Coastguard Worker""", 206*60517a1eSAndroid Build Coastguard Worker "files": """ 207*60517a1eSAndroid Build Coastguard Worker:type: depset[File] | None 208*60517a1eSAndroid Build Coastguard Worker 209*60517a1eSAndroid Build Coastguard WorkerIf this is an in-build runtime, this field is a `depset` of `File`s that need to 210*60517a1eSAndroid Build Coastguard Workerbe added to the runfiles of an executable target that uses this runtime (in 211*60517a1eSAndroid Build Coastguard Workerparticular, files needed by `interpreter`). The value of `interpreter` need not 212*60517a1eSAndroid Build Coastguard Workerbe included in this field. If this is a platform runtime then this field is 213*60517a1eSAndroid Build Coastguard Worker`None`. 214*60517a1eSAndroid Build Coastguard Worker""", 215*60517a1eSAndroid Build Coastguard Worker "implementation_name": """ 216*60517a1eSAndroid Build Coastguard Worker:type: str | None 217*60517a1eSAndroid Build Coastguard Worker 218*60517a1eSAndroid Build Coastguard WorkerThe Python implementation name (`sys.implementation.name`) 219*60517a1eSAndroid Build Coastguard Worker""", 220*60517a1eSAndroid Build Coastguard Worker "interpreter": """ 221*60517a1eSAndroid Build Coastguard Worker:type: File | None 222*60517a1eSAndroid Build Coastguard Worker 223*60517a1eSAndroid Build Coastguard WorkerIf this is an in-build runtime, this field is a `File` representing the 224*60517a1eSAndroid Build Coastguard Workerinterpreter. Otherwise, this is `None`. Note that an in-build runtime can use 225*60517a1eSAndroid Build Coastguard Workereither a prebuilt, checked-in interpreter or an interpreter built from source. 226*60517a1eSAndroid Build Coastguard Worker""", 227*60517a1eSAndroid Build Coastguard Worker "interpreter_path": """ 228*60517a1eSAndroid Build Coastguard Worker:type: str | None 229*60517a1eSAndroid Build Coastguard Worker 230*60517a1eSAndroid Build Coastguard WorkerIf this is a platform runtime, this field is the absolute filesystem path to the 231*60517a1eSAndroid Build Coastguard Workerinterpreter on the target platform. Otherwise, this is `None`. 232*60517a1eSAndroid Build Coastguard Worker""", 233*60517a1eSAndroid Build Coastguard Worker "interpreter_version_info": """ 234*60517a1eSAndroid Build Coastguard Worker:type: struct 235*60517a1eSAndroid Build Coastguard Worker 236*60517a1eSAndroid Build Coastguard WorkerVersion information about the interpreter this runtime provides. 237*60517a1eSAndroid Build Coastguard WorkerIt should match the format given by `sys.version_info`, however 238*60517a1eSAndroid Build Coastguard Workerfor simplicity, the micro, releaselevel, and serial values are 239*60517a1eSAndroid Build Coastguard Workeroptional. 240*60517a1eSAndroid Build Coastguard WorkerA struct with the following fields: 241*60517a1eSAndroid Build Coastguard Worker* `major`: {type}`int`, the major version number 242*60517a1eSAndroid Build Coastguard Worker* `minor`: {type}`int`, the minor version number 243*60517a1eSAndroid Build Coastguard Worker* `micro`: {type}`int | None`, the micro version number 244*60517a1eSAndroid Build Coastguard Worker* `releaselevel`: {type}`str | None`, the release level 245*60517a1eSAndroid Build Coastguard Worker* `serial`: {type}`int | None`, the serial number of the release 246*60517a1eSAndroid Build Coastguard Worker""", 247*60517a1eSAndroid Build Coastguard Worker "pyc_tag": """ 248*60517a1eSAndroid Build Coastguard Worker:type: str | None 249*60517a1eSAndroid Build Coastguard Worker 250*60517a1eSAndroid Build Coastguard WorkerThe tag portion of a pyc filename, e.g. the `cpython-39` infix 251*60517a1eSAndroid Build Coastguard Workerof `foo.cpython-39.pyc`. See PEP 3147. If not specified, it will be computed 252*60517a1eSAndroid Build Coastguard Workerfrom {obj}`implementation_name` and {obj}`interpreter_version_info`. If no 253*60517a1eSAndroid Build Coastguard Workerpyc_tag is available, then only source-less pyc generation will function 254*60517a1eSAndroid Build Coastguard Workercorrectly. 255*60517a1eSAndroid Build Coastguard Worker""", 256*60517a1eSAndroid Build Coastguard Worker "python_version": """ 257*60517a1eSAndroid Build Coastguard Worker:type: str 258*60517a1eSAndroid Build Coastguard Worker 259*60517a1eSAndroid Build Coastguard WorkerIndicates whether this runtime uses Python major version 2 or 3. Valid values 260*60517a1eSAndroid Build Coastguard Workerare (only) `"PY2"` and `"PY3"`. 261*60517a1eSAndroid Build Coastguard Worker""", 262*60517a1eSAndroid Build Coastguard Worker "stage2_bootstrap_template": """ 263*60517a1eSAndroid Build Coastguard Worker:type: File 264*60517a1eSAndroid Build Coastguard Worker 265*60517a1eSAndroid Build Coastguard WorkerA template of Python code that runs under the desired interpreter and is 266*60517a1eSAndroid Build Coastguard Workerresponsible for orchestrating calling the program's actual main code. This 267*60517a1eSAndroid Build Coastguard Workerbootstrap is responsible for affecting the current runtime's state, such as 268*60517a1eSAndroid Build Coastguard Workerimport paths or enabling coverage, so that, when it runs the program's actual 269*60517a1eSAndroid Build Coastguard Workermain code, it works properly under Bazel. 270*60517a1eSAndroid Build Coastguard Worker 271*60517a1eSAndroid Build Coastguard WorkerThe following substitutions are made during template expansion: 272*60517a1eSAndroid Build Coastguard Worker* `%main%`: A runfiles-relative path to the program's actual main file. This 273*60517a1eSAndroid Build Coastguard Worker can be a `.py` or `.pyc` file, depending on precompile settings. 274*60517a1eSAndroid Build Coastguard Worker* `%coverage_tool%`: Runfiles-relative path to the coverage library's entry point. 275*60517a1eSAndroid Build Coastguard Worker If coverage is not enabled or available, an empty string. 276*60517a1eSAndroid Build Coastguard Worker* `%import_all%`: The string `True` if all repositories in the runfiles should 277*60517a1eSAndroid Build Coastguard Worker be added to sys.path. The string `False` otherwise. 278*60517a1eSAndroid Build Coastguard Worker* `%imports%`: A colon-delimited string of runfiles-relative paths to add to 279*60517a1eSAndroid Build Coastguard Worker sys.path. 280*60517a1eSAndroid Build Coastguard Worker* `%target%`: The name of the target this is for. 281*60517a1eSAndroid Build Coastguard Worker* `%workspace_name%`: The name of the workspace the target belongs to. 282*60517a1eSAndroid Build Coastguard Worker 283*60517a1eSAndroid Build Coastguard Worker:::{versionadded} 0.33.0 284*60517a1eSAndroid Build Coastguard Worker::: 285*60517a1eSAndroid Build Coastguard Worker""", 286*60517a1eSAndroid Build Coastguard Worker "stub_shebang": """ 287*60517a1eSAndroid Build Coastguard Worker:type: str 288*60517a1eSAndroid Build Coastguard Worker 289*60517a1eSAndroid Build Coastguard Worker"Shebang" expression prepended to the bootstrapping Python stub 290*60517a1eSAndroid Build Coastguard Workerscript used when executing {obj}`py_binary` targets. Does not 291*60517a1eSAndroid Build Coastguard Workerapply to Windows. 292*60517a1eSAndroid Build Coastguard Worker""", 293*60517a1eSAndroid Build Coastguard Worker "zip_main_template": """ 294*60517a1eSAndroid Build Coastguard Worker:type: File 295*60517a1eSAndroid Build Coastguard Worker 296*60517a1eSAndroid Build Coastguard WorkerA template of Python code that becomes a zip file's top-level `__main__.py` 297*60517a1eSAndroid Build Coastguard Workerfile. The top-level `__main__.py` file is used when the zip file is explicitly 298*60517a1eSAndroid Build Coastguard Workerpassed to a Python interpreter. See PEP 441 for more information about zipapp 299*60517a1eSAndroid Build Coastguard Workersupport. Note that py_binary-generated zip files are self-executing and 300*60517a1eSAndroid Build Coastguard Workerskip calling `__main__.py`. 301*60517a1eSAndroid Build Coastguard Worker 302*60517a1eSAndroid Build Coastguard WorkerThe following substitutions are made during template expansion: 303*60517a1eSAndroid Build Coastguard Worker* `%stage2_bootstrap%`: A runfiles-relative string to the stage 2 bootstrap file. 304*60517a1eSAndroid Build Coastguard Worker* `%python_binary%`: The path to the target Python interpreter. There are three 305*60517a1eSAndroid Build Coastguard Worker types of paths: 306*60517a1eSAndroid Build Coastguard Worker * An absolute path to a system interpreter (e.g. begins with `/`). 307*60517a1eSAndroid Build Coastguard Worker * A runfiles-relative path to an interpreter (e.g. `somerepo/bin/python3`) 308*60517a1eSAndroid Build Coastguard Worker * A program to search for on PATH, i.e. a word without spaces, e.g. `python3`. 309*60517a1eSAndroid Build Coastguard Worker* `%workspace_name%`: The name of the workspace for the built target. 310*60517a1eSAndroid Build Coastguard Worker 311*60517a1eSAndroid Build Coastguard Worker:::{versionadded} 0.33.0 312*60517a1eSAndroid Build Coastguard Worker::: 313*60517a1eSAndroid Build Coastguard Worker""", 314*60517a1eSAndroid Build Coastguard Worker }, 315*60517a1eSAndroid Build Coastguard Worker) 316*60517a1eSAndroid Build Coastguard Worker 317*60517a1eSAndroid Build Coastguard Workerdef _check_arg_type(name, required_type, value): 318*60517a1eSAndroid Build Coastguard Worker value_type = type(value) 319*60517a1eSAndroid Build Coastguard Worker if value_type != required_type: 320*60517a1eSAndroid Build Coastguard Worker fail("parameter '{}' got value of type '{}', want '{}'".format( 321*60517a1eSAndroid Build Coastguard Worker name, 322*60517a1eSAndroid Build Coastguard Worker value_type, 323*60517a1eSAndroid Build Coastguard Worker required_type, 324*60517a1eSAndroid Build Coastguard Worker )) 325*60517a1eSAndroid Build Coastguard Worker 326*60517a1eSAndroid Build Coastguard Workerdef _PyInfo_init( 327*60517a1eSAndroid Build Coastguard Worker *, 328*60517a1eSAndroid Build Coastguard Worker transitive_sources, 329*60517a1eSAndroid Build Coastguard Worker uses_shared_libraries = False, 330*60517a1eSAndroid Build Coastguard Worker imports = depset(), 331*60517a1eSAndroid Build Coastguard Worker has_py2_only_sources = False, 332*60517a1eSAndroid Build Coastguard Worker has_py3_only_sources = False, 333*60517a1eSAndroid Build Coastguard Worker direct_pyc_files = depset(), 334*60517a1eSAndroid Build Coastguard Worker transitive_pyc_files = depset()): 335*60517a1eSAndroid Build Coastguard Worker _check_arg_type("transitive_sources", "depset", transitive_sources) 336*60517a1eSAndroid Build Coastguard Worker 337*60517a1eSAndroid Build Coastguard Worker # Verify it's postorder compatible, but retain is original ordering. 338*60517a1eSAndroid Build Coastguard Worker depset(transitive = [transitive_sources], order = "postorder") 339*60517a1eSAndroid Build Coastguard Worker 340*60517a1eSAndroid Build Coastguard Worker _check_arg_type("uses_shared_libraries", "bool", uses_shared_libraries) 341*60517a1eSAndroid Build Coastguard Worker _check_arg_type("imports", "depset", imports) 342*60517a1eSAndroid Build Coastguard Worker _check_arg_type("has_py2_only_sources", "bool", has_py2_only_sources) 343*60517a1eSAndroid Build Coastguard Worker _check_arg_type("has_py3_only_sources", "bool", has_py3_only_sources) 344*60517a1eSAndroid Build Coastguard Worker _check_arg_type("direct_pyc_files", "depset", direct_pyc_files) 345*60517a1eSAndroid Build Coastguard Worker _check_arg_type("transitive_pyc_files", "depset", transitive_pyc_files) 346*60517a1eSAndroid Build Coastguard Worker return { 347*60517a1eSAndroid Build Coastguard Worker "direct_pyc_files": direct_pyc_files, 348*60517a1eSAndroid Build Coastguard Worker "has_py2_only_sources": has_py2_only_sources, 349*60517a1eSAndroid Build Coastguard Worker "has_py3_only_sources": has_py2_only_sources, 350*60517a1eSAndroid Build Coastguard Worker "imports": imports, 351*60517a1eSAndroid Build Coastguard Worker "transitive_pyc_files": transitive_pyc_files, 352*60517a1eSAndroid Build Coastguard Worker "transitive_sources": transitive_sources, 353*60517a1eSAndroid Build Coastguard Worker "uses_shared_libraries": uses_shared_libraries, 354*60517a1eSAndroid Build Coastguard Worker } 355*60517a1eSAndroid Build Coastguard Worker 356*60517a1eSAndroid Build Coastguard WorkerPyInfo, _unused_raw_py_info_ctor = _define_provider( 357*60517a1eSAndroid Build Coastguard Worker doc = "Encapsulates information provided by the Python rules.", 358*60517a1eSAndroid Build Coastguard Worker init = _PyInfo_init, 359*60517a1eSAndroid Build Coastguard Worker fields = { 360*60517a1eSAndroid Build Coastguard Worker "direct_pyc_files": """ 361*60517a1eSAndroid Build Coastguard Worker:type: depset[File] 362*60517a1eSAndroid Build Coastguard Worker 363*60517a1eSAndroid Build Coastguard WorkerPrecompiled Python files that are considered directly provided 364*60517a1eSAndroid Build Coastguard Workerby the target. 365*60517a1eSAndroid Build Coastguard Worker""", 366*60517a1eSAndroid Build Coastguard Worker "has_py2_only_sources": """ 367*60517a1eSAndroid Build Coastguard Worker:type: bool 368*60517a1eSAndroid Build Coastguard Worker 369*60517a1eSAndroid Build Coastguard WorkerWhether any of this target's transitive sources requires a Python 2 runtime. 370*60517a1eSAndroid Build Coastguard Worker""", 371*60517a1eSAndroid Build Coastguard Worker "has_py3_only_sources": """ 372*60517a1eSAndroid Build Coastguard Worker:type: bool 373*60517a1eSAndroid Build Coastguard Worker 374*60517a1eSAndroid Build Coastguard WorkerWhether any of this target's transitive sources requires a Python 3 runtime. 375*60517a1eSAndroid Build Coastguard Worker""", 376*60517a1eSAndroid Build Coastguard Worker "imports": """\ 377*60517a1eSAndroid Build Coastguard Worker:type: depset[str] 378*60517a1eSAndroid Build Coastguard Worker 379*60517a1eSAndroid Build Coastguard WorkerA depset of import path strings to be added to the `PYTHONPATH` of executable 380*60517a1eSAndroid Build Coastguard WorkerPython targets. These are accumulated from the transitive `deps`. 381*60517a1eSAndroid Build Coastguard WorkerThe order of the depset is not guaranteed and may be changed in the future. It 382*60517a1eSAndroid Build Coastguard Workeris recommended to use `default` order (the default). 383*60517a1eSAndroid Build Coastguard Worker""", 384*60517a1eSAndroid Build Coastguard Worker "transitive_pyc_files": """ 385*60517a1eSAndroid Build Coastguard Worker:type: depset[File] 386*60517a1eSAndroid Build Coastguard Worker 387*60517a1eSAndroid Build Coastguard WorkerDirect and transitive precompiled Python files that are provided by the target. 388*60517a1eSAndroid Build Coastguard Worker""", 389*60517a1eSAndroid Build Coastguard Worker "transitive_sources": """\ 390*60517a1eSAndroid Build Coastguard Worker:type: depset[File] 391*60517a1eSAndroid Build Coastguard Worker 392*60517a1eSAndroid Build Coastguard WorkerA (`postorder`-compatible) depset of `.py` files appearing in the target's 393*60517a1eSAndroid Build Coastguard Worker`srcs` and the `srcs` of the target's transitive `deps`. 394*60517a1eSAndroid Build Coastguard Worker""", 395*60517a1eSAndroid Build Coastguard Worker "uses_shared_libraries": """ 396*60517a1eSAndroid Build Coastguard Worker:type: bool 397*60517a1eSAndroid Build Coastguard Worker 398*60517a1eSAndroid Build Coastguard WorkerWhether any of this target's transitive `deps` has a shared library file (such 399*60517a1eSAndroid Build Coastguard Workeras a `.so` file). 400*60517a1eSAndroid Build Coastguard Worker 401*60517a1eSAndroid Build Coastguard WorkerThis field is currently unused in Bazel and may go away in the future. 402*60517a1eSAndroid Build Coastguard Worker""", 403*60517a1eSAndroid Build Coastguard Worker }, 404*60517a1eSAndroid Build Coastguard Worker) 405*60517a1eSAndroid Build Coastguard Worker 406*60517a1eSAndroid Build Coastguard Workerdef _PyCcLinkParamsProvider_init(cc_info): 407*60517a1eSAndroid Build Coastguard Worker return { 408*60517a1eSAndroid Build Coastguard Worker "cc_info": CcInfo(linking_context = cc_info.linking_context), 409*60517a1eSAndroid Build Coastguard Worker } 410*60517a1eSAndroid Build Coastguard Worker 411*60517a1eSAndroid Build Coastguard Worker# buildifier: disable=name-conventions 412*60517a1eSAndroid Build Coastguard WorkerPyCcLinkParamsProvider, _unused_raw_py_cc_link_params_provider_ctor = _define_provider( 413*60517a1eSAndroid Build Coastguard Worker doc = ("Python-wrapper to forward {obj}`CcInfo.linking_context`. This is to " + 414*60517a1eSAndroid Build Coastguard Worker "allow Python targets to propagate C++ linking information, but " + 415*60517a1eSAndroid Build Coastguard Worker "without the Python target appearing to be a valid C++ rule dependency"), 416*60517a1eSAndroid Build Coastguard Worker init = _PyCcLinkParamsProvider_init, 417*60517a1eSAndroid Build Coastguard Worker fields = { 418*60517a1eSAndroid Build Coastguard Worker "cc_info": """ 419*60517a1eSAndroid Build Coastguard Worker:type: CcInfo 420*60517a1eSAndroid Build Coastguard Worker 421*60517a1eSAndroid Build Coastguard WorkerLinking information; it has only {obj}`CcInfo.linking_context` set. 422*60517a1eSAndroid Build Coastguard Worker""", 423*60517a1eSAndroid Build Coastguard Worker }, 424*60517a1eSAndroid Build Coastguard Worker) 425