# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. "Helpers for rules running on windows" # cmd.exe function for looking up runfiles. # Equivalent of the BASH_RLOCATION_FUNCTION in paths.bzl. # Use this to write actions that don't require bash. # Originally by @meteorcloudy in # https://github.com/bazelbuild/rules_nodejs/commit/f06553a BATCH_RLOCATION_FUNCTION = r""" rem Usage of rlocation function: rem call :rlocation rem The rlocation function maps the given to its absolute rem path and stores the result in a variable named . rem This function fails if the doesn't exist in mainifest rem file. :: Start of rlocation goto :rlocation_end :rlocation if "%~2" equ "" ( echo>&2 ERROR: Expected two arguments for rlocation function. exit 1 ) if "%RUNFILES_MANIFEST_ONLY%" neq "1" ( set %~2=%~1 exit /b 0 ) if exist "%RUNFILES_DIR%" ( set RUNFILES_MANIFEST_FILE=%RUNFILES_DIR%_manifest ) if "%RUNFILES_MANIFEST_FILE%" equ "" ( set RUNFILES_MANIFEST_FILE=%~f0.runfiles\MANIFEST ) if not exist "%RUNFILES_MANIFEST_FILE%" ( set RUNFILES_MANIFEST_FILE=%~f0.runfiles_manifest ) set MF=%RUNFILES_MANIFEST_FILE:/=\% if not exist "%MF%" ( echo>&2 ERROR: Manifest file %MF% does not exist. exit 1 ) set runfile_path=%~1 for /F "tokens=2* usebackq" %%i in (`%SYSTEMROOT%\system32\findstr.exe /l /c:"!runfile_path! " "%MF%"`) do ( set abs_path=%%i ) if "!abs_path!" equ "" ( echo>&2 ERROR: !runfile_path! not found in runfiles manifest exit 1 ) set %~2=!abs_path! exit /b 0 :rlocation_end :: End of rlocation """ def _to_manifest_path(ctx, file): if file.short_path.startswith("../"): return file.short_path[3:] else: return ctx.workspace_name + "/" + file.short_path def create_windows_native_launcher_script(ctx, shell_script): """Create a Windows Batch file to launch the given shell script. The rule should specify @bazel_tools//tools/sh:toolchain_type as a required toolchain. Args: ctx: Rule context shell_script: The bash launcher script Returns: A windows launcher script """ name = shell_script.basename if name.endswith(".sh"): name = name[:-3] win_launcher = ctx.actions.declare_file(name + ".bat", sibling = shell_script) ctx.actions.write( output = win_launcher, content = r"""@echo off SETLOCAL ENABLEEXTENSIONS SETLOCAL ENABLEDELAYEDEXPANSION set RUNFILES_MANIFEST_ONLY=1 {rlocation_function} call :rlocation "{sh_script}" run_script for %%a in ("{bash_bin}") do set "bash_bin_dir=%%~dpa" set PATH=%bash_bin_dir%;%PATH% set args=%* rem Escape \ and * in args before passsing it with double quote if defined args ( set args=!args:\=\\\\! set args=!args:"=\"! ) "{bash_bin}" -c "!run_script! !args!" """.format( bash_bin = ctx.toolchains["@bazel_tools//tools/sh:toolchain_type"].path, sh_script = _to_manifest_path(ctx, shell_script), rlocation_function = BATCH_RLOCATION_FUNCTION, ), is_executable = True, ) return win_launcher