fix: fix host platform detection on all copy actions which always run locally (#241)

This commit is contained in:
Greg Magolan 2022-09-12 20:45:48 -07:00 committed by GitHub
parent aa42a924fe
commit bbfb74c8e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 114 additions and 41 deletions

View File

@ -35,3 +35,10 @@ go_rules_dependencies()
go_register_toolchains(version = "1.17.2")
gazelle_dependencies()
# buildifier: disable=bzl-visibility
load("//lib/private:local_config_platform.bzl", "local_config_platform")
local_config_platform(
name = "local_config_platform",
)

View File

@ -58,6 +58,6 @@ other rule implementations.
| <a id="copy_directory_action-ctx"></a>ctx | The rule context. | none |
| <a id="copy_directory_action-src"></a>src | The directory to make a copy of. Can be a source directory or TreeArtifact. | none |
| <a id="copy_directory_action-dst"></a>dst | The directory to copy to. Must be a TreeArtifact. | none |
| <a id="copy_directory_action-is_windows"></a>is_windows | If true, an cmd.exe action is created so there is no bash dependency. | <code>False</code> |
| <a id="copy_directory_action-is_windows"></a>is_windows | Deprecated and unused | <code>None</code> |

2
docs/copy_file.md generated
View File

@ -72,6 +72,6 @@ other rule implementations.
| <a id="copy_file_action-src"></a>src | The source file to copy or TreeArtifact to copy a single file out of. | none |
| <a id="copy_file_action-dst"></a>dst | The destination file. | none |
| <a id="copy_file_action-dir_path"></a>dir_path | If src is a TreeArtifact, the path within the TreeArtifact to the file to copy. | <code>None</code> |
| <a id="copy_file_action-is_windows"></a>is_windows | If true, an cmd.exe action is created so there is no bash dependency. | <code>False</code> |
| <a id="copy_file_action-is_windows"></a>is_windows | Deprecated and unused | <code>None</code> |

4
docs/copy_to_bin.md generated
View File

@ -33,7 +33,7 @@ without a copy action.
| :------------- | :------------- | :------------- |
| <a id="copy_file_to_bin_action-ctx"></a>ctx | The rule context. | none |
| <a id="copy_file_to_bin_action-file"></a>file | The file to copy. | none |
| <a id="copy_file_to_bin_action-is_windows"></a>is_windows | If true, an cmd.exe action is created so there is no bash dependency. | <code>False</code> |
| <a id="copy_file_to_bin_action-is_windows"></a>is_windows | Deprecated and unused | <code>None</code> |
**RETURNS**
@ -64,7 +64,7 @@ directly to the result without a copy action.
| :------------- | :------------- | :------------- |
| <a id="copy_files_to_bin_actions-ctx"></a>ctx | The rule context. | none |
| <a id="copy_files_to_bin_actions-files"></a>files | List of File objects. | none |
| <a id="copy_files_to_bin_actions-is_windows"></a>is_windows | If true, an cmd.exe action is created so there is no bash dependency. | <code>False</code> |
| <a id="copy_files_to_bin_actions-is_windows"></a>is_windows | Deprecated and unused | <code>None</code> |
**RETURNS**

View File

@ -72,7 +72,7 @@ other rule implementations where additional_files can also be passed in.
| <a id="copy_to_directory_action-exclude_prefixes"></a>exclude_prefixes | List of path prefixes to exclude from output directory. | <code>[]</code> |
| <a id="copy_to_directory_action-replace_prefixes"></a>replace_prefixes | Map of paths prefixes to replace in the output directory path when copying files.<br><br>See copy_to_directory rule documentation for more details. | <code>{}</code> |
| <a id="copy_to_directory_action-allow_overwrites"></a>allow_overwrites | If True, allow files to be overwritten if the same output file is copied to twice.<br><br>See copy_to_directory rule documentation for more details. | <code>False</code> |
| <a id="copy_to_directory_action-is_windows"></a>is_windows | If true, an cmd.exe action is created so there is no bash dependency. | <code>False</code> |
| <a id="copy_to_directory_action-is_windows"></a>is_windows | Deprecated and unused | <code>None</code> |
<a id="copy_to_directory_lib.impl"></a>

View File

@ -8,13 +8,18 @@ exports_files(
)
exports_files(
["diff_test_tmpl.sh", "diff_test_tmpl.bat", "parse_status_file.jq"],
[
"diff_test_tmpl.sh",
"diff_test_tmpl.bat",
"parse_status_file.jq",
],
visibility = ["//visibility:public"],
)
bzl_library(
name = "copy_common",
srcs = ["copy_common.bzl"],
deps = ["@local_config_platform//:constraints"],
)
bzl_library(

View File

@ -1,5 +1,7 @@
"Helpers for copy rules"
load("@local_config_platform//:constraints.bzl", "HOST_CONSTRAINTS")
# Hints for Bazel spawn strategy
COPY_EXECUTION_REQUIREMENTS = {
# ----------------+-----------------------------------------------------------------------------
@ -57,3 +59,6 @@ COPY_EXECUTION_REQUIREMENTS = {
"no-sandbox": "1",
"local": "1",
}
def is_windows_host():
return "@platforms//os:windows" in HOST_CONSTRAINTS

View File

@ -4,7 +4,7 @@ This rule copies a directory to another location using Bash (on Linux/macOS) or
cmd.exe (on Windows).
"""
load(":copy_common.bzl", _COPY_EXECUTION_REQUIREMENTS = "COPY_EXECUTION_REQUIREMENTS")
load(":copy_common.bzl", _COPY_EXECUTION_REQUIREMENTS = "COPY_EXECUTION_REQUIREMENTS", _is_windows_host = "is_windows_host")
def _copy_cmd(ctx, src, dst):
# Most Windows binaries built with MSVC use a certain argument quoting
@ -61,7 +61,7 @@ def _copy_bash(ctx, src, dst):
execution_requirements = _COPY_EXECUTION_REQUIREMENTS,
)
def copy_directory_action(ctx, src, dst, is_windows = False):
def copy_directory_action(ctx, src, dst, is_windows = None):
"""Helper function that creates an action to copy a directory from src to dst.
This helper is used by copy_directory. It is exposed as a public API so it can be used within
@ -71,22 +71,27 @@ def copy_directory_action(ctx, src, dst, is_windows = False):
ctx: The rule context.
src: The directory to make a copy of. Can be a source directory or TreeArtifact.
dst: The directory to copy to. Must be a TreeArtifact.
is_windows: If true, an cmd.exe action is created so there is no bash dependency.
is_windows: Deprecated and unused
"""
# TODO(2.0): remove depcreated & unused is_windows parameter
if not src.is_source and not dst.is_directory:
fail("src must be a source directory or TreeArtifact")
if dst.is_source or not dst.is_directory:
fail("dst must be a TreeArtifact")
# Because copy actions have "local" execution requirements, we can safely assume
# the execution is the same as the host platform and generate different actions for Windows
# and non-Windows host platforms
is_windows = _is_windows_host()
if is_windows:
_copy_cmd(ctx, src, dst)
else:
_copy_bash(ctx, src, dst)
def _copy_directory_impl(ctx):
is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
dst = ctx.actions.declare_directory(ctx.attr.out)
copy_directory_action(ctx, ctx.file.src, dst, is_windows)
copy_directory_action(ctx, ctx.file.src, dst)
files = depset(direct = [dst])
runfiles = ctx.runfiles(files = [dst])
@ -101,7 +106,6 @@ _copy_directory = rule(
# Cannot declare out as an output here, because there's no API for declaring
# TreeArtifact outputs.
"out": attr.string(mandatory = True),
"_windows_constraint": attr.label(default = "@platforms//os:windows"),
},
)

View File

@ -24,7 +24,7 @@ cmd.exe (on Windows). `_copy_xfile` marks the resulting file executable,
`_copy_file` does not.
"""
load(":copy_common.bzl", _COPY_EXECUTION_REQUIREMENTS = "COPY_EXECUTION_REQUIREMENTS")
load(":copy_common.bzl", _COPY_EXECUTION_REQUIREMENTS = "COPY_EXECUTION_REQUIREMENTS", _is_windows_host = "is_windows_host")
load(":directory_path.bzl", "DirectoryPathInfo")
def _copy_cmd(ctx, src, src_path, dst):
@ -83,7 +83,7 @@ def _copy_bash(ctx, src, src_path, dst):
execution_requirements = _COPY_EXECUTION_REQUIREMENTS,
)
def copy_file_action(ctx, src, dst, dir_path = None, is_windows = False):
def copy_file_action(ctx, src, dst, dir_path = None, is_windows = None):
"""Helper function that creates an action to copy a file from src to dst.
If src is a TreeArtifact, dir_path must be specified as the path within
@ -97,8 +97,10 @@ def copy_file_action(ctx, src, dst, dir_path = None, is_windows = False):
src: The source file to copy or TreeArtifact to copy a single file out of.
dst: The destination file.
dir_path: If src is a TreeArtifact, the path within the TreeArtifact to the file to copy.
is_windows: If true, an cmd.exe action is created so there is no bash dependency.
is_windows: Deprecated and unused
"""
# TODO(2.0): remove depcreated & unused is_windows parameter
if dst.is_directory:
fail("dst must not be a TreeArtifact")
if src.is_directory:
@ -107,14 +109,17 @@ def copy_file_action(ctx, src, dst, dir_path = None, is_windows = False):
src_path = "/".join([src.path, dir_path])
else:
src_path = src.path
# Because copy actions have "local" execution requirements, we can safely assume
# the execution is the same as the host platform and generate different actions for Windows
# and non-Windows host platforms
is_windows = _is_windows_host()
if is_windows:
_copy_cmd(ctx, src, src_path, dst)
else:
_copy_bash(ctx, src, src_path, dst)
def _copy_file_impl(ctx):
is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
if ctx.attr.allow_symlink:
if len(ctx.files.src) != 1:
fail("src must be a single file when allow_symlink is True")
@ -131,14 +136,13 @@ def _copy_file_impl(ctx):
ctx.attr.src[DirectoryPathInfo].directory,
ctx.outputs.out,
dir_path = ctx.attr.src[DirectoryPathInfo].path,
is_windows = is_windows,
)
else:
if len(ctx.files.src) != 1:
fail("src must be a single file or a target that provides a DirectoryPathInfo")
if ctx.files.src[0].is_directory:
fail("cannot use copy_file on a directory; try copy_directory instead")
copy_file_action(ctx, ctx.files.src[0], ctx.outputs.out, is_windows = is_windows)
copy_file_action(ctx, ctx.files.src[0], ctx.outputs.out)
files = depset(direct = [ctx.outputs.out])
runfiles = ctx.runfiles(files = [ctx.outputs.out])
@ -152,7 +156,6 @@ _ATTRS = {
"is_executable": attr.bool(mandatory = True),
"allow_symlink": attr.bool(mandatory = True),
"out": attr.output(mandatory = True),
"_windows_constraint": attr.label(default = "@platforms//os:windows"),
}
_copy_file = rule(

View File

@ -17,7 +17,7 @@
load("@bazel_skylib//lib:paths.bzl", "paths")
load(":copy_file.bzl", "copy_file_action")
def copy_file_to_bin_action(ctx, file, is_windows = False):
def copy_file_to_bin_action(ctx, file, is_windows = None):
"""Helper function that creates an action to copy a file to the output tree.
File are copied to the same workspace-relative path. The resulting files is
@ -29,11 +29,13 @@ def copy_file_to_bin_action(ctx, file, is_windows = False):
Args:
ctx: The rule context.
file: The file to copy.
is_windows: If true, an cmd.exe action is created so there is no bash dependency.
is_windows: Deprecated and unused
Returns:
A File in the output tree.
"""
# TODO(2.0): remove depcreated & unused is_windows parameter
if not file.is_source:
return file
if ctx.label.workspace_name != file.owner.workspace_name:
@ -89,7 +91,7 @@ target to {file_package} using:
package = "%s//%s" % (curr_package_label.workspace_name, curr_package_label.package),
)
def copy_files_to_bin_actions(ctx, files, is_windows = False):
def copy_files_to_bin_actions(ctx, files, is_windows = None):
"""Helper function that creates actions to copy files to the output tree.
Files are copied to the same workspace-relative path. The resulting list of
@ -101,17 +103,17 @@ def copy_files_to_bin_actions(ctx, files, is_windows = False):
Args:
ctx: The rule context.
files: List of File objects.
is_windows: If true, an cmd.exe action is created so there is no bash dependency.
is_windows: Deprecated and unused
Returns:
List of File objects in the output tree.
"""
# TODO(2.0): remove depcreated & unused is_windows parameter
return [copy_file_to_bin_action(ctx, file, is_windows = is_windows) for file in files]
def _impl(ctx):
is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
files = copy_files_to_bin_actions(ctx, ctx.files.srcs, is_windows = is_windows)
files = copy_files_to_bin_actions(ctx, ctx.files.srcs)
return DefaultInfo(
files = depset(files),
runfiles = ctx.runfiles(files = files),
@ -122,7 +124,6 @@ _copy_to_bin = rule(
provides = [DefaultInfo],
attrs = {
"srcs": attr.label_list(mandatory = True, allow_files = True),
"_windows_constraint": attr.label(default = "@platforms//os:windows"),
},
)

View File

@ -1,7 +1,7 @@
"copy_to_directory implementation"
load("@bazel_skylib//lib:paths.bzl", skylib_paths = "paths")
load(":copy_common.bzl", _COPY_EXECUTION_REQUIREMENTS = "COPY_EXECUTION_REQUIREMENTS")
load(":copy_common.bzl", _COPY_EXECUTION_REQUIREMENTS = "COPY_EXECUTION_REQUIREMENTS", _is_windows_host = "is_windows_host")
load(":paths.bzl", "paths")
load(":directory_path.bzl", "DirectoryPathInfo")
load(":glob_match.bzl", "glob_match")
@ -279,7 +279,6 @@ _copy_to_directory_attr = {
This setting has no effect on Windows where overwrites are always allowed.""",
),
"_windows_constraint": attr.label(default = "@platforms//os:windows"),
}
def _any_globs_match(exprs, path):
@ -580,11 +579,10 @@ if exist "{src}\\*" (
mnemonic = "CopyToDirectory",
progress_message = "Copying files to directory",
use_default_shell_env = True,
execution_requirements = _COPY_EXECUTION_REQUIREMENTS,
)
def _copy_to_directory_impl(ctx):
is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
dst = ctx.actions.declare_directory(ctx.attr.out if ctx.attr.out else ctx.attr.name)
copy_to_directory_action(
@ -600,7 +598,6 @@ def _copy_to_directory_impl(ctx):
exclude_prefixes = ctx.attr.exclude_prefixes,
replace_prefixes = ctx.attr.replace_prefixes,
allow_overwrites = ctx.attr.allow_overwrites,
is_windows = is_windows,
)
return [
@ -640,7 +637,7 @@ def copy_to_directory_action(
exclude_prefixes = [],
replace_prefixes = {},
allow_overwrites = False,
is_windows = False):
is_windows = None):
"""Helper function to copy files to a directory.
This helper is used by copy_to_directory. It is exposed as a public API so it can be used within
@ -689,8 +686,10 @@ def copy_to_directory_action(
See copy_to_directory rule documentation for more details.
is_windows: If true, an cmd.exe action is created so there is no bash dependency.
is_windows: Deprecated and unused
"""
# TODO(2.0): remove depcreated & unused is_windows parameter
if not srcs:
fail("srcs must not be empty")
@ -762,6 +761,10 @@ def copy_to_directory_action(
if not copy_paths:
fail("There are no files or directories to copy after applying filters. Are your 'include_srcs_patterns' and 'exclude_srcs_patterns' attributes correct?")
# Because copy actions have "local" execution requirements, we can safely assume
# the execution is the same as the host platform and generate different actions for Windows
# and non-Windows host platforms
is_windows = _is_windows_host()
if is_windows:
_copy_to_dir_cmd(ctx, copy_paths, dst)
else:

View File

@ -0,0 +1,49 @@
"""Work-around for getting a bzl_library for @local_config_platform//:constraints.bzl load
For internal use only
"""
load(":repo_utils.bzl", "repo_utils")
def _impl(rctx):
rctx.file("BUILD.bazel", """load(':constraints.bzl', 'HOST_CONSTRAINTS')
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
package(default_visibility = ['//visibility:public'])
platform(name = 'host',
# Auto-detected host platform constraints.
constraint_values = HOST_CONSTRAINTS,
)
bzl_library(
name = "constraints",
srcs = ["constraints.bzl"],
visibility = ["//visibility:public"],
)
""")
# TODO: we can detect the host CPU in the future as well if needed;
# see the repo_utils.platform(rctx) function for an example of this
if repo_utils.is_darwin(rctx):
rctx.file("constraints.bzl", content = """HOST_CONSTRAINTS = [
'@platforms//cpu:x86_64',
'@platforms//os:osx',
]
""")
elif repo_utils.is_windows(rctx):
rctx.file("constraints.bzl", content = """HOST_CONSTRAINTS = [
'@platforms//cpu:x86_64',
'@platforms//os:windows',
]
""")
else:
rctx.file("constraints.bzl", content = """HOST_CONSTRAINTS = [
'@platforms//cpu:x86_64',
'@platforms//os:linux',
]
""")
local_config_platform = repository_rule(
implementation = _impl,
)

View File

@ -8,12 +8,9 @@ load(":other_info.bzl", "OtherInfo")
_attrs = {
"srcs": attr.label_list(allow_files = True),
"out": attr.string(mandatory = True),
"_windows_constraint": attr.label(default = "@platforms//os:windows"),
}
def _impl(ctx):
is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
dst = ctx.actions.declare_directory(ctx.attr.out)
additional_files_depsets = []
@ -27,8 +24,7 @@ def _impl(ctx):
ctx,
srcs = ctx.attr.srcs,
dst = dst,
additional_files = depset(transitive = additional_files_depsets).to_list(),
is_windows = is_windows,
additional_files = depset(transitive = additional_files_depsets),
)
return [