Refactored framework to avoid polymorphism complexity (#612)

* Refactored framework to be less complex

* Deleted default commands (aka 'stale linux commands')

* Restored toolchain name
This commit is contained in:
UebelAndre 2021-04-30 09:03:32 -07:00 committed by GitHub
parent 98c88de5e0
commit 1bd2a8c547
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 521 additions and 727 deletions

View File

@ -405,8 +405,7 @@ Information about the native tool
<pre>
rules_foreign_cc_dependencies(<a href="#rules_foreign_cc_dependencies-native_tools_toolchains">native_tools_toolchains</a>, <a href="#rules_foreign_cc_dependencies-register_default_tools">register_default_tools</a>, <a href="#rules_foreign_cc_dependencies-cmake_version">cmake_version</a>,
<a href="#rules_foreign_cc_dependencies-make_version">make_version</a>, <a href="#rules_foreign_cc_dependencies-ninja_version">ninja_version</a>, <a href="#rules_foreign_cc_dependencies-register_preinstalled_tools">register_preinstalled_tools</a>,
<a href="#rules_foreign_cc_dependencies-register_built_tools">register_built_tools</a>, <a href="#rules_foreign_cc_dependencies-additional_shell_toolchain_mappings">additional_shell_toolchain_mappings</a>,
<a href="#rules_foreign_cc_dependencies-additional_shell_toolchain_package">additional_shell_toolchain_package</a>)
<a href="#rules_foreign_cc_dependencies-register_built_tools">register_built_tools</a>)
</pre>
Call this function from the WORKSPACE file to initialize rules_foreign_cc dependencies and let neccesary code generation happen (Code generation is needed to support different variants of the C++ Starlark API.).
@ -423,7 +422,5 @@ Call this function from the WORKSPACE file to initialize rules_foreign_cc de
| <a id="rules_foreign_cc_dependencies-ninja_version"></a>ninja_version | The target version of the ninja toolchain if <code>register_default_tools</code> or <code>register_built_tools</code> is set to <code>True</code>. | <code>"1.10.2"</code> |
| <a id="rules_foreign_cc_dependencies-register_preinstalled_tools"></a>register_preinstalled_tools | If true, toolchains will be registered for the native built tools installed on the exec host | <code>True</code> |
| <a id="rules_foreign_cc_dependencies-register_built_tools"></a>register_built_tools | If true, toolchains that build the tools from source are registered | <code>True</code> |
| <a id="rules_foreign_cc_dependencies-additional_shell_toolchain_mappings"></a>additional_shell_toolchain_mappings | Mappings of the shell toolchain functions to execution and target platforms constraints. Similar to what defined in @rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:toolchain_mappings.bzl in the TOOLCHAIN_MAPPINGS list. Please refer to example in @rules_foreign_cc//toolchain_examples. | <code>[]</code> |
| <a id="rules_foreign_cc_dependencies-additional_shell_toolchain_package"></a>additional_shell_toolchain_package | A package under which additional toolchains, referencing the generated data for the passed additonal_shell_toolchain_mappings, will be defined. This value is needed since register_toolchains() is called for these toolchains. Please refer to example in @rules_foreign_cc//toolchain_examples. | <code>None</code> |

View File

@ -51,7 +51,7 @@ boost_build = rule(
output_to_genfiles = True,
implementation = _boost_build_impl,
toolchains = [
"@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:shell_commands",
"@rules_foreign_cc//foreign_cc/private/framework:shell_toolchain",
"@bazel_tools//tools/cpp:toolchain_type",
],
# TODO: Remove once https://github.com/bazelbuild/bazel/issues/11584 is closed and the min supported

View File

@ -29,7 +29,7 @@ cmake_tool = rule(
output_to_genfiles = True,
implementation = _cmake_tool_impl,
toolchains = [
str(Label("//foreign_cc/private/shell_toolchain/toolchains:shell_commands")),
str(Label("//foreign_cc/private/framework:shell_toolchain")),
"@bazel_tools//tools/cpp:toolchain_type",
],
)

View File

@ -6,7 +6,7 @@ load(
"FOREIGN_CC_BUILT_TOOLS_HOST_FRAGMENTS",
"built_tool_rule_impl",
)
load("//foreign_cc/private:shell_script_helper.bzl", "os_name")
load("//foreign_cc/private/framework:helpers.bzl", "os_name")
def _make_tool_impl(ctx):
script = [
@ -37,7 +37,7 @@ make_tool = rule(
output_to_genfiles = True,
implementation = _make_tool_impl,
toolchains = [
str(Label("//foreign_cc/private/shell_toolchain/toolchains:shell_commands")),
str(Label("//foreign_cc/private/framework:shell_toolchain")),
"@bazel_tools//tools/cpp:toolchain_type",
],
)

View File

@ -6,7 +6,7 @@ load(
"FOREIGN_CC_BUILT_TOOLS_HOST_FRAGMENTS",
"built_tool_rule_impl",
)
load("//foreign_cc/private:shell_script_helper.bzl", "os_name")
load("//foreign_cc/private/framework:helpers.bzl", "os_name")
def _ninja_tool_impl(ctx):
script = [
@ -31,7 +31,7 @@ ninja_tool = rule(
output_to_genfiles = True,
implementation = _ninja_tool_impl,
toolchains = [
str(Label("//foreign_cc/private/shell_toolchain/toolchains:shell_commands")),
str(Label("//foreign_cc/private/framework:shell_toolchain")),
"@bazel_tools//tools/cpp:toolchain_type",
],
)

View File

@ -3,7 +3,7 @@
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
load("//foreign_cc/private:detect_root.bzl", "detect_root")
load("//foreign_cc/private:framework.bzl", "wrap_outputs")
load("//foreign_cc/private:shell_script_helper.bzl", "convert_shell_script")
load("//foreign_cc/private/framework:helpers.bzl", "convert_shell_script")
# Common attributes for all built_tool rules
FOREIGN_CC_BUILT_TOOLS_ATTRS = {

View File

@ -16,10 +16,7 @@ load(
"cc_external_rule_impl",
"create_attrs",
)
load(
"//foreign_cc/private:shell_script_helper.bzl",
"os_name",
)
load("//foreign_cc/private/framework:helpers.bzl", "os_name")
load(
"//toolchains/native_tools:tool_access.bzl",
"get_cmake_data",
@ -279,7 +276,7 @@ cmake = rule(
"@rules_foreign_cc//toolchains:cmake_toolchain",
"@rules_foreign_cc//toolchains:ninja_toolchain",
"@rules_foreign_cc//toolchains:make_toolchain",
"@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:shell_commands",
"@rules_foreign_cc//foreign_cc/private/framework:shell_toolchain",
"@bazel_tools//tools/cpp:toolchain_type",
],
# TODO: Remove once https://github.com/bazelbuild/bazel/issues/11584 is closed and the min supported

View File

@ -14,7 +14,7 @@ load(
"cc_external_rule_impl",
"create_attrs",
)
load("//foreign_cc/private:shell_script_helper.bzl", "os_name")
load("//foreign_cc/private/framework:helpers.bzl", "os_name")
load("//toolchains/native_tools:tool_access.bzl", "get_make_data")
def _configure_make(ctx):
@ -211,7 +211,7 @@ configure_make = rule(
implementation = _configure_make,
toolchains = [
"@rules_foreign_cc//toolchains:make_toolchain",
"@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:shell_commands",
"@rules_foreign_cc//foreign_cc/private/framework:shell_toolchain",
"@bazel_tools//tools/cpp:toolchain_type",
],
# TODO: Remove once https://github.com/bazelbuild/bazel/issues/11584 is closed and the min supported

View File

@ -96,7 +96,7 @@ make = rule(
implementation = _make,
toolchains = [
"@rules_foreign_cc//toolchains:make_toolchain",
"@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:shell_commands",
"@rules_foreign_cc//foreign_cc/private/framework:shell_toolchain",
"@bazel_tools//tools/cpp:toolchain_type",
],
# TODO: Remove once https://github.com/bazelbuild/bazel/issues/11584 is closed and the min supported

View File

@ -113,7 +113,7 @@ ninja = rule(
implementation = _ninja_impl,
toolchains = [
"@rules_foreign_cc//toolchains:ninja_toolchain",
"@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:shell_commands",
"@rules_foreign_cc//foreign_cc/private/framework:shell_toolchain",
"@bazel_tools//tools/cpp:toolchain_type",
],
# TODO: Remove once https://github.com/bazelbuild/bazel/issues/11584 is closed and the min supported

View File

@ -5,7 +5,6 @@ bzl_library(
srcs = glob(["**/*.bzl"]),
visibility = ["//:__subpackages__"],
deps = [
"//foreign_cc/private/shell_toolchain/polymorphism:bzl_srcs",
"//foreign_cc/private/shell_toolchain/toolchains:bzl_srcs",
"//foreign_cc/private/framework:bzl_srcs",
],
)

View File

@ -6,6 +6,12 @@ load("@bazel_skylib//lib:collections.bzl", "collections")
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
load("//foreign_cc:providers.bzl", "ForeignCcArtifact", "ForeignCcDeps")
load("//foreign_cc/private:detect_root.bzl", "detect_root", "filter_containing_dirs_from_inputs")
load(
"//foreign_cc/private/framework:helpers.bzl",
"convert_shell_script",
"create_function",
"os_name",
)
load(
"//toolchains/native_tools:tool_access.bzl",
"get_make_data",
@ -23,12 +29,6 @@ load(
"copy_directory",
"fictive_file_in_genroot",
)
load(
":shell_script_helper.bzl",
"convert_shell_script",
"create_function",
"os_name",
)
# Dict with definitions of the context attributes, that customize cc_external_rule_impl function.
# Many of the attributes have default values.

View File

@ -1,7 +1,13 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
toolchain_type(
name = "shell_toolchain",
visibility = ["//visibility:public"],
)
bzl_library(
name = "bzl_srcs",
srcs = glob(["**/*.bzl"]),
visibility = ["//:__subpackages__"],
deps = ["//foreign_cc/private/framework/toolchains:bzl_srcs"],
)

View File

@ -31,8 +31,8 @@ Since function definitions can call other functions, we perform the fictive tran
of the function bodies to populate the "prelude" part of the script.
"""
load("//foreign_cc/private/shell_toolchain/toolchains:access.bzl", "call_shell", "create_context")
load("//foreign_cc/private/shell_toolchain/toolchains:commands.bzl", "PLATFORM_COMMANDS")
load("//foreign_cc/private/framework/toolchains:access.bzl", "call_shell", "create_context")
load("//foreign_cc/private/framework/toolchains:commands.bzl", "PLATFORM_COMMANDS")
def os_name(ctx):
return call_shell(create_context(ctx), "os_name")

View File

@ -0,0 +1,106 @@
"""A module containing the implementation of the foreign_cc framework's toolchains"""
load("//foreign_cc/private/framework/toolchains:commands.bzl", "PLATFORM_COMMANDS")
load("//foreign_cc/private/framework/toolchains:mappings.bzl", "TOOLCHAIN_MAPPINGS")
_BUILD_FILE_CONTENT = """\
load("//:defs.bzl", "foreign_cc_framework_toolchain")
package(default_visibility = ["//visibility:public"])
exports_files(["defs.bzl"])
foreign_cc_framework_toolchain(
name = "commands"
)
toolchain(
name = "toolchain",
toolchain_type = "@rules_foreign_cc//foreign_cc/private/framework:shell_toolchain",
toolchain = "//:commands",
exec_compatible_with = {exec_compat},
target_compatible_with = {target_compat},
)
"""
_DEFS_BZL_CONTENT = """\
load(
"{commands_src}",
{symbols}
)
commands = struct(
{commands}
)
def _foreign_cc_framework_toolchain_impl(ctx):
return platform_common.ToolchainInfo(
commands = commands,
)
foreign_cc_framework_toolchain = rule(
doc = "A toolchain contianing foreign_cc commands",
implementation = _foreign_cc_framework_toolchain_impl,
)
"""
def _framework_toolchain_repository_impl(repository_ctx):
"""The implementation of `framework_toolchain_repository`
Args:
repository_ctx (repository_ctx): The rule's context object
"""
# Ensure we always have an absolute label. This may not be the case
# when building within the `@rules_foreign_cc` workspace.
absolute_label = str(repository_ctx.attr.commands_src)
if not absolute_label.startswith("@"):
absolute_label = "@rules_foreign_cc" + absolute_label
repository_ctx.file("defs.bzl", _DEFS_BZL_CONTENT.format(
commands_src = absolute_label,
symbols = "\n ".join(["\"{}\",".format(symbol) for symbol in PLATFORM_COMMANDS.keys()]),
commands = "\n ".join(["{cmd} = {cmd},".format(cmd = symbol) for symbol in PLATFORM_COMMANDS.keys()]),
))
repository_ctx.file("BUILD.bazel", _BUILD_FILE_CONTENT.format(
exec_compat = repository_ctx.attr.exec_compatible_with,
target_compat = repository_ctx.attr.target_compatible_with,
))
framework_toolchain_repository = repository_rule(
doc = "A repository rule which defines a `@rules_foreign_cc//foreign_cc/private/framework:shell_toolchain` toolchain.",
implementation = _framework_toolchain_repository_impl,
attrs = {
"commands_src": attr.label(
doc = "The label of a `.bzl` source which defines toolchain commands",
allow_files = [".bzl"],
),
"exec_compatible_with": attr.string_list(
doc = "A list of constraint_values that must be present in the execution platform for this target.",
),
"target_compatible_with": attr.string_list(
doc = "A list of constraint_values that must be present in the target platform for this target to be considered compatible.",
),
},
)
# buildifier: disable=unnamed-macro
def register_framework_toolchains():
"""Define and register the foreign_cc framework toolchains"""
toolchains = []
for item in TOOLCHAIN_MAPPINGS:
# Generate a toolchain name without the `.bzl` suffix
toolchain_name = "rules_foreign_cc_framework_toolchain_" + item.file.name[:-len(".bzl")]
framework_toolchain_repository(
name = toolchain_name,
commands_src = item.file,
exec_compatible_with = item.exec_compatible_with,
target_compatible_with = item.target_compatible_with,
)
toolchains.append("@{}//:toolchain".format(toolchain_name))
native.register_toolchains(*toolchains)

View File

@ -0,0 +1,102 @@
"""A module defining functionality for invoking toolchain commands"""
load(":commands.bzl", "FunctionAndCallInfo", "PLATFORM_COMMANDS")
_function_and_call_type = type(FunctionAndCallInfo(text = ""))
def create_context(ctx):
"""Generate a 'context' object from the current foreign_cc framework toolchain
Args:
ctx (ctx): The current rule's context object
Returns:
struct: A foreign_cc framework context:
- shell (struct): All commands for the current toolchain
- prelude (dict): A cache for rendered functions
"""
return struct(
shell = ctx.toolchains[str(Label("//foreign_cc/private/framework:shell_toolchain"))].commands,
prelude = {},
)
def call_shell(shell_context, method_, *args):
"""Calls the 'method_' shell command from the toolchain.
Checks the number and types of passed arguments.
If the command returns the resulting text wrapped into `FunctionAndCallInfo` provider,
puts the text of the function into the 'prelude' dictionary in the 'shell_context',
and returns only the call of that function.
Args:
shell_context (struct): A shell_context created by `create_context`
method_ (str): The command to invoke from teh shell context's commands
*args: Optinal arguments to accomponany `method_`
Returns:
str: the rendered command
"""
check_argument_types(method_, args)
func_ = getattr(shell_context.shell, method_)
result = func_(*args)
if type(result) == _function_and_call_type:
# Cache the rendered function for use when rendering
# the full scrupt in `convert_shell_script_by_context`
if not shell_context.prelude.get(method_):
shell_context.prelude[method_] = shell_context.shell.define_function(method_, result.text)
# use provided method of calling a defined function or use default
if hasattr(result, "call"):
return result.call
# TODO: This doesn't play well with arguments such as `foo="bar"`.
return " ".join([method_] + [_wrap_if_needed(str(arg)) for arg in args])
return result
def _quoted(arg):
"""Check if arguments to framework functions are wrapped in quotes.
Args:
arg (str): The target argument
Returns:
bool: True if `arg` is quoted
"""
return arg.startswith("\"") and arg.endswith("\"")
def _wrap_if_needed(arg):
"""Ensure arguments to framework functions are wrapped in quotes.
Args:
arg (str): The target argument
Returns:
str: `arg` guaranteed to be wrapped by double quotes (`"`)
"""
if arg.find(" ") >= 0 and not _quoted(arg):
return "\"" + arg + "\""
return arg
def check_argument_types(method_, args_list):
"""Check a method's argument types
Args:
method_ (str): The target method
args_list (list): A list of arguments to check
"""
descriptor = PLATFORM_COMMANDS[method_]
args_info = descriptor.arguments
if len(args_list) != len(args_info):
fail("Wrong number ({}) of arguments ({}) in a call to '{}'".format(
len(args_list),
str(args_list),
method_,
))
for idx in range(0, len(args_list)):
if type(args_list[idx]) != args_info[idx].data_type:
fail("Wrong argument '{}' type: '{}'".format(args_info[idx].name, type(args_list[idx])))

View File

@ -0,0 +1,218 @@
"""A module difining all commands for a foreign_cc framework toolchain"""
FunctionAndCallInfo = provider(
doc = "Wrapper to pass function definition and (if custom) function call",
fields = {
"call": "How to call defined function, if different from <function-name> <arg1> ...<argn>",
"text": "Function body, without wrapping function <name>() {} fragment.",
},
)
def _command_info(arguments, doc):
"""To pass information about the Starlark function, defining the shell fragment.
Args:
arguments (list): Arguments of Starlark function (`_argument_info`)
doc (str): What the shell script fragment, generated by this function, does.
Returns:
struct: A struct of command info
"""
return struct(
arguments = arguments,
doc = doc,
)
def _argument_info(name, data_type, doc):
"""Generates a struct of information about a command argument for `_command_info` commands
Args:
name (str): The name fo the argument
data_type (str): The type of the data, typically the result of `type(...)`
doc (str): Documentation for the argument
Returns:
struct: A struct of argument info
"""
return struct(
name = name,
doc = doc,
data_type = data_type,
)
PLATFORM_COMMANDS = {
"assert_script_errors": _command_info(
arguments = [],
doc = "Script fragment that stops the execution after any error",
),
"cat": _command_info(
arguments = [
_argument_info(name = "filepath", data_type = type(""), doc = "Path to the file"),
],
doc = "Output the file contents to stdout",
),
"children_to_path": _command_info(
arguments = [
_argument_info(name = "dir_", data_type = type(""), doc = "Directory"),
],
doc = "Put all immediate subdirectories (and symlinks) into PATH",
),
"cleanup_function": _command_info(
arguments = [
_argument_info(name = "on_success", data_type = type(""), doc = "Command(s) to be executed on success"),
_argument_info(name = "on_failure", data_type = type(""), doc = "Command(s) to be executed on failure"),
],
doc = "Trap function called after the script is finished",
# doc = "Read the result of the execution of the previous command, execute success or failure callbacks",
),
"copy_dir_contents_to_dir": _command_info(
arguments = [
_argument_info(
name = "source",
data_type = type(""),
doc = "Source directory, immediate children of which are copied",
),
_argument_info(name = "target", data_type = type(""), doc = "Target directory"),
],
doc = "Copies contents of the directory to target directory",
),
"define_absolute_paths": _command_info(
arguments = [
_argument_info(name = "dir_", data_type = type(""), doc = "Directory where to replace"),
_argument_info(name = "abs_path", data_type = type(""), doc = "Absolute path value"),
],
doc = "Replaces absolute path placeholder inside 'dir_' with a provided value 'abs_path'",
),
"define_function": _command_info(
arguments = [
_argument_info(name = "name", data_type = type(""), doc = "Function name"),
_argument_info(name = "text", data_type = type(""), doc = "Function body"),
],
doc = "Defines a function with 'text' as the function body.",
),
"echo": _command_info(
arguments = [_argument_info(name = "text", data_type = type(""), doc = "Text to output")],
doc = "Outputs 'text' to stdout",
),
"env": _command_info(
arguments = [],
doc = "Print all environment variables",
),
"export_var": _command_info(
arguments = [
_argument_info(name = "name", data_type = type(""), doc = "Variable name"),
_argument_info(name = "value", data_type = type(""), doc = "Variable value"),
],
doc = "Defines and exports environment variable.",
),
"if_else": _command_info(
doc = "Creates if-else construct",
arguments = [
_argument_info(name = "condition", data_type = type(""), doc = "Condition text"),
_argument_info(name = "if_text", data_type = type(""), doc = "If block text"),
_argument_info(name = "else_text", data_type = type(""), doc = "Else block text"),
],
),
"increment_pkg_config_path": _command_info(
arguments = [
_argument_info(
name = "source",
data_type = type(""),
doc = "Source directory",
),
],
doc = (
"Find subdirectory inside a passed directory with *.pc files and add it " +
"to the PKG_CONFIG_PATH"
),
),
"local_var": _command_info(
arguments = [
_argument_info(name = "name", data_type = type(""), doc = "Variable name"),
_argument_info(name = "value", data_type = type(""), doc = "Variable value"),
],
doc = "Defines local shell variable.",
),
"mkdirs": _command_info(
arguments = [_argument_info(name = "path", data_type = type(""), doc = "Path to directory")],
doc = "Creates a directory and, if neccesary, it's parents",
),
"os_name": _command_info(
arguments = [],
doc = "Returns OS name",
),
"path": _command_info(
arguments = [
_argument_info(name = "expression", data_type = type(""), doc = "Path"),
],
doc = "Adds passed arguments in the beginning of the PATH.",
),
"pwd": _command_info(
arguments = [],
doc = "Returns command for getting current directory.",
),
"redirect_out_err": _command_info(
arguments = [
_argument_info(name = "from_process", data_type = type(""), doc = "Process to run"),
_argument_info(name = "to_file", data_type = type(""), doc = "File to redirect output to"),
],
doc = "Read the result of the execution of the previous command, execute success or failure callbacks",
),
"replace_absolute_paths": _command_info(
arguments = [
_argument_info(name = "dir_", data_type = type(""), doc = "Directory where to replace"),
_argument_info(name = "abs_path", data_type = type(""), doc = "Absolute path value"),
],
doc = "Replaces absolute path 'abs_path' inside 'dir_' with a placeholder value",
),
"replace_in_files": _command_info(
arguments = [
_argument_info(name = "dir_", data_type = type(""), doc = "Directory to search recursively"),
_argument_info(name = "from_", data_type = type(""), doc = "String to be replaced"),
_argument_info(name = "to_", data_type = type(""), doc = "Replace target"),
],
doc = "Replaces all occurrences of 'from_' to 'to_' recursively in the directory 'dir'.",
),
"script_prelude": _command_info(
arguments = [],
doc = "Function for setting necessary environment variables for the platform",
),
"symlink_contents_to_dir": _command_info(
arguments = [
_argument_info(
name = "source",
data_type = type(""),
doc = "Source directory, immediate children of which are symlinked, or file to be symlinked.",
),
_argument_info(name = "target", data_type = type(""), doc = "Target directory"),
],
doc = (
"Symlink contents of the directory to target directory (create the target directory if needed). " +
"If file is passed, symlink it into the target directory."
),
),
"symlink_to_dir": _command_info(
arguments = [
_argument_info(
name = "source",
data_type = type(""),
doc = "Source directory",
),
_argument_info(name = "target", data_type = type(""), doc = "Target directory"),
],
doc = (
"Symlink all files from source directory to target directory (create the target directory if needed). " +
"NB symlinks from the source directory are copied."
),
),
"touch": _command_info(
arguments = [_argument_info(name = "path", data_type = type(""), doc = "Path to file")],
doc = "Creates a file",
),
"use_var": _command_info(
arguments = [
_argument_info(name = "name", data_type = type(""), doc = "Variable name"),
],
doc = "Expression to address the variable.",
),
}

View File

@ -1,5 +1,6 @@
# buildifier: disable=module-docstring
load("@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:function_and_call.bzl", "FunctionAndCallInfo")
"""Define default foreign_cc framework commands. Linux platforms use bash"""
load(":commands.bzl", "FunctionAndCallInfo")
_REPLACE_VALUE = "\\${EXT_BUILD_DEPS}"

View File

@ -1,5 +1,6 @@
# buildifier: disable=module-docstring
load("@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:function_and_call.bzl", "FunctionAndCallInfo")
"""Define MacOS foreign_cc framework commands. MacOS platforms uses Bash"""
load(":commands.bzl", "FunctionAndCallInfo")
_REPLACE_VALUE = "\\${EXT_BUILD_DEPS}"

View File

@ -0,0 +1,40 @@
"""A module defining default toolchain info for the foreign_cc framework"""
def _toolchain_mapping(file, exec_compatible_with = [], target_compatible_with = []):
"""Mapping of toolchain definition files to platform constraints
Args:
file (Label): Toolchain definition file
exec_compatible_with (list): A list of compatible execution platform constraints.
target_compatible_with (list): Compatible target platform constraints
Returns:
struct: A collection of toolchain data
"""
return struct(
file = file,
exec_compatible_with = exec_compatible_with,
target_compatible_with = target_compatible_with,
)
# This list is the single entrypoint for all foreing_cc framework toolchains.
TOOLCHAIN_MAPPINGS = [
_toolchain_mapping(
exec_compatible_with = [
"@platforms//os:linux",
],
file = Label("@rules_foreign_cc//foreign_cc/private/framework/toolchains:linux_commands.bzl"),
),
_toolchain_mapping(
exec_compatible_with = [
"@platforms//os:windows",
],
file = Label("@rules_foreign_cc//foreign_cc/private/framework/toolchains:windows_commands.bzl"),
),
_toolchain_mapping(
exec_compatible_with = [
"@platforms//os:macos",
],
file = Label("@rules_foreign_cc//foreign_cc/private/framework/toolchains:macos_commands.bzl"),
),
]

View File

@ -1,5 +1,6 @@
# buildifier: disable=module-docstring
load("@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:function_and_call.bzl", "FunctionAndCallInfo")
"""Define windows foreign_cc framework commands. Windows uses Bash"""
load(":commands.bzl", "FunctionAndCallInfo")
_REPLACE_VALUE = "\\${EXT_BUILD_DEPS}"

View File

@ -1,88 +0,0 @@
# buildifier: disable=module-docstring
def _provider_text(symbols):
return """
WRAPPER = provider(
doc = "Wrapper to hold imported methods",
fields = [{}]
)
""".format(", ".join(["\"%s\"" % symbol_ for symbol_ in symbols]))
def _getter_text():
return """
def id_from_file(file_name):
(before, middle, after) = file_name.partition(".")
return before
def get(file_name):
id = id_from_file(file_name)
return WRAPPER(**_MAPPING[id])
"""
def _mapping_text(ids):
data_ = []
for id in ids:
data_.append("{id} = wrapper_{id}".format(id = id))
return "_MAPPING = dict(\n{data}\n)".format(data = ",\n".join(data_))
def _load_and_wrapper_text(id, file_path, symbols):
load_list = ", ".join(["{id}_{symbol} = \"{symbol}\"".format(id = id, symbol = symbol_) for symbol_ in symbols])
load_statement = "load(\":{file}\", {list})".format(file = file_path, list = load_list)
data = ", ".join(["{symbol} = {id}_{symbol}".format(id = id, symbol = symbol_) for symbol_ in symbols])
wrapper_statement = "wrapper_{id} = dict({data})".format(id = id, data = data)
return struct(
load_ = load_statement,
wrapper = wrapper_statement,
)
def id_from_file(file_name):
(before, middle, after) = file_name.partition(".")
return before
def get_file_name(file_label):
(before, separator, after) = file_label.partition(":")
return id_from_file(after)
def _copy_file(rctx, src):
src_path = rctx.path(src)
copy_path = src_path.basename
rctx.template(copy_path, src_path)
return copy_path
_BUILD_FILE = """\
exports_files(
[
"toolchain_data_defs.bzl",
],
visibility = ["//visibility:public"],
)
"""
def _generate_overloads(rctx):
symbols = rctx.attr.symbols
ids = []
lines = ["# Generated overload mappings"]
loads = []
wrappers = []
for file_ in rctx.attr.files:
id = id_from_file(file_.name)
ids.append(id)
copy = _copy_file(rctx, file_)
load_and_wrapper = _load_and_wrapper_text(id, copy, symbols)
loads.append(load_and_wrapper.load_)
wrappers.append(load_and_wrapper.wrapper)
lines += loads
lines += wrappers
lines.append(_mapping_text(ids))
lines.append(_provider_text(symbols))
lines.append(_getter_text())
rctx.file("toolchain_data_defs.bzl", "\n".join(lines))
rctx.file("BUILD", _BUILD_FILE)
generate_overloads = repository_rule(
implementation = _generate_overloads,
attrs = {
"files": attr.label_list(),
"symbols": attr.string_list(),
},
)

View File

@ -1,20 +0,0 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load(":defs.bzl", "build_part")
toolchain_type(
name = "shell_commands",
visibility = ["//visibility:public"],
)
build_part(
toolchain_type = ":shell_commands",
)
bzl_library(
name = "bzl_srcs",
srcs = glob(["**/*.bzl"]) + [
"@rules_foreign_cc_commands_overloads//:toolchain_data_defs.bzl",
],
visibility = ["//:__subpackages__"],
deps = ["//foreign_cc/private/shell_toolchain/toolchains/impl:bzl_srcs"],
)

View File

@ -1,63 +0,0 @@
# buildifier: disable=module-docstring
load("//foreign_cc/private/shell_toolchain/toolchains:commands.bzl", "PLATFORM_COMMANDS")
load(":function_and_call.bzl", "FunctionAndCallInfo")
_function_and_call_type = type(FunctionAndCallInfo(text = ""))
def create_context(ctx):
return struct(
shell = ctx.toolchains["@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:shell_commands"].data,
prelude = {},
)
# buildifier: disable=function-docstring-header
# buildifier: disable=function-docstring-args
# buildifier: disable=function-docstring-return
def call_shell(shell_context, method_, *args):
"""Calls the 'method_' shell command from the toolchain.
Checks the number and types of passed arguments.
If the command returns the resulting text wrapped into FunctionAndCallInfo provider,
puts the text of the function into the 'prelude' dictionary in the 'shell_context',
and returns only the call of that function.
"""
check_argument_types(method_, args)
func_ = getattr(shell_context.shell, method_)
result = func_(*args)
if type(result) == _function_and_call_type:
# If needed, add function definition to the prelude part of the script
if not shell_context.prelude.get(method_):
define_function = getattr(shell_context.shell, "define_function")
shell_context.prelude[method_] = define_function(method_, result.text)
# use provided method of calling a defined function or use default
if hasattr(result, "call"):
return result.call
return " ".join([method_] + [_wrap_if_needed(str(arg)) for arg in args])
return result
def _quoted(arg):
return arg.startswith("\"") and arg.endswith("\"")
def _wrap_if_needed(arg):
if arg.find(" ") >= 0 and not _quoted(arg):
return "\"" + arg + "\""
return arg
# buildifier: disable=function-docstring
def check_argument_types(method_, args_list):
descriptor = PLATFORM_COMMANDS[method_]
args_info = descriptor.arguments
if len(args_list) != len(args_info):
fail("Wrong number ({}) of arguments ({}) in a call to '{}'".format(
len(args_list),
str(args_list),
method_,
))
for idx in range(0, len(args_list)):
if type(args_list[idx]) != args_info[idx].type_:
fail("Wrong argument '{}' type: '{}'".format(args_info[idx].name, type(args_list[idx])))

View File

@ -1,194 +0,0 @@
# buildifier: disable=module-docstring
CommandInfo = provider(
doc = "To pass information about the Starlark function, defining the shell fragment.",
fields = {
"arguments": "Arguments of Starlark function",
"doc": "What the shell script fragment, generated by this function, does.",
},
)
ArgumentInfo = provider(
doc = "",
fields = {
"doc": "",
"name": "",
"type_": "",
},
)
PLATFORM_COMMANDS = {
"assert_script_errors": CommandInfo(
arguments = [],
doc = "Script fragment that stops the execution after any error",
),
"cat": CommandInfo(
arguments = [
ArgumentInfo(name = "filepath", type_ = type(""), doc = "Path to the file"),
],
doc = "Output the file contents to stdout",
),
"children_to_path": CommandInfo(
arguments = [
ArgumentInfo(name = "dir_", type_ = type(""), doc = "Directory"),
],
doc = "Put all immediate subdirectories (and symlinks) into PATH",
),
"cleanup_function": CommandInfo(
arguments = [
ArgumentInfo(name = "on_success", type_ = type(""), doc = "Command(s) to be executed on success"),
ArgumentInfo(name = "on_failure", type_ = type(""), doc = "Command(s) to be executed on failure"),
],
doc = "Trap function called after the script is finished",
# doc = "Read the result of the execution of the previous command, execute success or failure callbacks",
),
"copy_dir_contents_to_dir": CommandInfo(
arguments = [
ArgumentInfo(
name = "source",
type_ = type(""),
doc = "Source directory, immediate children of which are copied",
),
ArgumentInfo(name = "target", type_ = type(""), doc = "Target directory"),
],
doc = "Copies contents of the directory to target directory",
),
"define_absolute_paths": CommandInfo(
arguments = [
ArgumentInfo(name = "dir_", type_ = type(""), doc = "Directory where to replace"),
ArgumentInfo(name = "abs_path", type_ = type(""), doc = "Absolute path value"),
],
doc = "Replaces absolute path placeholder inside 'dir_' with a provided value 'abs_path'",
),
"define_function": CommandInfo(
arguments = [
ArgumentInfo(name = "name", type_ = type(""), doc = "Function name"),
ArgumentInfo(name = "text", type_ = type(""), doc = "Function body"),
],
doc = "Defines a function with 'text' as the function body.",
),
"echo": CommandInfo(
arguments = [ArgumentInfo(name = "text", type_ = type(""), doc = "Text to output")],
doc = "Outputs 'text' to stdout",
),
"env": CommandInfo(
arguments = [],
doc = "Print all environment variables",
),
"export_var": CommandInfo(
arguments = [
ArgumentInfo(name = "name", type_ = type(""), doc = "Variable name"),
ArgumentInfo(name = "value", type_ = type(""), doc = "Variable value"),
],
doc = "Defines and exports environment variable.",
),
"if_else": CommandInfo(
doc = "Creates if-else construct",
arguments = [
ArgumentInfo(name = "condition", type_ = type(""), doc = "Condition text"),
ArgumentInfo(name = "if_text", type_ = type(""), doc = "If block text"),
ArgumentInfo(name = "else_text", type_ = type(""), doc = "Else block text"),
],
),
"increment_pkg_config_path": CommandInfo(
arguments = [
ArgumentInfo(
name = "source",
type_ = type(""),
doc = "Source directory",
),
],
doc = (
"Find subdirectory inside a passed directory with *.pc files and add it " +
"to the PKG_CONFIG_PATH"
),
),
"local_var": CommandInfo(
arguments = [
ArgumentInfo(name = "name", type_ = type(""), doc = "Variable name"),
ArgumentInfo(name = "value", type_ = type(""), doc = "Variable value"),
],
doc = "Defines local shell variable.",
),
"mkdirs": CommandInfo(
arguments = [ArgumentInfo(name = "path", type_ = type(""), doc = "Path to directory")],
doc = "Creates a directory and, if neccesary, it's parents",
),
"os_name": CommandInfo(
arguments = [],
doc = "Returns OS name",
),
"path": CommandInfo(
arguments = [
ArgumentInfo(name = "expression", type_ = type(""), doc = "Path"),
],
doc = "Adds passed arguments in the beginning of the PATH.",
),
"pwd": CommandInfo(
arguments = [],
doc = "Returns command for getting current directory.",
),
"redirect_out_err": CommandInfo(
arguments = [
ArgumentInfo(name = "from_process", type_ = type(""), doc = "Process to run"),
ArgumentInfo(name = "to_file", type_ = type(""), doc = "File to redirect output to"),
],
doc = "Read the result of the execution of the previous command, execute success or failure callbacks",
),
"replace_absolute_paths": CommandInfo(
arguments = [
ArgumentInfo(name = "dir_", type_ = type(""), doc = "Directory where to replace"),
ArgumentInfo(name = "abs_path", type_ = type(""), doc = "Absolute path value"),
],
doc = "Replaces absolute path 'abs_path' inside 'dir_' with a placeholder value",
),
"replace_in_files": CommandInfo(
arguments = [
ArgumentInfo(name = "dir_", type_ = type(""), doc = "Directory to search recursively"),
ArgumentInfo(name = "from_", type_ = type(""), doc = "String to be replaced"),
ArgumentInfo(name = "to_", type_ = type(""), doc = "Replace target"),
],
doc = "Replaces all occurrences of 'from_' to 'to_' recursively in the directory 'dir'.",
),
"script_prelude": CommandInfo(
arguments = [],
doc = "Function for setting necessary environment variables for the platform",
),
"symlink_contents_to_dir": CommandInfo(
arguments = [
ArgumentInfo(
name = "source",
type_ = type(""),
doc = "Source directory, immediate children of which are symlinked, or file to be symlinked.",
),
ArgumentInfo(name = "target", type_ = type(""), doc = "Target directory"),
],
doc = (
"Symlink contents of the directory to target directory (create the target directory if needed). " +
"If file is passed, symlink it into the target directory."
),
),
"symlink_to_dir": CommandInfo(
arguments = [
ArgumentInfo(
name = "source",
type_ = type(""),
doc = "Source directory",
),
ArgumentInfo(name = "target", type_ = type(""), doc = "Target directory"),
],
doc = (
"Symlink all files from source directory to target directory (create the target directory if needed). " +
"NB symlinks from the source directory are copied."
),
),
"touch": CommandInfo(
arguments = [ArgumentInfo(name = "path", type_ = type(""), doc = "Path to file")],
doc = "Creates a file",
),
"use_var": CommandInfo(
arguments = [
ArgumentInfo(name = "name", type_ = type(""), doc = "Variable name"),
],
doc = "Expression to address the variable.",
),
}

View File

@ -1,39 +0,0 @@
# buildifier: disable=module-docstring
load("@rules_foreign_cc_commands_overloads//:toolchain_data_defs.bzl", "get")
load(
"//foreign_cc/private/shell_toolchain/polymorphism:generate_overloads.bzl",
"get_file_name",
)
load(":toolchain_mappings.bzl", "TOOLCHAIN_MAPPINGS")
def _toolchain_data(ctx):
return platform_common.ToolchainInfo(data = get(ctx.attr.file_name))
toolchain_data = rule(
implementation = _toolchain_data,
attrs = {
"file_name": attr.string(),
},
)
# buildifier: disable=unnamed-macro
def build_part(toolchain_type):
register_mappings(toolchain_type, TOOLCHAIN_MAPPINGS)
# buildifier: disable=unnamed-macro
def register_mappings(toolchain_type, mappings):
for item in mappings:
file_name = get_file_name(item.file)
toolchain_data(
name = file_name + "_data",
file_name = file_name,
visibility = ["//visibility:public"],
)
native.toolchain(
name = file_name,
toolchain_type = toolchain_type,
toolchain = file_name + "_data",
exec_compatible_with = item.exec_compatible_with if hasattr(item, "exec_compatible_with") else [],
target_compatible_with = item.target_compatible_with if hasattr(item, "target_compatible_with") else [],
)

View File

@ -1,8 +0,0 @@
# buildifier: disable=module-docstring
FunctionAndCallInfo = provider(
doc = "Wrapper to pass function definition and (if custom) function call",
fields = {
"call": "How to call defined function, if different from <function-name> <arg1> ...<argn>",
"text": "Function body, without wrapping function <name>() {} fragment.",
},
)

View File

@ -1,175 +0,0 @@
# buildifier: disable=module-docstring
load("@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:function_and_call.bzl", "FunctionAndCallInfo")
_REPLACE_VALUE = "\\${EXT_BUILD_DEPS}"
def os_name():
return "linux"
def pwd():
return "$(pwd)"
def echo(text):
return "echo \"{text}\"".format(text = text)
def export_var(name, value):
return "export {name}={value}".format(name = name, value = value)
def local_var(name, value):
return "local {name}={value}".format(name = name, value = value)
def use_var(name):
return "$" + name
def env():
return "env"
def path(expression):
return "export PATH=\"{expression}:$PATH\"".format(expression = expression)
def touch(path):
return "touch " + path
def mkdirs(path):
return "mkdir -p " + path
def if_else(condition, if_text, else_text):
return """\
if [ {condition} ]; then
{if_text}
else
{else_text}
fi
""".format(condition = condition, if_text = if_text, else_text = else_text)
# buildifier: disable=function-docstring
def define_function(name, text):
lines = []
lines.append("function " + name + "() {")
for line_ in text.splitlines():
lines.append(" " + line_)
lines.append("}")
return "\n".join(lines)
def replace_in_files(dir, from_, to_):
return FunctionAndCallInfo(
text = """\
if [ -d "$1" ]; then
find -L $1 -type f \\( -name "*.pc" -or -name "*.la" -or -name "*-config" -or -name "*.cmake" \\) -exec sed -i 's@'"$2"'@'"$3"'@g' {} ';'
fi
""",
)
def copy_dir_contents_to_dir(source, target):
return """cp -L -r --no-target-directory "{source}" "{target}" && find {target} -type f -exec touch -r "{source}" "{{}}" \\;""".format(
source = source,
target = target,
)
def symlink_contents_to_dir(source, target):
text = """\
local target="$2"
mkdir -p "$target"
if [[ -f "$1" ]]; then
##symlink_to_dir## "$1" "$target"
elif [[ -L "$1" ]]; then
local actual=$(readlink "$1")
##symlink_contents_to_dir## "$actual" "$target"
elif [[ -d "$1" ]]; then
SAVEIFS=$IFS
IFS=$'\n'
local children=($(find -H "$1" -maxdepth 1 -mindepth 1))
IFS=$SAVEIFS
for child in "${children[@]:-}"; do
##symlink_to_dir## "$child" "$target"
done
fi
"""
return FunctionAndCallInfo(text = text)
def symlink_to_dir(source, target):
text = """\
local target="$2"
mkdir -p "$target"
if [[ -f "$1" ]]; then
ln -s -f -t "$target" "$1"
elif [[ -L "$1" ]]; then
local actual=$(readlink "$1")
##symlink_to_dir## "$actual" "$target"
elif [[ -d "$1" ]]; then
SAVEIFS=$IFS
IFS=$'\n'
local children=($(find -H "$1" -maxdepth 1 -mindepth 1))
IFS=$SAVEIFS
local dirname=$(basename "$1")
for child in "${children[@]:-}"; do
if [[ "$dirname" != *.ext_build_deps ]]; then
##symlink_to_dir## "$child" "$target/$dirname"
fi
done
else
echo "Can not copy $1"
fi
"""
return FunctionAndCallInfo(text = text)
def script_prelude():
return "set -euo pipefail"
def increment_pkg_config_path(source):
text = """\
local children=$(find $1 -mindepth 1 -name '*.pc')
# assume there is only one directory with pkg config
for child in $children; do
export PKG_CONFIG_PATH="$${PKG_CONFIG_PATH:-}$$:$(dirname $child)"
return
done
"""
return FunctionAndCallInfo(text = text)
def cat(filepath):
return "cat \"{}\"".format(filepath)
def redirect_out_err(from_process, to_file):
return from_process + " &> " + to_file
def assert_script_errors():
return "set -e"
def cleanup_function(on_success, on_failure):
text = "\n".join([
"local ecode=$?",
"if [ $ecode -eq 0 ]; then",
on_success,
"else",
on_failure,
"fi",
])
return FunctionAndCallInfo(text = text, call = "trap \"cleanup_function\" EXIT")
def children_to_path(dir_):
text = """\
if [ -d {dir_} ]; then
local tools=$(find $EXT_BUILD_DEPS/bin -maxdepth 1 -mindepth 1)
for tool in $tools;
do
if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then
export PATH=$PATH:$tool
fi
done
fi""".format(dir_ = dir_)
return FunctionAndCallInfo(text = text)
def define_absolute_paths(dir_, abs_path):
return "##replace_in_files## {dir_} {REPLACE_VALUE} {abs_path}".format(
dir_ = dir_,
REPLACE_VALUE = _REPLACE_VALUE,
abs_path = abs_path,
)
def replace_absolute_paths(dir_, abs_path):
return "##replace_in_files## {dir_} {abs_path} {REPLACE_VALUE}".format(
dir_ = dir_,
REPLACE_VALUE = _REPLACE_VALUE,
abs_path = abs_path,
)

View File

@ -1,34 +0,0 @@
# buildifier: disable=module-docstring
# buildifier: disable=name-conventions
ToolchainMapping = provider(
doc = "Mapping of toolchain definition files to platform constraints",
fields = {
"exec_compatible_with": "Compatible execution platform constraints",
"file": "Toolchain definition file",
"target_compatible_with": "Compatible target platform constraints",
},
)
TOOLCHAIN_MAPPINGS = [
ToolchainMapping(
exec_compatible_with = [
"@platforms//os:linux",
],
file = "@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains/impl:linux_commands.bzl",
),
ToolchainMapping(
exec_compatible_with = [
"@platforms//os:windows",
],
file = "@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains/impl:windows_commands.bzl",
),
ToolchainMapping(
exec_compatible_with = [
"@platforms//os:macos",
],
file = "@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains/impl:macos_commands.bzl",
),
ToolchainMapping(
file = "@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains/impl:default_commands.bzl",
),
]

View File

@ -1,31 +0,0 @@
# buildifier: disable=module-docstring
load(
"//foreign_cc/private/shell_toolchain/polymorphism:generate_overloads.bzl",
"generate_overloads",
"get_file_name",
)
load("//foreign_cc/private/shell_toolchain/toolchains:commands.bzl", "PLATFORM_COMMANDS")
load(":toolchain_mappings.bzl", "TOOLCHAIN_MAPPINGS")
# buildifier: disable=unnamed-macro
# buildifier: disable=function-docstring
def workspace_part(
additional_toolchain_mappings = [],
additonal_shell_toolchain_package = None):
mappings = additional_toolchain_mappings + TOOLCHAIN_MAPPINGS
generate_overloads(
name = "rules_foreign_cc_commands_overloads",
files = [item.file for item in mappings],
symbols = PLATFORM_COMMANDS.keys(),
)
ordered_toolchains = []
for item in additional_toolchain_mappings:
if not additonal_shell_toolchain_package:
fail("Please specify the package, where the toolchains will be created")
if not additonal_shell_toolchain_package.endswith(":"):
additonal_shell_toolchain_package = additonal_shell_toolchain_package + ":"
ordered_toolchains.append(additonal_shell_toolchain_package + get_file_name(item.file))
prefix = "@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:"
for item in TOOLCHAIN_MAPPINGS:
ordered_toolchains.append(prefix + get_file_name(item.file))
native.register_toolchains(*ordered_toolchains)

View File

@ -2,10 +2,7 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
load(
"//foreign_cc/private/shell_toolchain/toolchains:ws_defs.bzl",
shell_toolchain_workspace_initalization = "workspace_part",
)
load("//foreign_cc/private/framework:toolchain.bzl", "register_framework_toolchains")
load("//toolchains:toolchains.bzl", "built_toolchains", "prebuilt_toolchains", "preinstalled_toolchains")
# buildifier: disable=unnamed-macro
@ -16,9 +13,7 @@ def rules_foreign_cc_dependencies(
make_version = "4.3",
ninja_version = "1.10.2",
register_preinstalled_tools = True,
register_built_tools = True,
additional_shell_toolchain_mappings = [],
additional_shell_toolchain_package = None):
register_built_tools = True):
"""Call this function from the WORKSPACE file to initialize rules_foreign_cc \
dependencies and let neccesary code generation happen \
(Code generation is needed to support different variants of the C++ Starlark API.).
@ -46,22 +41,9 @@ def rules_foreign_cc_dependencies(
installed on the exec host
register_built_tools: If true, toolchains that build the tools from source are registered
additional_shell_toolchain_mappings: Mappings of the shell toolchain functions to
execution and target platforms constraints. Similar to what defined in
@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:toolchain_mappings.bzl
in the TOOLCHAIN_MAPPINGS list. Please refer to example in @rules_foreign_cc//toolchain_examples.
additional_shell_toolchain_package: A package under which additional toolchains, referencing
the generated data for the passed additonal_shell_toolchain_mappings, will be defined.
This value is needed since register_toolchains() is called for these toolchains.
Please refer to example in @rules_foreign_cc//toolchain_examples.
"""
shell_toolchain_workspace_initalization(
additional_shell_toolchain_mappings,
additional_shell_toolchain_package,
)
register_framework_toolchains()
native.register_toolchains(*native_tools_toolchains)

View File

@ -29,20 +29,13 @@ config_setting(
visibility = ["//visibility:private"],
)
result_file = select({
":macos": "expected/inner_fun_text_osx.txt",
"//conditions:default": "expected/inner_fun_text.txt",
})
result_file_symlink_dirs = select({
":macos": "expected/out_symlinked_dirs_osx.txt",
"//conditions:default": "expected/out_symlinked_dirs.txt",
})
diff_test(
name = "shell_script_inner_fun_test",
file1 = ":shell_script_inner_fun",
file2 = result_file,
file2 = select({
":macos": "expected/inner_fun_text_osx.txt",
"//conditions:default": "expected/inner_fun_text.txt",
}),
)
filegroup(
@ -64,6 +57,9 @@ symlink_contents_to_dir_test_rule(
diff_test(
name = "shell_method_symlink_contents_to_dir_test",
file1 = result_file_symlink_dirs,
file1 = select({
":macos": "expected/out_symlinked_dirs_osx.txt",
"//conditions:default": "expected/out_symlinked_dirs.txt",
}),
file2 = ":symlink_dirs",
)

View File

@ -4,7 +4,7 @@ load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
# buildifier: disable=bzl-visibility
load(
"//foreign_cc/private:shell_script_helper.bzl",
"//foreign_cc/private/framework:helpers.bzl",
"convert_shell_script_by_context",
"do_function_call",
"replace_var_ref",
@ -12,7 +12,7 @@ load(
)
# buildifier: disable=bzl-visibility
load("//foreign_cc/private/shell_toolchain/toolchains:function_and_call.bzl", "FunctionAndCallInfo")
load("//foreign_cc/private/framework/toolchains:commands.bzl", "FunctionAndCallInfo")
def _use_var_linux(varname):
return "$" + varname

View File

@ -1,6 +1,6 @@
# buildifier: disable=module-docstring
# buildifier: disable=bzl-visibility
load("//foreign_cc/private:shell_script_helper.bzl", "convert_shell_script")
load("//foreign_cc/private/framework:helpers.bzl", "convert_shell_script")
def _impl(ctx):
text = convert_shell_script(ctx, ctx.attr.script)
@ -18,6 +18,6 @@ shell_script_helper_test_rule = rule(
"script": attr.string_list(mandatory = True),
},
toolchains = [
"@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:shell_commands",
"@rules_foreign_cc//foreign_cc/private/framework:shell_toolchain",
],
)

View File

@ -3,7 +3,7 @@
load("@rules_foreign_cc//foreign_cc/private:detect_root.bzl", "detect_root", "filter_containing_dirs_from_inputs")
# buildifier: disable=bzl-visibility
load("@rules_foreign_cc//foreign_cc/private:shell_script_helper.bzl", "convert_shell_script")
load("@rules_foreign_cc//foreign_cc/private/framework:helpers.bzl", "convert_shell_script")
def _symlink_contents_to_dir_test_rule_impl(ctx):
out = ctx.actions.declare_file(ctx.attr.out)
@ -37,6 +37,6 @@ symlink_contents_to_dir_test_rule = rule(
"out": attr.string(),
},
toolchains = [
"@rules_foreign_cc//foreign_cc/private/shell_toolchain/toolchains:shell_commands",
"@rules_foreign_cc//foreign_cc/private/framework:shell_toolchain",
],
)