forked from protocolbuffers/protobuf
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinternal.bzl
More file actions
161 lines (143 loc) · 5.55 KB
/
internal.bzl
File metadata and controls
161 lines (143 loc) · 5.55 KB
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
"""
Internal helpers for building the Python protobuf runtime.
"""
load("@rules_python//python:py_test.bzl", "py_test")
# Adapted from https://github.com/bazelbuild/bazel-skylib/blob/main/rules/private/copy_common.bzl#L47
InternalOsInfo = provider(
doc = "Information about the target platform's OS.",
fields = ["is_windows"],
)
# Adapted from https://github.com/bazelbuild/bazel-skylib/blob/main/rules/private/copy_common.bzl#L52
internal_is_windows = rule(
implementation = lambda ctx: InternalOsInfo(
is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]),
),
attrs = {
"_windows_constraint": attr.label(default = "@platforms//os:windows"),
},
)
def _remove_cross_repo_path(path):
components = path.split("/")
if components[0] == "..":
return "/".join(components[2:])
return path
def _internal_copy_files_impl(ctx):
strip_prefix = ctx.attr.strip_prefix
if strip_prefix[-1] != "/":
strip_prefix += "/"
src_dests = []
for src in ctx.files.srcs:
short_path = _remove_cross_repo_path(src.short_path)
if short_path[:len(strip_prefix)] != strip_prefix:
fail("Source does not start with %s: %s" %
(strip_prefix, short_path))
dest = ctx.actions.declare_file(short_path[len(strip_prefix):])
src_dests.append([src, dest])
# Windows check adapted from
# https://github.com/bazelbuild/bazel-skylib/blob/main/rules/private/copy_file_private.bzl#L71C10-L71C54
if ctx.attr._exec_is_windows[InternalOsInfo].is_windows:
bat_file = ctx.actions.declare_file(ctx.label.name + "_copy.bat")
ctx.actions.write(
output = bat_file,
content = "\r\n".join([
'@copy /Y "{}" "{}" >NUL'.format(
src.path.replace("/", "\\"),
dest.path.replace("/", "\\"),
)
for src, dest in src_dests
]) + "\r\n",
)
ctx.actions.run(
inputs = ctx.files.srcs,
tools = [bat_file],
outputs = [dest for src, dest in src_dests],
executable = "cmd.exe",
arguments = ["/C", bat_file.path.replace("/", "\\")],
mnemonic = "InternalCopyFile",
progress_message = "Copying files",
use_default_shell_env = True,
toolchain = None,
)
else:
sh_file = ctx.actions.declare_file(ctx.label.name + "_copy.sh")
ctx.actions.write(
output = sh_file,
content = "\n".join([
'cp -f "{}" "{}"'.format(src.path, dest.path)
for src, dest in src_dests
]),
)
ctx.actions.run(
inputs = ctx.files.srcs,
tools = [sh_file],
outputs = [dest for src, dest in src_dests],
executable = "bash",
arguments = [sh_file.path],
mnemonic = "InternalCopyFile",
progress_message = "Copying files",
use_default_shell_env = True,
toolchain = None,
)
return [
DefaultInfo(files = depset([dest for src, dest in src_dests])),
]
internal_copy_files_impl = rule(
doc = """
Implementation for internal_copy_files macro.
This rule implements file copying, including a compatibility mode for Windows.
""",
implementation = _internal_copy_files_impl,
attrs = {
"srcs": attr.label_list(allow_files = True, providers = [DefaultInfo]),
"strip_prefix": attr.string(),
# Adapted from https://github.com/bazelbuild/bazel-skylib/blob/main/rules/private/copy_file_private.bzl#L91C1-L96C7
"_exec_is_windows": attr.label(
default = ":is_windows",
# The exec transition must match the exec group of the actions, which in
# this case is the default exec group.
cfg = "exec",
),
},
)
def internal_copy_files(name, srcs, strip_prefix, **kwargs):
"""Copies common proto files to the python tree.
In order for Python imports to work, generated proto interfaces under
the google.protobuf package need to be in the same directory as other
source files. This rule copies the .proto files themselves, e.g. with
strip_prefix = 'src', 'src/google/protobuf/blah.proto' could be copied
to '<package>/google/protobuf/blah.proto'.
(An alternative might be to implement a separate rule to generate
Python code in a different location for the sources. However, this
would be strange behavior that doesn't match any other language's proto
library generation.)
Args:
name: the name for the rule.
srcs: the sources.
strip_prefix: the prefix to remove from each of the paths in 'srcs'. The
remainder will be used to construct the output path.
**kwargs: common rule arguments.
"""
internal_copy_files_impl(
name = name,
srcs = srcs,
strip_prefix = strip_prefix,
**kwargs
)
def internal_py_test(deps = [], **kwargs):
"""Internal wrapper for shared test configuration
Args:
deps: any additional dependencies of the test.
**kwargs: arguments forwarded to py_test.
"""
py_test(
imports = ["."],
deps = deps + [
"//python:python_test_lib",
"@com_google_absl_py//absl/testing:parameterized",
],
target_compatible_with = select({
"@system_python//:supported": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
**kwargs
)