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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
|
"""Wrappers for common build rules.
These wrappers apply common BUILD configurations (e.g., proto_library
automagically creating cc_ and go_ proto targets) and act as a single point of
change for Google-internal and bazel-compatible rules.
"""
load("//tools/go_stateify:defs.bzl", "go_stateify")
load("//tools/go_marshal:defs.bzl", "go_marshal", "marshal_deps", "marshal_test_deps")
load("//tools/bazeldefs:defs.bzl", _build_test = "build_test", _bzl_library = "bzl_library", _cc_binary = "cc_binary", _cc_flags_supplier = "cc_flags_supplier", _cc_grpc_library = "cc_grpc_library", _cc_library = "cc_library", _cc_proto_library = "cc_proto_library", _cc_test = "cc_test", _cc_toolchain = "cc_toolchain", _coreutil = "coreutil", _default_installer = "default_installer", _default_net_util = "default_net_util", _gazelle = "gazelle", _gbenchmark = "gbenchmark", _go_binary = "go_binary", _go_embed_data = "go_embed_data", _go_grpc_and_proto_libraries = "go_grpc_and_proto_libraries", _go_library = "go_library", _go_path = "go_path", _go_proto_library = "go_proto_library", _go_test = "go_test", _grpcpp = "grpcpp", _gtest = "gtest", _loopback = "loopback", _pkg_deb = "pkg_deb", _pkg_tar = "pkg_tar", _proto_library = "proto_library", _py_binary = "py_binary", _rbe_platform = "rbe_platform", _rbe_toolchain = "rbe_toolchain", _select_arch = "select_arch", _select_system = "select_system", _short_path = "short_path", _vdso_linker_option = "vdso_linker_option")
load("//tools/bazeldefs:platforms.bzl", _default_platform = "default_platform", _platforms = "platforms")
load("//tools/bazeldefs:tags.bzl", "go_suffixes")
load("//tools/nogo:defs.bzl", "nogo_test")
# Delegate directly.
build_test = _build_test
bzl_library = _bzl_library
cc_binary = _cc_binary
cc_flags_supplier = _cc_flags_supplier
cc_grpc_library = _cc_grpc_library
cc_library = _cc_library
cc_test = _cc_test
cc_toolchain = _cc_toolchain
default_installer = _default_installer
default_net_util = _default_net_util
gbenchmark = _gbenchmark
gazelle = _gazelle
go_embed_data = _go_embed_data
go_path = _go_path
gtest = _gtest
grpcpp = _grpcpp
loopback = _loopback
pkg_deb = _pkg_deb
pkg_tar = _pkg_tar
py_binary = _py_binary
select_arch = _select_arch
select_system = _select_system
short_path = _short_path
rbe_platform = _rbe_platform
rbe_toolchain = _rbe_toolchain
vdso_linker_option = _vdso_linker_option
coreutil = _coreutil
# Platform options.
default_platform = _default_platform
platforms = _platforms
def go_binary(name, nogo = True, pure = False, static = False, x_defs = None, **kwargs):
"""Wraps the standard go_binary.
Args:
name: the rule name.
nogo: enable nogo analysis.
pure: build a pure Go (no CGo) binary.
static: build a static binary.
x_defs: additional linker definitions.
**kwargs: standard go_binary arguments.
"""
_go_binary(
name = name,
pure = pure,
static = static,
x_defs = x_defs,
**kwargs
)
if nogo:
# Note that the nogo rule applies only for go_library and go_test
# targets, therefore we construct a library from the binary sources.
_go_library(
name = name + "_nogo_library",
**kwargs
)
nogo_test(
name = name + "_nogo",
library = ":" + name + "_nogo_library",
)
def calculate_sets(srcs):
"""Calculates special Go sets for templates.
Args:
srcs: the full set of Go sources.
Returns:
A dictionary of the form:
"": [src1.go, src2.go]
"suffix": [src3suffix.go, src4suffix.go]
Note that suffix will typically start with '_'.
"""
result = dict()
for file in srcs:
if not file.endswith(".go"):
continue
target = ""
for suffix in go_suffixes:
if file.endswith(suffix + ".go"):
target = suffix
if not target in result:
result[target] = [file]
else:
result[target].append(file)
return result
def go_imports(name, src, out):
"""Simplify a single Go source file by eliminating unused imports."""
native.genrule(
name = name,
srcs = [src],
outs = [out],
tools = ["@org_golang_x_tools//cmd/goimports:goimports"],
cmd = ("$(location @org_golang_x_tools//cmd/goimports:goimports) $(SRCS) > $@"),
)
def go_library(name, srcs, deps = [], imports = [], stateify = True, marshal = False, marshal_debug = False, nogo = True, **kwargs):
"""Wraps the standard go_library and does stateification and marshalling.
The recommended way is to use this rule with mostly identical configuration as the native
go_library rule.
These definitions provide additional flags (stateify, marshal) that can be used
with the generators to automatically supplement the library code.
load("//tools:defs.bzl", "go_library")
go_library(
name = "foo",
srcs = ["foo.go"],
)
Args:
name: the rule name.
srcs: the library sources.
deps: the library dependencies.
imports: imports required for stateify.
stateify: whether statify is enabled (default: true).
marshal: whether marshal is enabled (default: false).
marshal_debug: whether the gomarshal tools emits debugging output (default: false).
nogo: enable nogo analysis.
**kwargs: standard go_library arguments.
"""
all_srcs = srcs
all_deps = deps
dirname, _, _ = native.package_name().rpartition("/")
full_pkg = dirname + "/" + name
if stateify:
# Only do stateification for non-state packages without manual autogen.
# First, we need to segregate the input files via the special suffixes,
# and calculate the final output set.
state_sets = calculate_sets(srcs)
for (suffix, src_subset) in state_sets.items():
go_stateify(
name = name + suffix + "_state_autogen_with_imports",
srcs = src_subset,
imports = imports,
package = full_pkg,
out = name + suffix + "_state_autogen_with_imports.go",
)
go_imports(
name = name + suffix + "_state_autogen",
src = name + suffix + "_state_autogen_with_imports.go",
out = name + suffix + "_state_autogen.go",
)
all_srcs = all_srcs + [
name + suffix + "_state_autogen.go"
for suffix in state_sets.keys()
]
if "//pkg/state" not in all_deps:
all_deps = all_deps + ["//pkg/state"]
if marshal:
# See above.
marshal_sets = calculate_sets(srcs)
for (suffix, src_subset) in marshal_sets.items():
go_marshal(
name = name + suffix + "_abi_autogen",
srcs = src_subset,
debug = select({
"//tools/go_marshal:marshal_config_verbose": True,
"//conditions:default": marshal_debug,
}),
imports = imports,
package = name,
)
extra_deps = [
dep
for dep in marshal_deps
if not dep in all_deps
]
all_deps = all_deps + extra_deps
all_srcs = all_srcs + [
name + suffix + "_abi_autogen_unsafe.go"
for suffix in marshal_sets.keys()
]
_go_library(
name = name,
srcs = all_srcs,
deps = all_deps,
**kwargs
)
if nogo:
nogo_test(
name = name + "_nogo",
library = ":" + name,
)
if marshal:
# Ignore importpath for go_test.
kwargs.pop("importpath", None)
# See above.
marshal_sets = calculate_sets(srcs)
for (suffix, _) in marshal_sets.items():
_go_test(
name = name + suffix + "_abi_autogen_test",
srcs = [
name + suffix + "_abi_autogen_test.go",
name + suffix + "_abi_autogen_unconditional_test.go",
],
library = ":" + name,
deps = marshal_test_deps,
**kwargs
)
def go_test(name, nogo = True, **kwargs):
"""Wraps the standard go_test.
Args:
name: the rule name.
nogo: enable nogo analysis.
**kwargs: standard go_test arguments.
"""
_go_test(
name = name,
**kwargs
)
if nogo:
nogo_test(
name = name + "_nogo",
library = ":" + name,
)
def proto_library(name, srcs, deps = None, has_services = 0, **kwargs):
"""Wraps the standard proto_library.
Given a proto_library named "foo", this produces up to five different
targets:
- foo_proto: proto_library rule.
- foo_go_proto: go_proto_library rule.
- foo_cc_proto: cc_proto_library rule.
- foo_go_grpc_proto: go_grpc_library rule.
- foo_cc_grpc_proto: cc_grpc_library rule.
Args:
name: the name to which _proto, _go_proto, etc, will be appended.
srcs: the proto sources.
deps: for the proto library and the go_proto_library.
has_services: 1 to build gRPC code, otherwise 0.
**kwargs: standard proto_library arguments.
"""
_proto_library(
name = name + "_proto",
srcs = srcs,
deps = deps,
has_services = has_services,
**kwargs
)
if has_services:
_go_grpc_and_proto_libraries(
name = name,
deps = deps,
**kwargs
)
else:
_go_proto_library(
name = name,
deps = deps,
**kwargs
)
_cc_proto_library(
name = name + "_cc_proto",
deps = [":" + name + "_proto"],
**kwargs
)
if has_services:
_cc_grpc_library(
name = name + "_cc_grpc_proto",
srcs = [":" + name + "_proto"],
deps = [":" + name + "_cc_proto"],
**kwargs
)
|