blob: 7a11a26aa9a828dae857347080b68674698fd184 [file] [log] [blame]
# Copyright 2019 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.
"""Configure local Resource Compilers for every available target platform.
Platform support:
- Linux/macOS/non-Windows: this repository rule is almost a no-op.
It generates an empty BUILD file, and does not actually discover any
toolchains. The register_local_rc_exe_toolchains() method is a no-op.
- Windows: this repository rule discovers the Windows SDK path, the installed
rc.exe compilers. The register_local_rc_exe_toolchains() registers a toolchain
for each rc.exe compiler.
Usage:
load("//src/main/res:winsdk_configure.bzl", "winsdk_configure")
winsdk_configure(name = "local_config_winsdk")
load("@local_config_winsdk//:toolchains.bzl", "register_local_rc_exe_toolchains")
register_local_rc_exe_toolchains()
"""
load("@bazel_tools//tools/cpp:cc_configure.bzl", "MSVC_ENVVARS")
load("@bazel_tools//tools/cpp:windows_cc_configure.bzl", "find_vc_path", "setup_vc_env_vars")
# Keys: target architecture, as in <Windows-SDK-path>/<target-architecture>/bin/rc.exe
# Values: corresponding Bazel CPU value under @platforms//cpu:*
_TARGET_ARCH = {
"arm": "arm",
"arm64": "aarch64",
"x64": "x86_64",
"x86": "x86_32",
}
def _find_rc_exes(root):
result = {}
for a in _TARGET_ARCH:
exe = root.get_child(a).get_child("rc.exe")
if exe.exists:
result[a] = str(exe)
return result
def _find_all_rc_exe(repository_ctx):
if not repository_ctx.os.name.startswith("windows"):
return {}
vc = find_vc_path(repository_ctx)
if vc:
env = setup_vc_env_vars(
repository_ctx,
vc,
envvars = [
"WindowsSdkDir",
"WindowsSdkVerBinPath",
],
allow_empty = True,
escape = False,
)
# Try the versioned directory.
sdk = env.get("WindowsSdkVerBinPath")
if sdk:
archs = _find_rc_exes(repository_ctx.path(sdk))
if archs:
return archs
# Try the unversioned directory (typically Windows 8.1 SDK).
sdk = env.get("WindowsSdkDir")
if sdk:
archs = _find_rc_exes(repository_ctx.path(sdk).get_child("bin"))
if archs:
return archs
return {}
def _toolchain_defs(repository_ctx, rc_exes):
if not rc_exes:
return ""
result = ["""# Auto-generated by winsdk_configure.bzl
load(
"@io_bazel//src/main/res:winsdk_toolchain.bzl",
"WINDOWS_RESOURCE_COMPILER_TOOLCHAIN_TYPE",
"windows_resource_compiler_toolchain",
)"""]
for arch, rc_path in rc_exes.items():
wrapper = "rc_%s.bat" % arch
repository_ctx.file(
wrapper,
content = "@\"%s\" %%*" % rc_path,
executable = True,
)
result.append(
"""
windows_resource_compiler_toolchain(
name = "local_{arch}_tc",
rc_exe = "{wrapper}",
)
toolchain(
name = "local_{arch}",
exec_compatible_with = [
"@platforms//os:windows",
"@platforms//cpu:x86_64",
],
target_compatible_with = [
"@platforms//os:windows",
"@platforms//cpu:{cpu}",
],
toolchain = ":local_{arch}_tc",
toolchain_type = WINDOWS_RESOURCE_COMPILER_TOOLCHAIN_TYPE,
visibility = ["//visibility:public"],
)
""".format(
arch = arch,
wrapper = wrapper,
cpu = _TARGET_ARCH[arch],
),
)
return "\n".join(result)
def _toolchain_labels(repository_ctx, rc_exes):
tc_labels = [
"\"@{repo}//:local_{arch}\"".format(repo = repository_ctx.name, arch = arch)
for arch in rc_exes
]
if rc_exes:
body = "native.register_toolchains(%s)" % ", ".join(tc_labels)
else:
body = "pass"
return """# Auto-generated by winsdk_configure.bzl
def register_local_rc_exe_toolchains():
{body}
""".format(body = body)
def _impl(repository_ctx):
rc_exes = _find_all_rc_exe(repository_ctx)
repository_ctx.file(
"BUILD",
content = _toolchain_defs(repository_ctx, rc_exes),
executable = False,
)
repository_ctx.file(
"toolchains.bzl",
content = _toolchain_labels(repository_ctx, rc_exes),
executable = False,
)
winsdk_configure = repository_rule(
implementation = _impl,
local = True,
environ = list(MSVC_ENVVARS),
)