1*60517a1eSAndroid Build Coastguard Worker# Copyright 2024 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 15*60517a1eSAndroid Build Coastguard Worker"""Functionality shared only by repository rule phase code. 16*60517a1eSAndroid Build Coastguard Worker 17*60517a1eSAndroid Build Coastguard WorkerThis code should only be loaded and used during the repository phase. 18*60517a1eSAndroid Build Coastguard Worker""" 19*60517a1eSAndroid Build Coastguard Worker 20*60517a1eSAndroid Build Coastguard WorkerREPO_DEBUG_ENV_VAR = "RULES_PYTHON_REPO_DEBUG" 21*60517a1eSAndroid Build Coastguard WorkerREPO_VERBOSITY_ENV_VAR = "RULES_PYTHON_REPO_DEBUG_VERBOSITY" 22*60517a1eSAndroid Build Coastguard Worker 23*60517a1eSAndroid Build Coastguard Workerdef _is_repo_debug_enabled(mrctx): 24*60517a1eSAndroid Build Coastguard Worker """Tells if debbugging output is requested during repo operatiosn. 25*60517a1eSAndroid Build Coastguard Worker 26*60517a1eSAndroid Build Coastguard Worker Args: 27*60517a1eSAndroid Build Coastguard Worker mrctx: repository_ctx or module_ctx object 28*60517a1eSAndroid Build Coastguard Worker 29*60517a1eSAndroid Build Coastguard Worker Returns: 30*60517a1eSAndroid Build Coastguard Worker True if enabled, False if not. 31*60517a1eSAndroid Build Coastguard Worker """ 32*60517a1eSAndroid Build Coastguard Worker return _getenv(mrctx, REPO_DEBUG_ENV_VAR) == "1" 33*60517a1eSAndroid Build Coastguard Worker 34*60517a1eSAndroid Build Coastguard Workerdef _logger(mrctx, name = None): 35*60517a1eSAndroid Build Coastguard Worker """Creates a logger instance for printing messages. 36*60517a1eSAndroid Build Coastguard Worker 37*60517a1eSAndroid Build Coastguard Worker Args: 38*60517a1eSAndroid Build Coastguard Worker mrctx: repository_ctx or module_ctx object. If the attribute 39*60517a1eSAndroid Build Coastguard Worker `_rule_name` is present, it will be included in log messages. 40*60517a1eSAndroid Build Coastguard Worker name: name for the logger. Optional for repository_ctx usage. 41*60517a1eSAndroid Build Coastguard Worker 42*60517a1eSAndroid Build Coastguard Worker Returns: 43*60517a1eSAndroid Build Coastguard Worker A struct with attributes logging: trace, debug, info, warn, fail. 44*60517a1eSAndroid Build Coastguard Worker """ 45*60517a1eSAndroid Build Coastguard Worker if _is_repo_debug_enabled(mrctx): 46*60517a1eSAndroid Build Coastguard Worker verbosity_level = "DEBUG" 47*60517a1eSAndroid Build Coastguard Worker else: 48*60517a1eSAndroid Build Coastguard Worker verbosity_level = "WARN" 49*60517a1eSAndroid Build Coastguard Worker 50*60517a1eSAndroid Build Coastguard Worker env_var_verbosity = _getenv(mrctx, REPO_VERBOSITY_ENV_VAR) 51*60517a1eSAndroid Build Coastguard Worker verbosity_level = env_var_verbosity or verbosity_level 52*60517a1eSAndroid Build Coastguard Worker 53*60517a1eSAndroid Build Coastguard Worker verbosity = { 54*60517a1eSAndroid Build Coastguard Worker "DEBUG": 2, 55*60517a1eSAndroid Build Coastguard Worker "INFO": 1, 56*60517a1eSAndroid Build Coastguard Worker "TRACE": 3, 57*60517a1eSAndroid Build Coastguard Worker }.get(verbosity_level, 0) 58*60517a1eSAndroid Build Coastguard Worker 59*60517a1eSAndroid Build Coastguard Worker if hasattr(mrctx, "attr"): 60*60517a1eSAndroid Build Coastguard Worker rctx = mrctx # This is `repository_ctx`. 61*60517a1eSAndroid Build Coastguard Worker name = name or "{}(@@{})".format(getattr(rctx.attr, "_rule_name", "?"), rctx.name) 62*60517a1eSAndroid Build Coastguard Worker elif not name: 63*60517a1eSAndroid Build Coastguard Worker fail("The name has to be specified when using the logger with `module_ctx`") 64*60517a1eSAndroid Build Coastguard Worker 65*60517a1eSAndroid Build Coastguard Worker def _log(enabled_on_verbosity, level, message_cb_or_str, printer = print): 66*60517a1eSAndroid Build Coastguard Worker if verbosity < enabled_on_verbosity: 67*60517a1eSAndroid Build Coastguard Worker return 68*60517a1eSAndroid Build Coastguard Worker 69*60517a1eSAndroid Build Coastguard Worker if type(message_cb_or_str) == "string": 70*60517a1eSAndroid Build Coastguard Worker message = message_cb_or_str 71*60517a1eSAndroid Build Coastguard Worker else: 72*60517a1eSAndroid Build Coastguard Worker message = message_cb_or_str() 73*60517a1eSAndroid Build Coastguard Worker 74*60517a1eSAndroid Build Coastguard Worker # NOTE: printer may be the `fail` function. 75*60517a1eSAndroid Build Coastguard Worker printer("\nrules_python:{} {}:".format( 76*60517a1eSAndroid Build Coastguard Worker name, 77*60517a1eSAndroid Build Coastguard Worker level.upper(), 78*60517a1eSAndroid Build Coastguard Worker ), message) # buildifier: disable=print 79*60517a1eSAndroid Build Coastguard Worker 80*60517a1eSAndroid Build Coastguard Worker return struct( 81*60517a1eSAndroid Build Coastguard Worker trace = lambda message_cb: _log(3, "TRACE", message_cb), 82*60517a1eSAndroid Build Coastguard Worker debug = lambda message_cb: _log(2, "DEBUG", message_cb), 83*60517a1eSAndroid Build Coastguard Worker info = lambda message_cb: _log(1, "INFO", message_cb), 84*60517a1eSAndroid Build Coastguard Worker warn = lambda message_cb: _log(0, "WARNING", message_cb), 85*60517a1eSAndroid Build Coastguard Worker fail = lambda message_cb: _log(-1, "FAIL", message_cb, fail), 86*60517a1eSAndroid Build Coastguard Worker ) 87*60517a1eSAndroid Build Coastguard Worker 88*60517a1eSAndroid Build Coastguard Workerdef _execute_internal( 89*60517a1eSAndroid Build Coastguard Worker mrctx, 90*60517a1eSAndroid Build Coastguard Worker *, 91*60517a1eSAndroid Build Coastguard Worker op, 92*60517a1eSAndroid Build Coastguard Worker fail_on_error = False, 93*60517a1eSAndroid Build Coastguard Worker arguments, 94*60517a1eSAndroid Build Coastguard Worker environment = {}, 95*60517a1eSAndroid Build Coastguard Worker logger = None, 96*60517a1eSAndroid Build Coastguard Worker **kwargs): 97*60517a1eSAndroid Build Coastguard Worker """Execute a subprocess with debugging instrumentation. 98*60517a1eSAndroid Build Coastguard Worker 99*60517a1eSAndroid Build Coastguard Worker Args: 100*60517a1eSAndroid Build Coastguard Worker mrctx: module_ctx or repository_ctx object 101*60517a1eSAndroid Build Coastguard Worker op: string, brief description of the operation this command 102*60517a1eSAndroid Build Coastguard Worker represents. Used to succintly describe it in logging and 103*60517a1eSAndroid Build Coastguard Worker error messages. 104*60517a1eSAndroid Build Coastguard Worker fail_on_error: bool, True if fail() should be called if the command 105*60517a1eSAndroid Build Coastguard Worker fails (non-zero exit code), False if not. 106*60517a1eSAndroid Build Coastguard Worker arguments: list of arguments; see module_ctx.execute#arguments or 107*60517a1eSAndroid Build Coastguard Worker repository_ctx#arguments. 108*60517a1eSAndroid Build Coastguard Worker environment: optional dict of the environment to run the command 109*60517a1eSAndroid Build Coastguard Worker in; see module_ctx.execute#environment or 110*60517a1eSAndroid Build Coastguard Worker repository_ctx.execute#environment. 111*60517a1eSAndroid Build Coastguard Worker logger: optional `Logger` to use for logging execution details. Must be 112*60517a1eSAndroid Build Coastguard Worker specified when using module_ctx. If not specified, a default will 113*60517a1eSAndroid Build Coastguard Worker be created. 114*60517a1eSAndroid Build Coastguard Worker **kwargs: additional kwargs to pass onto rctx.execute 115*60517a1eSAndroid Build Coastguard Worker 116*60517a1eSAndroid Build Coastguard Worker Returns: 117*60517a1eSAndroid Build Coastguard Worker exec_result object, see repository_ctx.execute return type. 118*60517a1eSAndroid Build Coastguard Worker """ 119*60517a1eSAndroid Build Coastguard Worker if not logger and hasattr(mrctx, "attr"): 120*60517a1eSAndroid Build Coastguard Worker rctx = mrctx 121*60517a1eSAndroid Build Coastguard Worker logger = _logger(rctx) 122*60517a1eSAndroid Build Coastguard Worker elif not logger: 123*60517a1eSAndroid Build Coastguard Worker fail("logger must be specified when using 'module_ctx'") 124*60517a1eSAndroid Build Coastguard Worker 125*60517a1eSAndroid Build Coastguard Worker logger.debug(lambda: ( 126*60517a1eSAndroid Build Coastguard Worker "repo.execute: {op}: start\n" + 127*60517a1eSAndroid Build Coastguard Worker " command: {cmd}\n" + 128*60517a1eSAndroid Build Coastguard Worker " working dir: {cwd}\n" + 129*60517a1eSAndroid Build Coastguard Worker " timeout: {timeout}\n" + 130*60517a1eSAndroid Build Coastguard Worker " environment:{env_str}\n" 131*60517a1eSAndroid Build Coastguard Worker ).format( 132*60517a1eSAndroid Build Coastguard Worker op = op, 133*60517a1eSAndroid Build Coastguard Worker cmd = _args_to_str(arguments), 134*60517a1eSAndroid Build Coastguard Worker cwd = _cwd_to_str(mrctx, kwargs), 135*60517a1eSAndroid Build Coastguard Worker timeout = _timeout_to_str(kwargs), 136*60517a1eSAndroid Build Coastguard Worker env_str = _env_to_str(environment), 137*60517a1eSAndroid Build Coastguard Worker )) 138*60517a1eSAndroid Build Coastguard Worker 139*60517a1eSAndroid Build Coastguard Worker mrctx.report_progress("Running {}".format(op)) 140*60517a1eSAndroid Build Coastguard Worker result = mrctx.execute(arguments, environment = environment, **kwargs) 141*60517a1eSAndroid Build Coastguard Worker 142*60517a1eSAndroid Build Coastguard Worker if fail_on_error and result.return_code != 0: 143*60517a1eSAndroid Build Coastguard Worker logger.fail(( 144*60517a1eSAndroid Build Coastguard Worker "repo.execute: {op}: end: failure:\n" + 145*60517a1eSAndroid Build Coastguard Worker " command: {cmd}\n" + 146*60517a1eSAndroid Build Coastguard Worker " return code: {return_code}\n" + 147*60517a1eSAndroid Build Coastguard Worker " working dir: {cwd}\n" + 148*60517a1eSAndroid Build Coastguard Worker " timeout: {timeout}\n" + 149*60517a1eSAndroid Build Coastguard Worker " environment:{env_str}\n" + 150*60517a1eSAndroid Build Coastguard Worker "{output}" 151*60517a1eSAndroid Build Coastguard Worker ).format( 152*60517a1eSAndroid Build Coastguard Worker op = op, 153*60517a1eSAndroid Build Coastguard Worker cmd = _args_to_str(arguments), 154*60517a1eSAndroid Build Coastguard Worker return_code = result.return_code, 155*60517a1eSAndroid Build Coastguard Worker cwd = _cwd_to_str(mrctx, kwargs), 156*60517a1eSAndroid Build Coastguard Worker timeout = _timeout_to_str(kwargs), 157*60517a1eSAndroid Build Coastguard Worker env_str = _env_to_str(environment), 158*60517a1eSAndroid Build Coastguard Worker output = _outputs_to_str(result), 159*60517a1eSAndroid Build Coastguard Worker )) 160*60517a1eSAndroid Build Coastguard Worker elif _is_repo_debug_enabled(mrctx): 161*60517a1eSAndroid Build Coastguard Worker logger.debug(( 162*60517a1eSAndroid Build Coastguard Worker "repo.execute: {op}: end: {status}\n" + 163*60517a1eSAndroid Build Coastguard Worker " return code: {return_code}\n" + 164*60517a1eSAndroid Build Coastguard Worker "{output}" 165*60517a1eSAndroid Build Coastguard Worker ).format( 166*60517a1eSAndroid Build Coastguard Worker op = op, 167*60517a1eSAndroid Build Coastguard Worker status = "success" if result.return_code == 0 else "failure", 168*60517a1eSAndroid Build Coastguard Worker return_code = result.return_code, 169*60517a1eSAndroid Build Coastguard Worker output = _outputs_to_str(result), 170*60517a1eSAndroid Build Coastguard Worker )) 171*60517a1eSAndroid Build Coastguard Worker 172*60517a1eSAndroid Build Coastguard Worker result_kwargs = {k: getattr(result, k) for k in dir(result)} 173*60517a1eSAndroid Build Coastguard Worker return struct( 174*60517a1eSAndroid Build Coastguard Worker describe_failure = lambda: _execute_describe_failure( 175*60517a1eSAndroid Build Coastguard Worker op = op, 176*60517a1eSAndroid Build Coastguard Worker arguments = arguments, 177*60517a1eSAndroid Build Coastguard Worker result = result, 178*60517a1eSAndroid Build Coastguard Worker mrctx = mrctx, 179*60517a1eSAndroid Build Coastguard Worker kwargs = kwargs, 180*60517a1eSAndroid Build Coastguard Worker environment = environment, 181*60517a1eSAndroid Build Coastguard Worker ), 182*60517a1eSAndroid Build Coastguard Worker **result_kwargs 183*60517a1eSAndroid Build Coastguard Worker ) 184*60517a1eSAndroid Build Coastguard Worker 185*60517a1eSAndroid Build Coastguard Workerdef _execute_unchecked(*args, **kwargs): 186*60517a1eSAndroid Build Coastguard Worker """Execute a subprocess. 187*60517a1eSAndroid Build Coastguard Worker 188*60517a1eSAndroid Build Coastguard Worker Additional information will be printed if debug output is enabled. 189*60517a1eSAndroid Build Coastguard Worker 190*60517a1eSAndroid Build Coastguard Worker Args: 191*60517a1eSAndroid Build Coastguard Worker *args: see _execute_internal 192*60517a1eSAndroid Build Coastguard Worker **kwargs: see _execute_internal 193*60517a1eSAndroid Build Coastguard Worker 194*60517a1eSAndroid Build Coastguard Worker Returns: 195*60517a1eSAndroid Build Coastguard Worker exec_result object, see repository_ctx.execute return type. 196*60517a1eSAndroid Build Coastguard Worker """ 197*60517a1eSAndroid Build Coastguard Worker return _execute_internal(fail_on_error = False, *args, **kwargs) 198*60517a1eSAndroid Build Coastguard Worker 199*60517a1eSAndroid Build Coastguard Workerdef _execute_checked(*args, **kwargs): 200*60517a1eSAndroid Build Coastguard Worker """Execute a subprocess, failing for a non-zero exit code. 201*60517a1eSAndroid Build Coastguard Worker 202*60517a1eSAndroid Build Coastguard Worker If the command fails, then fail() is called with detailed information 203*60517a1eSAndroid Build Coastguard Worker about the command and its failure. 204*60517a1eSAndroid Build Coastguard Worker 205*60517a1eSAndroid Build Coastguard Worker Args: 206*60517a1eSAndroid Build Coastguard Worker *args: see _execute_internal 207*60517a1eSAndroid Build Coastguard Worker **kwargs: see _execute_internal 208*60517a1eSAndroid Build Coastguard Worker 209*60517a1eSAndroid Build Coastguard Worker Returns: 210*60517a1eSAndroid Build Coastguard Worker exec_result object, see repository_ctx.execute return type. 211*60517a1eSAndroid Build Coastguard Worker """ 212*60517a1eSAndroid Build Coastguard Worker return _execute_internal(fail_on_error = True, *args, **kwargs) 213*60517a1eSAndroid Build Coastguard Worker 214*60517a1eSAndroid Build Coastguard Workerdef _execute_checked_stdout(*args, **kwargs): 215*60517a1eSAndroid Build Coastguard Worker """Calls execute_checked, but only returns the stdout value.""" 216*60517a1eSAndroid Build Coastguard Worker return _execute_checked(*args, **kwargs).stdout 217*60517a1eSAndroid Build Coastguard Worker 218*60517a1eSAndroid Build Coastguard Workerdef _execute_describe_failure(*, op, arguments, result, mrctx, kwargs, environment): 219*60517a1eSAndroid Build Coastguard Worker return ( 220*60517a1eSAndroid Build Coastguard Worker "repo.execute: {op}: failure:\n" + 221*60517a1eSAndroid Build Coastguard Worker " command: {cmd}\n" + 222*60517a1eSAndroid Build Coastguard Worker " return code: {return_code}\n" + 223*60517a1eSAndroid Build Coastguard Worker " working dir: {cwd}\n" + 224*60517a1eSAndroid Build Coastguard Worker " timeout: {timeout}\n" + 225*60517a1eSAndroid Build Coastguard Worker " environment:{env_str}\n" + 226*60517a1eSAndroid Build Coastguard Worker "{output}" 227*60517a1eSAndroid Build Coastguard Worker ).format( 228*60517a1eSAndroid Build Coastguard Worker op = op, 229*60517a1eSAndroid Build Coastguard Worker cmd = _args_to_str(arguments), 230*60517a1eSAndroid Build Coastguard Worker return_code = result.return_code, 231*60517a1eSAndroid Build Coastguard Worker cwd = _cwd_to_str(mrctx, kwargs), 232*60517a1eSAndroid Build Coastguard Worker timeout = _timeout_to_str(kwargs), 233*60517a1eSAndroid Build Coastguard Worker env_str = _env_to_str(environment), 234*60517a1eSAndroid Build Coastguard Worker output = _outputs_to_str(result), 235*60517a1eSAndroid Build Coastguard Worker ) 236*60517a1eSAndroid Build Coastguard Worker 237*60517a1eSAndroid Build Coastguard Workerdef _which_checked(mrctx, binary_name): 238*60517a1eSAndroid Build Coastguard Worker """Tests to see if a binary exists, and otherwise fails with a message. 239*60517a1eSAndroid Build Coastguard Worker 240*60517a1eSAndroid Build Coastguard Worker Args: 241*60517a1eSAndroid Build Coastguard Worker binary_name: name of the binary to find. 242*60517a1eSAndroid Build Coastguard Worker mrctx: module_ctx or repository_ctx. 243*60517a1eSAndroid Build Coastguard Worker 244*60517a1eSAndroid Build Coastguard Worker Returns: 245*60517a1eSAndroid Build Coastguard Worker mrctx.Path for the binary. 246*60517a1eSAndroid Build Coastguard Worker """ 247*60517a1eSAndroid Build Coastguard Worker result = _which_unchecked(mrctx, binary_name) 248*60517a1eSAndroid Build Coastguard Worker if result.binary == None: 249*60517a1eSAndroid Build Coastguard Worker fail(result.describe_failure()) 250*60517a1eSAndroid Build Coastguard Worker return result.binary 251*60517a1eSAndroid Build Coastguard Worker 252*60517a1eSAndroid Build Coastguard Workerdef _which_unchecked(mrctx, binary_name): 253*60517a1eSAndroid Build Coastguard Worker """Tests to see if a binary exists. 254*60517a1eSAndroid Build Coastguard Worker 255*60517a1eSAndroid Build Coastguard Worker This is also watch the `PATH` environment variable. 256*60517a1eSAndroid Build Coastguard Worker 257*60517a1eSAndroid Build Coastguard Worker Args: 258*60517a1eSAndroid Build Coastguard Worker binary_name: name of the binary to find. 259*60517a1eSAndroid Build Coastguard Worker mrctx: repository context. 260*60517a1eSAndroid Build Coastguard Worker 261*60517a1eSAndroid Build Coastguard Worker Returns: 262*60517a1eSAndroid Build Coastguard Worker `struct` with attributes: 263*60517a1eSAndroid Build Coastguard Worker * `binary`: `repository_ctx.Path` 264*60517a1eSAndroid Build Coastguard Worker * `describe_failure`: `Callable | None`; takes no args. If the 265*60517a1eSAndroid Build Coastguard Worker binary couldn't be found, provides a detailed error description. 266*60517a1eSAndroid Build Coastguard Worker """ 267*60517a1eSAndroid Build Coastguard Worker path = _getenv(mrctx, "PATH", "") 268*60517a1eSAndroid Build Coastguard Worker binary = mrctx.which(binary_name) 269*60517a1eSAndroid Build Coastguard Worker if binary: 270*60517a1eSAndroid Build Coastguard Worker _watch(mrctx, binary) 271*60517a1eSAndroid Build Coastguard Worker describe_failure = None 272*60517a1eSAndroid Build Coastguard Worker else: 273*60517a1eSAndroid Build Coastguard Worker describe_failure = lambda: _which_describe_failure(binary_name, path) 274*60517a1eSAndroid Build Coastguard Worker 275*60517a1eSAndroid Build Coastguard Worker return struct( 276*60517a1eSAndroid Build Coastguard Worker binary = binary, 277*60517a1eSAndroid Build Coastguard Worker describe_failure = describe_failure, 278*60517a1eSAndroid Build Coastguard Worker ) 279*60517a1eSAndroid Build Coastguard Worker 280*60517a1eSAndroid Build Coastguard Workerdef _which_describe_failure(binary_name, path): 281*60517a1eSAndroid Build Coastguard Worker return ( 282*60517a1eSAndroid Build Coastguard Worker "Unable to find the binary '{binary_name}' on PATH.\n" + 283*60517a1eSAndroid Build Coastguard Worker " PATH = {path}" 284*60517a1eSAndroid Build Coastguard Worker ).format( 285*60517a1eSAndroid Build Coastguard Worker binary_name = binary_name, 286*60517a1eSAndroid Build Coastguard Worker path = path, 287*60517a1eSAndroid Build Coastguard Worker ) 288*60517a1eSAndroid Build Coastguard Worker 289*60517a1eSAndroid Build Coastguard Workerdef _getenv(mrctx, name, default = None): 290*60517a1eSAndroid Build Coastguard Worker # Bazel 7+ API has (repository|module)_ctx.getenv 291*60517a1eSAndroid Build Coastguard Worker return getattr(mrctx, "getenv", mrctx.os.environ.get)(name, default) 292*60517a1eSAndroid Build Coastguard Worker 293*60517a1eSAndroid Build Coastguard Workerdef _args_to_str(arguments): 294*60517a1eSAndroid Build Coastguard Worker return " ".join([_arg_repr(a) for a in arguments]) 295*60517a1eSAndroid Build Coastguard Worker 296*60517a1eSAndroid Build Coastguard Workerdef _arg_repr(value): 297*60517a1eSAndroid Build Coastguard Worker if _arg_should_be_quoted(value): 298*60517a1eSAndroid Build Coastguard Worker return repr(value) 299*60517a1eSAndroid Build Coastguard Worker else: 300*60517a1eSAndroid Build Coastguard Worker return str(value) 301*60517a1eSAndroid Build Coastguard Worker 302*60517a1eSAndroid Build Coastguard Worker_SPECIAL_SHELL_CHARS = [" ", "'", '"', "{", "$", "("] 303*60517a1eSAndroid Build Coastguard Worker 304*60517a1eSAndroid Build Coastguard Workerdef _arg_should_be_quoted(value): 305*60517a1eSAndroid Build Coastguard Worker # `value` may be non-str, such as mrctx.path objects 306*60517a1eSAndroid Build Coastguard Worker value_str = str(value) 307*60517a1eSAndroid Build Coastguard Worker for char in _SPECIAL_SHELL_CHARS: 308*60517a1eSAndroid Build Coastguard Worker if char in value_str: 309*60517a1eSAndroid Build Coastguard Worker return True 310*60517a1eSAndroid Build Coastguard Worker return False 311*60517a1eSAndroid Build Coastguard Worker 312*60517a1eSAndroid Build Coastguard Workerdef _cwd_to_str(mrctx, kwargs): 313*60517a1eSAndroid Build Coastguard Worker cwd = kwargs.get("working_directory") 314*60517a1eSAndroid Build Coastguard Worker if not cwd: 315*60517a1eSAndroid Build Coastguard Worker cwd = "<default: {}>".format(mrctx.path("")) 316*60517a1eSAndroid Build Coastguard Worker return cwd 317*60517a1eSAndroid Build Coastguard Worker 318*60517a1eSAndroid Build Coastguard Workerdef _env_to_str(environment): 319*60517a1eSAndroid Build Coastguard Worker if not environment: 320*60517a1eSAndroid Build Coastguard Worker env_str = " <default environment>" 321*60517a1eSAndroid Build Coastguard Worker else: 322*60517a1eSAndroid Build Coastguard Worker env_str = "\n".join(["{}={}".format(k, repr(v)) for k, v in environment.items()]) 323*60517a1eSAndroid Build Coastguard Worker env_str = "\n" + env_str 324*60517a1eSAndroid Build Coastguard Worker return env_str 325*60517a1eSAndroid Build Coastguard Worker 326*60517a1eSAndroid Build Coastguard Workerdef _timeout_to_str(kwargs): 327*60517a1eSAndroid Build Coastguard Worker return kwargs.get("timeout", "<default timeout>") 328*60517a1eSAndroid Build Coastguard Worker 329*60517a1eSAndroid Build Coastguard Workerdef _outputs_to_str(result): 330*60517a1eSAndroid Build Coastguard Worker lines = [] 331*60517a1eSAndroid Build Coastguard Worker items = [ 332*60517a1eSAndroid Build Coastguard Worker ("stdout", result.stdout), 333*60517a1eSAndroid Build Coastguard Worker ("stderr", result.stderr), 334*60517a1eSAndroid Build Coastguard Worker ] 335*60517a1eSAndroid Build Coastguard Worker for name, content in items: 336*60517a1eSAndroid Build Coastguard Worker if content: 337*60517a1eSAndroid Build Coastguard Worker lines.append("===== {} start =====".format(name)) 338*60517a1eSAndroid Build Coastguard Worker 339*60517a1eSAndroid Build Coastguard Worker # Prevent adding an extra new line, which makes the output look odd. 340*60517a1eSAndroid Build Coastguard Worker if content.endswith("\n"): 341*60517a1eSAndroid Build Coastguard Worker lines.append(content[:-1]) 342*60517a1eSAndroid Build Coastguard Worker else: 343*60517a1eSAndroid Build Coastguard Worker lines.append(content) 344*60517a1eSAndroid Build Coastguard Worker lines.append("===== {} end =====".format(name)) 345*60517a1eSAndroid Build Coastguard Worker else: 346*60517a1eSAndroid Build Coastguard Worker lines.append("<{} empty>".format(name)) 347*60517a1eSAndroid Build Coastguard Worker return "\n".join(lines) 348*60517a1eSAndroid Build Coastguard Worker 349*60517a1eSAndroid Build Coastguard Worker# This includes the vendored _translate_cpu and _translate_os from 350*60517a1eSAndroid Build Coastguard Worker# @platforms//host:extension.bzl at version 0.0.9 so that we don't 351*60517a1eSAndroid Build Coastguard Worker# force the users to depend on it. 352*60517a1eSAndroid Build Coastguard Worker 353*60517a1eSAndroid Build Coastguard Workerdef _get_platforms_os_name(mrctx): 354*60517a1eSAndroid Build Coastguard Worker """Return the name in @platforms//os for the host os. 355*60517a1eSAndroid Build Coastguard Worker 356*60517a1eSAndroid Build Coastguard Worker Args: 357*60517a1eSAndroid Build Coastguard Worker mrctx: module_ctx or repository_ctx. 358*60517a1eSAndroid Build Coastguard Worker 359*60517a1eSAndroid Build Coastguard Worker Returns: 360*60517a1eSAndroid Build Coastguard Worker `str`. The target name. 361*60517a1eSAndroid Build Coastguard Worker """ 362*60517a1eSAndroid Build Coastguard Worker os = mrctx.os.name.lower() 363*60517a1eSAndroid Build Coastguard Worker 364*60517a1eSAndroid Build Coastguard Worker if os.startswith("mac os"): 365*60517a1eSAndroid Build Coastguard Worker return "osx" 366*60517a1eSAndroid Build Coastguard Worker if os.startswith("freebsd"): 367*60517a1eSAndroid Build Coastguard Worker return "freebsd" 368*60517a1eSAndroid Build Coastguard Worker if os.startswith("openbsd"): 369*60517a1eSAndroid Build Coastguard Worker return "openbsd" 370*60517a1eSAndroid Build Coastguard Worker if os.startswith("linux"): 371*60517a1eSAndroid Build Coastguard Worker return "linux" 372*60517a1eSAndroid Build Coastguard Worker if os.startswith("windows"): 373*60517a1eSAndroid Build Coastguard Worker return "windows" 374*60517a1eSAndroid Build Coastguard Worker return os 375*60517a1eSAndroid Build Coastguard Worker 376*60517a1eSAndroid Build Coastguard Workerdef _get_platforms_cpu_name(mrctx): 377*60517a1eSAndroid Build Coastguard Worker """Return the name in @platforms//cpu for the host arch. 378*60517a1eSAndroid Build Coastguard Worker 379*60517a1eSAndroid Build Coastguard Worker Args: 380*60517a1eSAndroid Build Coastguard Worker mrctx: module_ctx or repository_ctx. 381*60517a1eSAndroid Build Coastguard Worker 382*60517a1eSAndroid Build Coastguard Worker Returns: 383*60517a1eSAndroid Build Coastguard Worker `str`. The target name. 384*60517a1eSAndroid Build Coastguard Worker """ 385*60517a1eSAndroid Build Coastguard Worker arch = mrctx.os.arch.lower() 386*60517a1eSAndroid Build Coastguard Worker if arch in ["i386", "i486", "i586", "i686", "i786", "x86"]: 387*60517a1eSAndroid Build Coastguard Worker return "x86_32" 388*60517a1eSAndroid Build Coastguard Worker if arch in ["amd64", "x86_64", "x64"]: 389*60517a1eSAndroid Build Coastguard Worker return "x86_64" 390*60517a1eSAndroid Build Coastguard Worker if arch in ["ppc", "ppc64", "ppc64le"]: 391*60517a1eSAndroid Build Coastguard Worker return "ppc" 392*60517a1eSAndroid Build Coastguard Worker if arch in ["arm", "armv7l"]: 393*60517a1eSAndroid Build Coastguard Worker return "arm" 394*60517a1eSAndroid Build Coastguard Worker if arch in ["aarch64"]: 395*60517a1eSAndroid Build Coastguard Worker return "aarch64" 396*60517a1eSAndroid Build Coastguard Worker if arch in ["s390x", "s390"]: 397*60517a1eSAndroid Build Coastguard Worker return "s390x" 398*60517a1eSAndroid Build Coastguard Worker if arch in ["mips64el", "mips64"]: 399*60517a1eSAndroid Build Coastguard Worker return "mips64" 400*60517a1eSAndroid Build Coastguard Worker if arch in ["riscv64"]: 401*60517a1eSAndroid Build Coastguard Worker return "riscv64" 402*60517a1eSAndroid Build Coastguard Worker return arch 403*60517a1eSAndroid Build Coastguard Worker 404*60517a1eSAndroid Build Coastguard Worker# TODO: Remove after Bazel 6 support dropped 405*60517a1eSAndroid Build Coastguard Workerdef _watch(mrctx, *args, **kwargs): 406*60517a1eSAndroid Build Coastguard Worker """Calls mrctx.watch, if available.""" 407*60517a1eSAndroid Build Coastguard Worker if not args and not kwargs: 408*60517a1eSAndroid Build Coastguard Worker fail("'watch' needs at least a single argument.") 409*60517a1eSAndroid Build Coastguard Worker 410*60517a1eSAndroid Build Coastguard Worker if hasattr(mrctx, "watch"): 411*60517a1eSAndroid Build Coastguard Worker mrctx.watch(*args, **kwargs) 412*60517a1eSAndroid Build Coastguard Worker 413*60517a1eSAndroid Build Coastguard Worker# TODO: Remove after Bazel 6 support dropped 414*60517a1eSAndroid Build Coastguard Workerdef _watch_tree(mrctx, *args, **kwargs): 415*60517a1eSAndroid Build Coastguard Worker """Calls mrctx.watch_tree, if available.""" 416*60517a1eSAndroid Build Coastguard Worker if not args and not kwargs: 417*60517a1eSAndroid Build Coastguard Worker fail("'watch_tree' needs at least a single argument.") 418*60517a1eSAndroid Build Coastguard Worker 419*60517a1eSAndroid Build Coastguard Worker if hasattr(mrctx, "watch_tree"): 420*60517a1eSAndroid Build Coastguard Worker mrctx.watch_tree(*args, **kwargs) 421*60517a1eSAndroid Build Coastguard Worker 422*60517a1eSAndroid Build Coastguard Workerrepo_utils = struct( 423*60517a1eSAndroid Build Coastguard Worker # keep sorted 424*60517a1eSAndroid Build Coastguard Worker execute_checked = _execute_checked, 425*60517a1eSAndroid Build Coastguard Worker execute_checked_stdout = _execute_checked_stdout, 426*60517a1eSAndroid Build Coastguard Worker execute_unchecked = _execute_unchecked, 427*60517a1eSAndroid Build Coastguard Worker get_platforms_cpu_name = _get_platforms_cpu_name, 428*60517a1eSAndroid Build Coastguard Worker get_platforms_os_name = _get_platforms_os_name, 429*60517a1eSAndroid Build Coastguard Worker getenv = _getenv, 430*60517a1eSAndroid Build Coastguard Worker is_repo_debug_enabled = _is_repo_debug_enabled, 431*60517a1eSAndroid Build Coastguard Worker logger = _logger, 432*60517a1eSAndroid Build Coastguard Worker watch = _watch, 433*60517a1eSAndroid Build Coastguard Worker watch_tree = _watch_tree, 434*60517a1eSAndroid Build Coastguard Worker which_checked = _which_checked, 435*60517a1eSAndroid Build Coastguard Worker which_unchecked = _which_unchecked, 436*60517a1eSAndroid Build Coastguard Worker) 437