104 lines
4.3 KiB
Python
104 lines
4.3 KiB
Python
"""Rules for building native build tools such as ninja, make or cmake"""
|
|
|
|
# buildifier: disable=module-docstring
|
|
ToolInfo = provider(
|
|
doc = "Information about the native tool",
|
|
fields = {
|
|
"env": "Environment variables to set when using this tool e.g. M4",
|
|
"path": (
|
|
"Absolute path to the tool in case the tool is preinstalled on the machine. " +
|
|
"Relative path to the tool in case the tool is built as part of a build; the path should be relative " +
|
|
"to the bazel-genfiles, i.e. it should start with the name of the top directory of the built tree " +
|
|
"artifact. (Please see the example `//examples:built_cmake_toolchain`)"
|
|
),
|
|
"target": (
|
|
"If the tool is preinstalled, must be None. " +
|
|
"If the tool is built as part of the build, the corresponding build target, which should produce " +
|
|
"the tree artifact with the binary to call."
|
|
),
|
|
},
|
|
)
|
|
|
|
def _resolve_tool_path(ctx, path, target, tools):
|
|
"""
|
|
Resolve the path to a tool.
|
|
|
|
Note that ctx.resolve_command is used instead of ctx.expand_location as the
|
|
latter cannot be used with py_binary and sh_binary targets as they both produce multiple files in some contexts, meaning
|
|
that the plural make variables must be used, e.g. $(execpaths) must be used. See https://github.com/bazelbuild/bazel/issues/11820.
|
|
|
|
The usage of ctx.resolve_command facilitates the usage of the singular make variables, e.g $(execpath), with py_binary and sh_binary targets
|
|
"""
|
|
_, resolved_bash_command, _ = ctx.resolve_command(
|
|
command = path,
|
|
expand_locations = True,
|
|
tools = tools + [target],
|
|
)
|
|
|
|
return resolved_bash_command[-1]
|
|
|
|
def _native_tool_toolchain_impl(ctx):
|
|
if not ctx.attr.path and not ctx.attr.target:
|
|
fail("Either path or target (and path) should be defined for the tool.")
|
|
path = None
|
|
env = {}
|
|
if ctx.attr.target:
|
|
path = _resolve_tool_path(ctx, ctx.attr.path, ctx.attr.target, ctx.attr.tools)
|
|
|
|
for k, v in ctx.attr.env.items():
|
|
env[k] = _resolve_tool_path(ctx, v, ctx.attr.target, ctx.attr.tools)
|
|
|
|
else:
|
|
path = ctx.expand_location(ctx.attr.path)
|
|
env = {k: ctx.expand_location(v) for (k, v) in ctx.attr.env.items()}
|
|
return platform_common.ToolchainInfo(data = ToolInfo(
|
|
env = env,
|
|
path = path,
|
|
target = ctx.attr.target,
|
|
))
|
|
|
|
native_tool_toolchain = rule(
|
|
doc = (
|
|
"Rule for defining the toolchain data of the native tools (cmake, ninja), " +
|
|
"to be used by rules_foreign_cc with toolchain types " +
|
|
"`@rules_foreign_cc//toolchains:cmake_toolchain` and " +
|
|
"`@rules_foreign_cc//toolchains:ninja_toolchain`."
|
|
),
|
|
implementation = _native_tool_toolchain_impl,
|
|
attrs = {
|
|
"env": attr.string_dict(
|
|
doc = "Environment variables to be set when using this tool e.g. M4",
|
|
),
|
|
"path": attr.string(
|
|
mandatory = False,
|
|
doc = (
|
|
"Absolute path to the tool in case the tool is preinstalled on the machine. " +
|
|
"Relative path to the tool in case the tool is built as part of a build; the path should be " +
|
|
"relative to the bazel-genfiles, i.e. it should start with the name of the top directory " +
|
|
"of the built tree artifact. (Please see the example `//examples:built_cmake_toolchain`)"
|
|
),
|
|
),
|
|
"target": attr.label(
|
|
mandatory = False,
|
|
cfg = "exec",
|
|
doc = (
|
|
"If the tool is preinstalled, must be None. " +
|
|
"If the tool is built as part of the build, the corresponding build target, " +
|
|
"which should produce the tree artifact with the binary to call."
|
|
),
|
|
allow_files = True,
|
|
),
|
|
"tools": attr.label_list(
|
|
mandatory = False,
|
|
cfg = "exec",
|
|
doc = (
|
|
"Additional tools." +
|
|
"If `target` expands to several files, `tools` can be used to " +
|
|
"isolate a specific file that can be used in `env`."
|
|
),
|
|
allow_files = True,
|
|
),
|
|
},
|
|
incompatible_use_toolchain_transition = True,
|
|
)
|