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"""Various things common to Bazel and Google rule implementations.""" 15*60517a1eSAndroid Build Coastguard Worker 16*60517a1eSAndroid Build Coastguard Workerload("//python/private:reexports.bzl", "BuiltinPyInfo") 17*60517a1eSAndroid Build Coastguard Workerload(":cc_helper.bzl", "cc_helper") 18*60517a1eSAndroid Build Coastguard Workerload(":providers.bzl", "PyInfo") 19*60517a1eSAndroid Build Coastguard Workerload(":py_internal.bzl", "py_internal") 20*60517a1eSAndroid Build Coastguard Workerload( 21*60517a1eSAndroid Build Coastguard Worker ":semantics.bzl", 22*60517a1eSAndroid Build Coastguard Worker "NATIVE_RULES_MIGRATION_FIX_CMD", 23*60517a1eSAndroid Build Coastguard Worker "NATIVE_RULES_MIGRATION_HELP_URL", 24*60517a1eSAndroid Build Coastguard Worker) 25*60517a1eSAndroid Build Coastguard Worker 26*60517a1eSAndroid Build Coastguard Worker_testing = testing 27*60517a1eSAndroid Build Coastguard Worker_platform_common = platform_common 28*60517a1eSAndroid Build Coastguard Worker_coverage_common = coverage_common 29*60517a1eSAndroid Build Coastguard Worker_py_builtins = py_internal 30*60517a1eSAndroid Build Coastguard WorkerPackageSpecificationInfo = getattr(py_internal, "PackageSpecificationInfo", None) 31*60517a1eSAndroid Build Coastguard Worker 32*60517a1eSAndroid Build Coastguard Worker# Extensions without the dot 33*60517a1eSAndroid Build Coastguard Worker_PYTHON_SOURCE_EXTENSIONS = ["py"] 34*60517a1eSAndroid Build Coastguard Worker 35*60517a1eSAndroid Build Coastguard Worker# NOTE: Must stay in sync with the value used in rules_python 36*60517a1eSAndroid Build Coastguard Worker_MIGRATION_TAG = "__PYTHON_RULES_MIGRATION_DO_NOT_USE_WILL_BREAK__" 37*60517a1eSAndroid Build Coastguard Worker 38*60517a1eSAndroid Build Coastguard Workerdef create_binary_semantics_struct( 39*60517a1eSAndroid Build Coastguard Worker *, 40*60517a1eSAndroid Build Coastguard Worker create_executable, 41*60517a1eSAndroid Build Coastguard Worker get_cc_details_for_binary, 42*60517a1eSAndroid Build Coastguard Worker get_central_uncachable_version_file, 43*60517a1eSAndroid Build Coastguard Worker get_coverage_deps, 44*60517a1eSAndroid Build Coastguard Worker get_debugger_deps, 45*60517a1eSAndroid Build Coastguard Worker get_extra_common_runfiles_for_binary, 46*60517a1eSAndroid Build Coastguard Worker get_extra_providers, 47*60517a1eSAndroid Build Coastguard Worker get_extra_write_build_data_env, 48*60517a1eSAndroid Build Coastguard Worker get_interpreter_path, 49*60517a1eSAndroid Build Coastguard Worker get_imports, 50*60517a1eSAndroid Build Coastguard Worker get_native_deps_dso_name, 51*60517a1eSAndroid Build Coastguard Worker get_native_deps_user_link_flags, 52*60517a1eSAndroid Build Coastguard Worker get_stamp_flag, 53*60517a1eSAndroid Build Coastguard Worker maybe_precompile, 54*60517a1eSAndroid Build Coastguard Worker should_build_native_deps_dso, 55*60517a1eSAndroid Build Coastguard Worker should_create_init_files, 56*60517a1eSAndroid Build Coastguard Worker should_include_build_data): 57*60517a1eSAndroid Build Coastguard Worker """Helper to ensure a semantics struct has all necessary fields. 58*60517a1eSAndroid Build Coastguard Worker 59*60517a1eSAndroid Build Coastguard Worker Call this instead of a raw call to `struct(...)`; it'll help ensure all 60*60517a1eSAndroid Build Coastguard Worker the necessary functions are being correctly provided. 61*60517a1eSAndroid Build Coastguard Worker 62*60517a1eSAndroid Build Coastguard Worker Args: 63*60517a1eSAndroid Build Coastguard Worker create_executable: Callable; creates a binary's executable output. See 64*60517a1eSAndroid Build Coastguard Worker py_executable.bzl#py_executable_base_impl for details. 65*60517a1eSAndroid Build Coastguard Worker get_cc_details_for_binary: Callable that returns a `CcDetails` struct; see 66*60517a1eSAndroid Build Coastguard Worker `create_cc_detail_struct`. 67*60517a1eSAndroid Build Coastguard Worker get_central_uncachable_version_file: Callable that returns an optional 68*60517a1eSAndroid Build Coastguard Worker Artifact; this artifact is special: it is never cached and is a copy 69*60517a1eSAndroid Build Coastguard Worker of `ctx.version_file`; see py_builtins.copy_without_caching 70*60517a1eSAndroid Build Coastguard Worker get_coverage_deps: Callable that returns a list of Targets for making 71*60517a1eSAndroid Build Coastguard Worker coverage work; only called if coverage is enabled. 72*60517a1eSAndroid Build Coastguard Worker get_debugger_deps: Callable that returns a list of Targets that provide 73*60517a1eSAndroid Build Coastguard Worker custom debugger support; only called for target-configuration. 74*60517a1eSAndroid Build Coastguard Worker get_extra_common_runfiles_for_binary: Callable that returns a runfiles 75*60517a1eSAndroid Build Coastguard Worker object of extra runfiles a binary should include. 76*60517a1eSAndroid Build Coastguard Worker get_extra_providers: Callable that returns extra providers; see 77*60517a1eSAndroid Build Coastguard Worker py_executable.bzl#_create_providers for details. 78*60517a1eSAndroid Build Coastguard Worker get_extra_write_build_data_env: Callable that returns a dict[str, str] 79*60517a1eSAndroid Build Coastguard Worker of additional environment variable to pass to build data generation. 80*60517a1eSAndroid Build Coastguard Worker get_interpreter_path: Callable that returns an optional string, which is 81*60517a1eSAndroid Build Coastguard Worker the path to the Python interpreter to use for running the binary. 82*60517a1eSAndroid Build Coastguard Worker get_imports: Callable that returns a list of the target's import 83*60517a1eSAndroid Build Coastguard Worker paths (from the `imports` attribute, so just the target's own import 84*60517a1eSAndroid Build Coastguard Worker path strings, not from dependencies). 85*60517a1eSAndroid Build Coastguard Worker get_native_deps_dso_name: Callable that returns a string, which is the 86*60517a1eSAndroid Build Coastguard Worker basename (with extension) of the native deps DSO library. 87*60517a1eSAndroid Build Coastguard Worker get_native_deps_user_link_flags: Callable that returns a list of strings, 88*60517a1eSAndroid Build Coastguard Worker which are any extra linker flags to pass onto the native deps DSO 89*60517a1eSAndroid Build Coastguard Worker linking action. 90*60517a1eSAndroid Build Coastguard Worker get_stamp_flag: Callable that returns bool of if the --stamp flag was 91*60517a1eSAndroid Build Coastguard Worker enabled or not. 92*60517a1eSAndroid Build Coastguard Worker maybe_precompile: Callable that may optional precompile the input `.py` 93*60517a1eSAndroid Build Coastguard Worker sources and returns the full set of desired outputs derived from 94*60517a1eSAndroid Build Coastguard Worker the source files (e.g., both py and pyc, only one of them, etc). 95*60517a1eSAndroid Build Coastguard Worker should_build_native_deps_dso: Callable that returns bool; True if 96*60517a1eSAndroid Build Coastguard Worker building a native deps DSO is supported, False if not. 97*60517a1eSAndroid Build Coastguard Worker should_create_init_files: Callable that returns bool; True if 98*60517a1eSAndroid Build Coastguard Worker `__init__.py` files should be generated, False if not. 99*60517a1eSAndroid Build Coastguard Worker should_include_build_data: Callable that returns bool; True if 100*60517a1eSAndroid Build Coastguard Worker build data should be generated, False if not. 101*60517a1eSAndroid Build Coastguard Worker Returns: 102*60517a1eSAndroid Build Coastguard Worker A "BinarySemantics" struct. 103*60517a1eSAndroid Build Coastguard Worker """ 104*60517a1eSAndroid Build Coastguard Worker return struct( 105*60517a1eSAndroid Build Coastguard Worker # keep-sorted 106*60517a1eSAndroid Build Coastguard Worker create_executable = create_executable, 107*60517a1eSAndroid Build Coastguard Worker get_cc_details_for_binary = get_cc_details_for_binary, 108*60517a1eSAndroid Build Coastguard Worker get_central_uncachable_version_file = get_central_uncachable_version_file, 109*60517a1eSAndroid Build Coastguard Worker get_coverage_deps = get_coverage_deps, 110*60517a1eSAndroid Build Coastguard Worker get_debugger_deps = get_debugger_deps, 111*60517a1eSAndroid Build Coastguard Worker get_extra_common_runfiles_for_binary = get_extra_common_runfiles_for_binary, 112*60517a1eSAndroid Build Coastguard Worker get_extra_providers = get_extra_providers, 113*60517a1eSAndroid Build Coastguard Worker get_extra_write_build_data_env = get_extra_write_build_data_env, 114*60517a1eSAndroid Build Coastguard Worker get_imports = get_imports, 115*60517a1eSAndroid Build Coastguard Worker get_interpreter_path = get_interpreter_path, 116*60517a1eSAndroid Build Coastguard Worker get_native_deps_dso_name = get_native_deps_dso_name, 117*60517a1eSAndroid Build Coastguard Worker get_native_deps_user_link_flags = get_native_deps_user_link_flags, 118*60517a1eSAndroid Build Coastguard Worker get_stamp_flag = get_stamp_flag, 119*60517a1eSAndroid Build Coastguard Worker maybe_precompile = maybe_precompile, 120*60517a1eSAndroid Build Coastguard Worker should_build_native_deps_dso = should_build_native_deps_dso, 121*60517a1eSAndroid Build Coastguard Worker should_create_init_files = should_create_init_files, 122*60517a1eSAndroid Build Coastguard Worker should_include_build_data = should_include_build_data, 123*60517a1eSAndroid Build Coastguard Worker ) 124*60517a1eSAndroid Build Coastguard Worker 125*60517a1eSAndroid Build Coastguard Workerdef create_library_semantics_struct( 126*60517a1eSAndroid Build Coastguard Worker *, 127*60517a1eSAndroid Build Coastguard Worker get_cc_info_for_library, 128*60517a1eSAndroid Build Coastguard Worker get_imports, 129*60517a1eSAndroid Build Coastguard Worker maybe_precompile): 130*60517a1eSAndroid Build Coastguard Worker """Create a `LibrarySemantics` struct. 131*60517a1eSAndroid Build Coastguard Worker 132*60517a1eSAndroid Build Coastguard Worker Call this instead of a raw call to `struct(...)`; it'll help ensure all 133*60517a1eSAndroid Build Coastguard Worker the necessary functions are being correctly provided. 134*60517a1eSAndroid Build Coastguard Worker 135*60517a1eSAndroid Build Coastguard Worker Args: 136*60517a1eSAndroid Build Coastguard Worker get_cc_info_for_library: Callable that returns a CcInfo for the library; 137*60517a1eSAndroid Build Coastguard Worker see py_library_impl for arg details. 138*60517a1eSAndroid Build Coastguard Worker get_imports: Callable; see create_binary_semantics_struct. 139*60517a1eSAndroid Build Coastguard Worker maybe_precompile: Callable; see create_binary_semantics_struct. 140*60517a1eSAndroid Build Coastguard Worker Returns: 141*60517a1eSAndroid Build Coastguard Worker a `LibrarySemantics` struct. 142*60517a1eSAndroid Build Coastguard Worker """ 143*60517a1eSAndroid Build Coastguard Worker return struct( 144*60517a1eSAndroid Build Coastguard Worker # keep sorted 145*60517a1eSAndroid Build Coastguard Worker get_cc_info_for_library = get_cc_info_for_library, 146*60517a1eSAndroid Build Coastguard Worker get_imports = get_imports, 147*60517a1eSAndroid Build Coastguard Worker maybe_precompile = maybe_precompile, 148*60517a1eSAndroid Build Coastguard Worker ) 149*60517a1eSAndroid Build Coastguard Worker 150*60517a1eSAndroid Build Coastguard Workerdef create_cc_details_struct( 151*60517a1eSAndroid Build Coastguard Worker *, 152*60517a1eSAndroid Build Coastguard Worker cc_info_for_propagating, 153*60517a1eSAndroid Build Coastguard Worker cc_info_for_self_link, 154*60517a1eSAndroid Build Coastguard Worker cc_info_with_extra_link_time_libraries, 155*60517a1eSAndroid Build Coastguard Worker extra_runfiles, 156*60517a1eSAndroid Build Coastguard Worker cc_toolchain, 157*60517a1eSAndroid Build Coastguard Worker feature_config, 158*60517a1eSAndroid Build Coastguard Worker **kwargs): 159*60517a1eSAndroid Build Coastguard Worker """Creates a CcDetails struct. 160*60517a1eSAndroid Build Coastguard Worker 161*60517a1eSAndroid Build Coastguard Worker Args: 162*60517a1eSAndroid Build Coastguard Worker cc_info_for_propagating: CcInfo that is propagated out of the target 163*60517a1eSAndroid Build Coastguard Worker by returning it within a PyCcLinkParamsProvider object. 164*60517a1eSAndroid Build Coastguard Worker cc_info_for_self_link: CcInfo that is used when linking for the 165*60517a1eSAndroid Build Coastguard Worker binary (or its native deps DSO) itself. This may include extra 166*60517a1eSAndroid Build Coastguard Worker information that isn't propagating (e.g. a custom malloc) 167*60517a1eSAndroid Build Coastguard Worker cc_info_with_extra_link_time_libraries: CcInfo of extra link time 168*60517a1eSAndroid Build Coastguard Worker libraries that MUST come after `cc_info_for_self_link` (or possibly 169*60517a1eSAndroid Build Coastguard Worker always last; not entirely clear) when passed to 170*60517a1eSAndroid Build Coastguard Worker `link.linking_contexts`. 171*60517a1eSAndroid Build Coastguard Worker extra_runfiles: runfiles of extra files needed at runtime, usually as 172*60517a1eSAndroid Build Coastguard Worker part of `cc_info_with_extra_link_time_libraries`; should be added to 173*60517a1eSAndroid Build Coastguard Worker runfiles. 174*60517a1eSAndroid Build Coastguard Worker cc_toolchain: CcToolchain that should be used when building. 175*60517a1eSAndroid Build Coastguard Worker feature_config: struct from cc_configure_features(); see 176*60517a1eSAndroid Build Coastguard Worker //python/private/common:py_executable.bzl%cc_configure_features. 177*60517a1eSAndroid Build Coastguard Worker **kwargs: Additional keys/values to set in the returned struct. This is to 178*60517a1eSAndroid Build Coastguard Worker facilitate extensions with less patching. Any added fields should 179*60517a1eSAndroid Build Coastguard Worker pick names that are unlikely to collide if the CcDetails API has 180*60517a1eSAndroid Build Coastguard Worker additional fields added. 181*60517a1eSAndroid Build Coastguard Worker 182*60517a1eSAndroid Build Coastguard Worker Returns: 183*60517a1eSAndroid Build Coastguard Worker A `CcDetails` struct. 184*60517a1eSAndroid Build Coastguard Worker """ 185*60517a1eSAndroid Build Coastguard Worker return struct( 186*60517a1eSAndroid Build Coastguard Worker cc_info_for_propagating = cc_info_for_propagating, 187*60517a1eSAndroid Build Coastguard Worker cc_info_for_self_link = cc_info_for_self_link, 188*60517a1eSAndroid Build Coastguard Worker cc_info_with_extra_link_time_libraries = cc_info_with_extra_link_time_libraries, 189*60517a1eSAndroid Build Coastguard Worker extra_runfiles = extra_runfiles, 190*60517a1eSAndroid Build Coastguard Worker cc_toolchain = cc_toolchain, 191*60517a1eSAndroid Build Coastguard Worker feature_config = feature_config, 192*60517a1eSAndroid Build Coastguard Worker **kwargs 193*60517a1eSAndroid Build Coastguard Worker ) 194*60517a1eSAndroid Build Coastguard Worker 195*60517a1eSAndroid Build Coastguard Workerdef create_executable_result_struct(*, extra_files_to_build, output_groups, extra_runfiles = None): 196*60517a1eSAndroid Build Coastguard Worker """Creates a `CreateExecutableResult` struct. 197*60517a1eSAndroid Build Coastguard Worker 198*60517a1eSAndroid Build Coastguard Worker This is the return value type of the semantics create_executable function. 199*60517a1eSAndroid Build Coastguard Worker 200*60517a1eSAndroid Build Coastguard Worker Args: 201*60517a1eSAndroid Build Coastguard Worker extra_files_to_build: depset of File; additional files that should be 202*60517a1eSAndroid Build Coastguard Worker included as default outputs. 203*60517a1eSAndroid Build Coastguard Worker output_groups: dict[str, depset[File]]; additional output groups that 204*60517a1eSAndroid Build Coastguard Worker should be returned. 205*60517a1eSAndroid Build Coastguard Worker extra_runfiles: A runfiles object of additional runfiles to include. 206*60517a1eSAndroid Build Coastguard Worker 207*60517a1eSAndroid Build Coastguard Worker Returns: 208*60517a1eSAndroid Build Coastguard Worker A `CreateExecutableResult` struct. 209*60517a1eSAndroid Build Coastguard Worker """ 210*60517a1eSAndroid Build Coastguard Worker return struct( 211*60517a1eSAndroid Build Coastguard Worker extra_files_to_build = extra_files_to_build, 212*60517a1eSAndroid Build Coastguard Worker output_groups = output_groups, 213*60517a1eSAndroid Build Coastguard Worker extra_runfiles = extra_runfiles, 214*60517a1eSAndroid Build Coastguard Worker ) 215*60517a1eSAndroid Build Coastguard Worker 216*60517a1eSAndroid Build Coastguard Workerdef union_attrs(*attr_dicts, allow_none = False): 217*60517a1eSAndroid Build Coastguard Worker """Helper for combining and building attriute dicts for rules. 218*60517a1eSAndroid Build Coastguard Worker 219*60517a1eSAndroid Build Coastguard Worker Similar to dict.update, except: 220*60517a1eSAndroid Build Coastguard Worker * Duplicate keys raise an error if they aren't equal. This is to prevent 221*60517a1eSAndroid Build Coastguard Worker unintentionally replacing an attribute with a potentially incompatible 222*60517a1eSAndroid Build Coastguard Worker definition. 223*60517a1eSAndroid Build Coastguard Worker * None values are special: They mean the attribute is required, but the 224*60517a1eSAndroid Build Coastguard Worker value should be provided by another attribute dict (depending on the 225*60517a1eSAndroid Build Coastguard Worker `allow_none` arg). 226*60517a1eSAndroid Build Coastguard Worker Args: 227*60517a1eSAndroid Build Coastguard Worker *attr_dicts: The dicts to combine. 228*60517a1eSAndroid Build Coastguard Worker allow_none: bool, if True, then None values are allowed. If False, 229*60517a1eSAndroid Build Coastguard Worker then one of `attrs_dicts` must set a non-None value for keys 230*60517a1eSAndroid Build Coastguard Worker with a None value. 231*60517a1eSAndroid Build Coastguard Worker 232*60517a1eSAndroid Build Coastguard Worker Returns: 233*60517a1eSAndroid Build Coastguard Worker dict of attributes. 234*60517a1eSAndroid Build Coastguard Worker """ 235*60517a1eSAndroid Build Coastguard Worker result = {} 236*60517a1eSAndroid Build Coastguard Worker missing = {} 237*60517a1eSAndroid Build Coastguard Worker for attr_dict in attr_dicts: 238*60517a1eSAndroid Build Coastguard Worker for attr_name, value in attr_dict.items(): 239*60517a1eSAndroid Build Coastguard Worker if value == None and not allow_none: 240*60517a1eSAndroid Build Coastguard Worker if attr_name not in result: 241*60517a1eSAndroid Build Coastguard Worker missing[attr_name] = None 242*60517a1eSAndroid Build Coastguard Worker else: 243*60517a1eSAndroid Build Coastguard Worker if attr_name in missing: 244*60517a1eSAndroid Build Coastguard Worker missing.pop(attr_name) 245*60517a1eSAndroid Build Coastguard Worker 246*60517a1eSAndroid Build Coastguard Worker if attr_name not in result or result[attr_name] == None: 247*60517a1eSAndroid Build Coastguard Worker result[attr_name] = value 248*60517a1eSAndroid Build Coastguard Worker elif value != None and result[attr_name] != value: 249*60517a1eSAndroid Build Coastguard Worker fail("Duplicate attribute name: '{}': existing={}, new={}".format( 250*60517a1eSAndroid Build Coastguard Worker attr_name, 251*60517a1eSAndroid Build Coastguard Worker result[attr_name], 252*60517a1eSAndroid Build Coastguard Worker value, 253*60517a1eSAndroid Build Coastguard Worker )) 254*60517a1eSAndroid Build Coastguard Worker 255*60517a1eSAndroid Build Coastguard Worker # Else, they're equal, so do nothing. This allows merging dicts 256*60517a1eSAndroid Build Coastguard Worker # that both define the same key from a common place. 257*60517a1eSAndroid Build Coastguard Worker 258*60517a1eSAndroid Build Coastguard Worker if missing and not allow_none: 259*60517a1eSAndroid Build Coastguard Worker fail("Required attributes missing: " + csv(missing.keys())) 260*60517a1eSAndroid Build Coastguard Worker return result 261*60517a1eSAndroid Build Coastguard Worker 262*60517a1eSAndroid Build Coastguard Workerdef csv(values): 263*60517a1eSAndroid Build Coastguard Worker """Convert a list of strings to comma separated value string.""" 264*60517a1eSAndroid Build Coastguard Worker return ", ".join(sorted(values)) 265*60517a1eSAndroid Build Coastguard Worker 266*60517a1eSAndroid Build Coastguard Workerdef filter_to_py_srcs(srcs): 267*60517a1eSAndroid Build Coastguard Worker """Filters .py files from the given list of files""" 268*60517a1eSAndroid Build Coastguard Worker 269*60517a1eSAndroid Build Coastguard Worker # TODO(b/203567235): Get the set of recognized extensions from 270*60517a1eSAndroid Build Coastguard Worker # elsewhere, as there may be others. e.g. Bazel recognizes .py3 271*60517a1eSAndroid Build Coastguard Worker # as a valid extension. 272*60517a1eSAndroid Build Coastguard Worker return [f for f in srcs if f.extension == "py"] 273*60517a1eSAndroid Build Coastguard Worker 274*60517a1eSAndroid Build Coastguard Workerdef collect_imports(ctx, semantics): 275*60517a1eSAndroid Build Coastguard Worker return depset(direct = semantics.get_imports(ctx), transitive = [ 276*60517a1eSAndroid Build Coastguard Worker dep[PyInfo].imports 277*60517a1eSAndroid Build Coastguard Worker for dep in ctx.attr.deps 278*60517a1eSAndroid Build Coastguard Worker if PyInfo in dep 279*60517a1eSAndroid Build Coastguard Worker ] + [ 280*60517a1eSAndroid Build Coastguard Worker dep[BuiltinPyInfo].imports 281*60517a1eSAndroid Build Coastguard Worker for dep in ctx.attr.deps 282*60517a1eSAndroid Build Coastguard Worker if BuiltinPyInfo in dep 283*60517a1eSAndroid Build Coastguard Worker ]) 284*60517a1eSAndroid Build Coastguard Worker 285*60517a1eSAndroid Build Coastguard Workerdef collect_runfiles(ctx, files): 286*60517a1eSAndroid Build Coastguard Worker """Collects the necessary files from the rule's context. 287*60517a1eSAndroid Build Coastguard Worker 288*60517a1eSAndroid Build Coastguard Worker This presumes the ctx is for a py_binary, py_test, or py_library rule. 289*60517a1eSAndroid Build Coastguard Worker 290*60517a1eSAndroid Build Coastguard Worker Args: 291*60517a1eSAndroid Build Coastguard Worker ctx: rule ctx 292*60517a1eSAndroid Build Coastguard Worker files: depset of extra files to include in the runfiles. 293*60517a1eSAndroid Build Coastguard Worker Returns: 294*60517a1eSAndroid Build Coastguard Worker runfiles necessary for the ctx's target. 295*60517a1eSAndroid Build Coastguard Worker """ 296*60517a1eSAndroid Build Coastguard Worker return ctx.runfiles( 297*60517a1eSAndroid Build Coastguard Worker transitive_files = files, 298*60517a1eSAndroid Build Coastguard Worker # This little arg carries a lot of weight, but because Starlark doesn't 299*60517a1eSAndroid Build Coastguard Worker # have a way to identify if a target is just a File, the equivalent 300*60517a1eSAndroid Build Coastguard Worker # logic can't be re-implemented in pure-Starlark. 301*60517a1eSAndroid Build Coastguard Worker # 302*60517a1eSAndroid Build Coastguard Worker # Under the hood, it calls the Java `Runfiles#addRunfiles(ctx, 303*60517a1eSAndroid Build Coastguard Worker # DEFAULT_RUNFILES)` method, which is the what the Java implementation 304*60517a1eSAndroid Build Coastguard Worker # of the Python rules originally did, and the details of how that method 305*60517a1eSAndroid Build Coastguard Worker # works have become relied on in various ways. Specifically, what it 306*60517a1eSAndroid Build Coastguard Worker # does is visit the srcs, deps, and data attributes in the following 307*60517a1eSAndroid Build Coastguard Worker # ways: 308*60517a1eSAndroid Build Coastguard Worker # 309*60517a1eSAndroid Build Coastguard Worker # For each target in the "data" attribute... 310*60517a1eSAndroid Build Coastguard Worker # If the target is a File, then add that file to the runfiles. 311*60517a1eSAndroid Build Coastguard Worker # Otherwise, add the target's **data runfiles** to the runfiles. 312*60517a1eSAndroid Build Coastguard Worker # 313*60517a1eSAndroid Build Coastguard Worker # Note that, contray to best practice, the default outputs of the 314*60517a1eSAndroid Build Coastguard Worker # targets in `data` are *not* added, nor are the default runfiles. 315*60517a1eSAndroid Build Coastguard Worker # 316*60517a1eSAndroid Build Coastguard Worker # This ends up being important for several reasons, some of which are 317*60517a1eSAndroid Build Coastguard Worker # specific to Google-internal features of the rules. 318*60517a1eSAndroid Build Coastguard Worker # * For Python executables, we have to use `data_runfiles` to avoid 319*60517a1eSAndroid Build Coastguard Worker # conflicts for the build data files. Such files have 320*60517a1eSAndroid Build Coastguard Worker # target-specific content, but uses a fixed location, so if a 321*60517a1eSAndroid Build Coastguard Worker # binary has another binary in `data`, and both try to specify a 322*60517a1eSAndroid Build Coastguard Worker # file for that file path, then a warning is printed and an 323*60517a1eSAndroid Build Coastguard Worker # arbitrary one will be used. 324*60517a1eSAndroid Build Coastguard Worker # * For rules with _entirely_ different sets of files in data runfiles 325*60517a1eSAndroid Build Coastguard Worker # vs default runfiles vs default outputs. For example, 326*60517a1eSAndroid Build Coastguard Worker # proto_library: documented behavior of this rule is that putting it 327*60517a1eSAndroid Build Coastguard Worker # in the `data` attribute will cause the transitive closure of 328*60517a1eSAndroid Build Coastguard Worker # `.proto` source files to be included. This set of sources is only 329*60517a1eSAndroid Build Coastguard Worker # in the `data_runfiles` (`default_runfiles` is empty). 330*60517a1eSAndroid Build Coastguard Worker # * For rules with a _subset_ of files in data runfiles. For example, 331*60517a1eSAndroid Build Coastguard Worker # a certain Google rule used for packaging arbitrary binaries will 332*60517a1eSAndroid Build Coastguard Worker # generate multiple versions of a binary (e.g. different archs, 333*60517a1eSAndroid Build Coastguard Worker # stripped vs un-stripped, etc) in its default outputs, but only 334*60517a1eSAndroid Build Coastguard Worker # one of them in the runfiles; this helps avoid large, unused 335*60517a1eSAndroid Build Coastguard Worker # binaries contributing to remote executor input limits. 336*60517a1eSAndroid Build Coastguard Worker # 337*60517a1eSAndroid Build Coastguard Worker # Unfortunately, the above behavior also results in surprising behavior 338*60517a1eSAndroid Build Coastguard Worker # in some cases. For example, simple custom rules that only return their 339*60517a1eSAndroid Build Coastguard Worker # files in their default outputs won't have their files included. Such 340*60517a1eSAndroid Build Coastguard Worker # cases must either return their files in runfiles, or use `filegroup()` 341*60517a1eSAndroid Build Coastguard Worker # which will do so for them. 342*60517a1eSAndroid Build Coastguard Worker # 343*60517a1eSAndroid Build Coastguard Worker # For each target in "srcs" and "deps"... 344*60517a1eSAndroid Build Coastguard Worker # Add the default runfiles of the target to the runfiles. While this 345*60517a1eSAndroid Build Coastguard Worker # is desirable behavior, it also ends up letting a `py_library` 346*60517a1eSAndroid Build Coastguard Worker # be put in `srcs` and still mostly work. 347*60517a1eSAndroid Build Coastguard Worker # TODO(b/224640180): Reject py_library et al rules in srcs. 348*60517a1eSAndroid Build Coastguard Worker collect_default = True, 349*60517a1eSAndroid Build Coastguard Worker ) 350*60517a1eSAndroid Build Coastguard Worker 351*60517a1eSAndroid Build Coastguard Workerdef create_py_info(ctx, *, direct_sources, direct_pyc_files, imports): 352*60517a1eSAndroid Build Coastguard Worker """Create PyInfo provider. 353*60517a1eSAndroid Build Coastguard Worker 354*60517a1eSAndroid Build Coastguard Worker Args: 355*60517a1eSAndroid Build Coastguard Worker ctx: rule ctx. 356*60517a1eSAndroid Build Coastguard Worker direct_sources: depset of Files; the direct, raw `.py` sources for the 357*60517a1eSAndroid Build Coastguard Worker target. This should only be Python source files. It should not 358*60517a1eSAndroid Build Coastguard Worker include pyc files. 359*60517a1eSAndroid Build Coastguard Worker direct_pyc_files: depset of Files; the direct `.pyc` sources for the target. 360*60517a1eSAndroid Build Coastguard Worker imports: depset of strings; the import path values to propagate. 361*60517a1eSAndroid Build Coastguard Worker 362*60517a1eSAndroid Build Coastguard Worker Returns: 363*60517a1eSAndroid Build Coastguard Worker A tuple of the PyInfo instance and a depset of the 364*60517a1eSAndroid Build Coastguard Worker transitive sources collected from dependencies (the latter is only 365*60517a1eSAndroid Build Coastguard Worker necessary for deprecated extra actions support). 366*60517a1eSAndroid Build Coastguard Worker """ 367*60517a1eSAndroid Build Coastguard Worker uses_shared_libraries = False 368*60517a1eSAndroid Build Coastguard Worker has_py2_only_sources = ctx.attr.srcs_version in ("PY2", "PY2ONLY") 369*60517a1eSAndroid Build Coastguard Worker has_py3_only_sources = ctx.attr.srcs_version in ("PY3", "PY3ONLY") 370*60517a1eSAndroid Build Coastguard Worker transitive_sources_depsets = [] # list of depsets 371*60517a1eSAndroid Build Coastguard Worker transitive_sources_files = [] # list of Files 372*60517a1eSAndroid Build Coastguard Worker transitive_pyc_depsets = [direct_pyc_files] # list of depsets 373*60517a1eSAndroid Build Coastguard Worker for target in ctx.attr.deps: 374*60517a1eSAndroid Build Coastguard Worker # PyInfo may not be present e.g. cc_library rules. 375*60517a1eSAndroid Build Coastguard Worker if PyInfo in target or BuiltinPyInfo in target: 376*60517a1eSAndroid Build Coastguard Worker info = _get_py_info(target) 377*60517a1eSAndroid Build Coastguard Worker transitive_sources_depsets.append(info.transitive_sources) 378*60517a1eSAndroid Build Coastguard Worker uses_shared_libraries = uses_shared_libraries or info.uses_shared_libraries 379*60517a1eSAndroid Build Coastguard Worker has_py2_only_sources = has_py2_only_sources or info.has_py2_only_sources 380*60517a1eSAndroid Build Coastguard Worker has_py3_only_sources = has_py3_only_sources or info.has_py3_only_sources 381*60517a1eSAndroid Build Coastguard Worker 382*60517a1eSAndroid Build Coastguard Worker # BuiltinPyInfo doesn't have this field. 383*60517a1eSAndroid Build Coastguard Worker if hasattr(info, "transitive_pyc_files"): 384*60517a1eSAndroid Build Coastguard Worker transitive_pyc_depsets.append(info.transitive_pyc_files) 385*60517a1eSAndroid Build Coastguard Worker else: 386*60517a1eSAndroid Build Coastguard Worker # TODO(b/228692666): Remove this once non-PyInfo targets are no 387*60517a1eSAndroid Build Coastguard Worker # longer supported in `deps`. 388*60517a1eSAndroid Build Coastguard Worker files = target.files.to_list() 389*60517a1eSAndroid Build Coastguard Worker for f in files: 390*60517a1eSAndroid Build Coastguard Worker if f.extension == "py": 391*60517a1eSAndroid Build Coastguard Worker transitive_sources_files.append(f) 392*60517a1eSAndroid Build Coastguard Worker uses_shared_libraries = ( 393*60517a1eSAndroid Build Coastguard Worker uses_shared_libraries or 394*60517a1eSAndroid Build Coastguard Worker cc_helper.is_valid_shared_library_artifact(f) 395*60517a1eSAndroid Build Coastguard Worker ) 396*60517a1eSAndroid Build Coastguard Worker deps_transitive_sources = depset( 397*60517a1eSAndroid Build Coastguard Worker direct = transitive_sources_files, 398*60517a1eSAndroid Build Coastguard Worker transitive = transitive_sources_depsets, 399*60517a1eSAndroid Build Coastguard Worker ) 400*60517a1eSAndroid Build Coastguard Worker 401*60517a1eSAndroid Build Coastguard Worker # We only look at data to calculate uses_shared_libraries, if it's already 402*60517a1eSAndroid Build Coastguard Worker # true, then we don't need to waste time looping over it. 403*60517a1eSAndroid Build Coastguard Worker if not uses_shared_libraries: 404*60517a1eSAndroid Build Coastguard Worker # Similar to the above, except we only calculate uses_shared_libraries 405*60517a1eSAndroid Build Coastguard Worker for target in ctx.attr.data: 406*60517a1eSAndroid Build Coastguard Worker # TODO(b/234730058): Remove checking for PyInfo in data once depot 407*60517a1eSAndroid Build Coastguard Worker # cleaned up. 408*60517a1eSAndroid Build Coastguard Worker if PyInfo in target or BuiltinPyInfo in target: 409*60517a1eSAndroid Build Coastguard Worker info = _get_py_info(target) 410*60517a1eSAndroid Build Coastguard Worker uses_shared_libraries = info.uses_shared_libraries 411*60517a1eSAndroid Build Coastguard Worker else: 412*60517a1eSAndroid Build Coastguard Worker files = target.files.to_list() 413*60517a1eSAndroid Build Coastguard Worker for f in files: 414*60517a1eSAndroid Build Coastguard Worker uses_shared_libraries = cc_helper.is_valid_shared_library_artifact(f) 415*60517a1eSAndroid Build Coastguard Worker if uses_shared_libraries: 416*60517a1eSAndroid Build Coastguard Worker break 417*60517a1eSAndroid Build Coastguard Worker if uses_shared_libraries: 418*60517a1eSAndroid Build Coastguard Worker break 419*60517a1eSAndroid Build Coastguard Worker 420*60517a1eSAndroid Build Coastguard Worker py_info_kwargs = dict( 421*60517a1eSAndroid Build Coastguard Worker transitive_sources = depset( 422*60517a1eSAndroid Build Coastguard Worker transitive = [deps_transitive_sources, direct_sources], 423*60517a1eSAndroid Build Coastguard Worker ), 424*60517a1eSAndroid Build Coastguard Worker imports = imports, 425*60517a1eSAndroid Build Coastguard Worker # NOTE: This isn't strictly correct, but with Python 2 gone, 426*60517a1eSAndroid Build Coastguard Worker # the srcs_version logic is largely defunct, so shouldn't matter in 427*60517a1eSAndroid Build Coastguard Worker # practice. 428*60517a1eSAndroid Build Coastguard Worker has_py2_only_sources = has_py2_only_sources, 429*60517a1eSAndroid Build Coastguard Worker has_py3_only_sources = has_py3_only_sources, 430*60517a1eSAndroid Build Coastguard Worker uses_shared_libraries = uses_shared_libraries, 431*60517a1eSAndroid Build Coastguard Worker direct_pyc_files = direct_pyc_files, 432*60517a1eSAndroid Build Coastguard Worker transitive_pyc_files = depset(transitive = transitive_pyc_depsets), 433*60517a1eSAndroid Build Coastguard Worker ) 434*60517a1eSAndroid Build Coastguard Worker 435*60517a1eSAndroid Build Coastguard Worker # TODO(b/203567235): Set `uses_shared_libraries` field, though the Bazel 436*60517a1eSAndroid Build Coastguard Worker # docs indicate it's unused in Bazel and may be removed. 437*60517a1eSAndroid Build Coastguard Worker py_info = PyInfo(**py_info_kwargs) 438*60517a1eSAndroid Build Coastguard Worker 439*60517a1eSAndroid Build Coastguard Worker # Remove args that BuiltinPyInfo doesn't support 440*60517a1eSAndroid Build Coastguard Worker py_info_kwargs.pop("direct_pyc_files") 441*60517a1eSAndroid Build Coastguard Worker py_info_kwargs.pop("transitive_pyc_files") 442*60517a1eSAndroid Build Coastguard Worker builtin_py_info = BuiltinPyInfo(**py_info_kwargs) 443*60517a1eSAndroid Build Coastguard Worker 444*60517a1eSAndroid Build Coastguard Worker return py_info, deps_transitive_sources, builtin_py_info 445*60517a1eSAndroid Build Coastguard Worker 446*60517a1eSAndroid Build Coastguard Workerdef _get_py_info(target): 447*60517a1eSAndroid Build Coastguard Worker return target[PyInfo] if PyInfo in target else target[BuiltinPyInfo] 448*60517a1eSAndroid Build Coastguard Worker 449*60517a1eSAndroid Build Coastguard Workerdef create_instrumented_files_info(ctx): 450*60517a1eSAndroid Build Coastguard Worker return _coverage_common.instrumented_files_info( 451*60517a1eSAndroid Build Coastguard Worker ctx, 452*60517a1eSAndroid Build Coastguard Worker source_attributes = ["srcs"], 453*60517a1eSAndroid Build Coastguard Worker dependency_attributes = ["deps", "data"], 454*60517a1eSAndroid Build Coastguard Worker extensions = _PYTHON_SOURCE_EXTENSIONS, 455*60517a1eSAndroid Build Coastguard Worker ) 456*60517a1eSAndroid Build Coastguard Worker 457*60517a1eSAndroid Build Coastguard Workerdef create_output_group_info(transitive_sources, extra_groups): 458*60517a1eSAndroid Build Coastguard Worker return OutputGroupInfo( 459*60517a1eSAndroid Build Coastguard Worker compilation_prerequisites_INTERNAL_ = transitive_sources, 460*60517a1eSAndroid Build Coastguard Worker compilation_outputs = transitive_sources, 461*60517a1eSAndroid Build Coastguard Worker **extra_groups 462*60517a1eSAndroid Build Coastguard Worker ) 463*60517a1eSAndroid Build Coastguard Worker 464*60517a1eSAndroid Build Coastguard Workerdef maybe_add_test_execution_info(providers, ctx): 465*60517a1eSAndroid Build Coastguard Worker """Adds ExecutionInfo, if necessary for proper test execution. 466*60517a1eSAndroid Build Coastguard Worker 467*60517a1eSAndroid Build Coastguard Worker Args: 468*60517a1eSAndroid Build Coastguard Worker providers: Mutable list of providers; may have ExecutionInfo 469*60517a1eSAndroid Build Coastguard Worker provider appended. 470*60517a1eSAndroid Build Coastguard Worker ctx: Rule ctx. 471*60517a1eSAndroid Build Coastguard Worker """ 472*60517a1eSAndroid Build Coastguard Worker 473*60517a1eSAndroid Build Coastguard Worker # When built for Apple platforms, require the execution to be on a Mac. 474*60517a1eSAndroid Build Coastguard Worker # TODO(b/176993122): Remove when bazel automatically knows to run on darwin. 475*60517a1eSAndroid Build Coastguard Worker if target_platform_has_any_constraint(ctx, ctx.attr._apple_constraints): 476*60517a1eSAndroid Build Coastguard Worker providers.append(_testing.ExecutionInfo({"requires-darwin": ""})) 477*60517a1eSAndroid Build Coastguard Worker 478*60517a1eSAndroid Build Coastguard Worker_BOOL_TYPE = type(True) 479*60517a1eSAndroid Build Coastguard Worker 480*60517a1eSAndroid Build Coastguard Workerdef is_bool(v): 481*60517a1eSAndroid Build Coastguard Worker return type(v) == _BOOL_TYPE 482*60517a1eSAndroid Build Coastguard Worker 483*60517a1eSAndroid Build Coastguard Workerdef target_platform_has_any_constraint(ctx, constraints): 484*60517a1eSAndroid Build Coastguard Worker """Check if target platform has any of a list of constraints. 485*60517a1eSAndroid Build Coastguard Worker 486*60517a1eSAndroid Build Coastguard Worker Args: 487*60517a1eSAndroid Build Coastguard Worker ctx: rule context. 488*60517a1eSAndroid Build Coastguard Worker constraints: label_list of constraints. 489*60517a1eSAndroid Build Coastguard Worker 490*60517a1eSAndroid Build Coastguard Worker Returns: 491*60517a1eSAndroid Build Coastguard Worker True if target platform has at least one of the constraints. 492*60517a1eSAndroid Build Coastguard Worker """ 493*60517a1eSAndroid Build Coastguard Worker for constraint in constraints: 494*60517a1eSAndroid Build Coastguard Worker constraint_value = constraint[_platform_common.ConstraintValueInfo] 495*60517a1eSAndroid Build Coastguard Worker if ctx.target_platform_has_constraint(constraint_value): 496*60517a1eSAndroid Build Coastguard Worker return True 497*60517a1eSAndroid Build Coastguard Worker return False 498*60517a1eSAndroid Build Coastguard Worker 499*60517a1eSAndroid Build Coastguard Workerdef check_native_allowed(ctx): 500*60517a1eSAndroid Build Coastguard Worker """Check if the usage of the native rule is allowed. 501*60517a1eSAndroid Build Coastguard Worker 502*60517a1eSAndroid Build Coastguard Worker Args: 503*60517a1eSAndroid Build Coastguard Worker ctx: rule context to check 504*60517a1eSAndroid Build Coastguard Worker """ 505*60517a1eSAndroid Build Coastguard Worker if not ctx.fragments.py.disallow_native_rules: 506*60517a1eSAndroid Build Coastguard Worker return 507*60517a1eSAndroid Build Coastguard Worker 508*60517a1eSAndroid Build Coastguard Worker if _MIGRATION_TAG in ctx.attr.tags: 509*60517a1eSAndroid Build Coastguard Worker return 510*60517a1eSAndroid Build Coastguard Worker 511*60517a1eSAndroid Build Coastguard Worker # NOTE: The main repo name is empty in *labels*, but not in 512*60517a1eSAndroid Build Coastguard Worker # ctx.workspace_name 513*60517a1eSAndroid Build Coastguard Worker is_main_repo = not bool(ctx.label.workspace_name) 514*60517a1eSAndroid Build Coastguard Worker if is_main_repo: 515*60517a1eSAndroid Build Coastguard Worker check_label = ctx.label 516*60517a1eSAndroid Build Coastguard Worker else: 517*60517a1eSAndroid Build Coastguard Worker # package_group doesn't allow @repo syntax, so we work around that 518*60517a1eSAndroid Build Coastguard Worker # by prefixing external repos with a fake package path. This also 519*60517a1eSAndroid Build Coastguard Worker # makes it easy to enable or disable all external repos. 520*60517a1eSAndroid Build Coastguard Worker check_label = Label("@//__EXTERNAL_REPOS__/{workspace}/{package}".format( 521*60517a1eSAndroid Build Coastguard Worker workspace = ctx.label.workspace_name, 522*60517a1eSAndroid Build Coastguard Worker package = ctx.label.package, 523*60517a1eSAndroid Build Coastguard Worker )) 524*60517a1eSAndroid Build Coastguard Worker allowlist = ctx.attr._native_rules_allowlist 525*60517a1eSAndroid Build Coastguard Worker if allowlist: 526*60517a1eSAndroid Build Coastguard Worker allowed = ctx.attr._native_rules_allowlist[PackageSpecificationInfo].contains(check_label) 527*60517a1eSAndroid Build Coastguard Worker allowlist_help = str(allowlist.label).replace("@//", "//") 528*60517a1eSAndroid Build Coastguard Worker else: 529*60517a1eSAndroid Build Coastguard Worker allowed = False 530*60517a1eSAndroid Build Coastguard Worker allowlist_help = ("no allowlist specified; all disallowed; specify one " + 531*60517a1eSAndroid Build Coastguard Worker "with --python_native_rules_allowlist") 532*60517a1eSAndroid Build Coastguard Worker if not allowed: 533*60517a1eSAndroid Build Coastguard Worker if ctx.attr.generator_function: 534*60517a1eSAndroid Build Coastguard Worker generator = "{generator_function}(name={generator_name}) in {generator_location}".format( 535*60517a1eSAndroid Build Coastguard Worker generator_function = ctx.attr.generator_function, 536*60517a1eSAndroid Build Coastguard Worker generator_name = ctx.attr.generator_name, 537*60517a1eSAndroid Build Coastguard Worker generator_location = ctx.attr.generator_location, 538*60517a1eSAndroid Build Coastguard Worker ) 539*60517a1eSAndroid Build Coastguard Worker else: 540*60517a1eSAndroid Build Coastguard Worker generator = "No generator (called directly in BUILD file)" 541*60517a1eSAndroid Build Coastguard Worker 542*60517a1eSAndroid Build Coastguard Worker msg = ( 543*60517a1eSAndroid Build Coastguard Worker "{target} not allowed to use native.{rule}\n" + 544*60517a1eSAndroid Build Coastguard Worker "Generated by: {generator}\n" + 545*60517a1eSAndroid Build Coastguard Worker "Allowlist: {allowlist}\n" + 546*60517a1eSAndroid Build Coastguard Worker "Migrate to using @rules_python, see {help_url}\n" + 547*60517a1eSAndroid Build Coastguard Worker "FIXCMD: {fix_cmd} --target={target} --rule={rule} " + 548*60517a1eSAndroid Build Coastguard Worker "--generator_name={generator_name} --location={generator_location}" 549*60517a1eSAndroid Build Coastguard Worker ) 550*60517a1eSAndroid Build Coastguard Worker fail(msg.format( 551*60517a1eSAndroid Build Coastguard Worker target = str(ctx.label).replace("@//", "//"), 552*60517a1eSAndroid Build Coastguard Worker rule = _py_builtins.get_rule_name(ctx), 553*60517a1eSAndroid Build Coastguard Worker generator = generator, 554*60517a1eSAndroid Build Coastguard Worker allowlist = allowlist_help, 555*60517a1eSAndroid Build Coastguard Worker generator_name = ctx.attr.generator_name, 556*60517a1eSAndroid Build Coastguard Worker generator_location = ctx.attr.generator_location, 557*60517a1eSAndroid Build Coastguard Worker help_url = NATIVE_RULES_MIGRATION_HELP_URL, 558*60517a1eSAndroid Build Coastguard Worker fix_cmd = NATIVE_RULES_MIGRATION_FIX_CMD, 559*60517a1eSAndroid Build Coastguard Worker )) 560