-
Notifications
You must be signed in to change notification settings - Fork 522
/
windows_utils.bzl
116 lines (109 loc) · 3.63 KB
/
windows_utils.bzl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# 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.
"""Windows Utils
These functions help making rules work on Windows.
"""
BATCH_RLOCATION_FUNCTION = r"""
rem Usage of rlocation function:
rem call :rlocation <runfile_path> <abs_path>
rem The rlocation function maps the given <runfile_path> to its absolute
rem path and stores the result in a variable named <abs_path>.
rem This function fails if the <runfile_path> 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 is_windows(ctx):
"""
Check if we are building for Windows.
"""
# Only on Windows the path separator would be ';'
# We should switch to a proper API after
# https://github.com/bazelbuild/bazel/issues/9209 is resolved.
return ctx.configuration.host_path_separator == ";"
# Avoid using non-normalized paths (workspace/../other_workspace/path)
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.
"""
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