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
|
"""Stateify is a tool for generating state wrappers for Go types.
The recommended way is to use the go_library rule defined below with mostly
identical configuration as the native go_library rule.
load("//tools/go_stateify:defs.bzl", "go_library")
go_library(
name = "foo",
srcs = ["foo.go"],
)
Under the hood, the go_stateify rule is used to generate a file that will
appear in a Go target; the output file should appear explicitly in a srcs list.
For example (the above is still the preferred way):
load("//tools/go_stateify:defs.bzl", "go_stateify")
go_stateify(
name = "foo_state",
srcs = ["foo.go"],
out = "foo_state.go",
package = "foo",
)
go_library(
name = "foo",
srcs = [
"foo.go",
"foo_state.go",
],
deps = [
"//pkg/state",
],
)
"""
load("@io_bazel_rules_go//go:def.bzl", _go_library = "go_library")
def _go_stateify_impl(ctx):
"""Implementation for the stateify tool."""
output = ctx.outputs.out
# Run the stateify command.
args = ["-output=%s" % output.path]
args += ["-pkg=%s" % ctx.attr.package]
args += ["-arch=%s" % ctx.attr.arch]
if ctx.attr._statepkg:
args += ["-statepkg=%s" % ctx.attr._statepkg]
if ctx.attr.imports:
args += ["-imports=%s" % ",".join(ctx.attr.imports)]
args += ["--"]
for src in ctx.attr.srcs:
args += [f.path for f in src.files.to_list()]
ctx.actions.run(
inputs = ctx.files.srcs,
outputs = [output],
mnemonic = "GoStateify",
progress_message = "Generating state library %s" % ctx.label,
arguments = args,
executable = ctx.executable._tool,
)
go_stateify = rule(
implementation = _go_stateify_impl,
doc = "Generates save and restore logic from a set of Go files.",
attrs = {
"srcs": attr.label_list(
doc = """
The input source files. These files should include all structs in the package
that need to be saved.
""",
mandatory = True,
allow_files = True,
),
"imports": attr.string_list(
doc = """
An optional list of extra non-aliased, Go-style absolute import paths required
for statified types.
""",
mandatory = False,
),
"package": attr.string(
doc = "The package name for the input sources.",
mandatory = True,
),
"arch": attr.string(
doc = "Target platform.",
mandatory = True,
),
"out": attr.output(
doc = """
The name of the generated file output. This must not conflict with any other
files and must be added to the srcs of the relevant go_library.
""",
mandatory = True,
),
"_tool": attr.label(
executable = True,
cfg = "host",
default = Label("//tools/go_stateify:stateify"),
),
"_statepkg": attr.string(default = "gvisor.dev/gvisor/pkg/state"),
},
)
def go_library(name, srcs, deps = [], imports = [], **kwargs):
"""Standard go_library wrapped which generates state source files.
Args:
name: the name of the go_library rule.
srcs: sources of the go_library. Each will be processed for stateify
annotations.
deps: dependencies for the go_library.
imports: an optional list of extra non-aliased, Go-style absolute import
paths required for stateified types.
**kwargs: passed to go_library.
"""
if "encode_unsafe.go" not in srcs and (name + "_state_autogen.go") not in srcs:
# Only do stateification for non-state packages without manual autogen.
go_stateify(
name = name + "_state_autogen",
srcs = [src for src in srcs if src.endswith(".go")],
imports = imports,
package = name,
arch = select({
"@bazel_tools//src/conditions:linux_aarch64": "arm64",
"//conditions:default": "amd64",
}),
out = name + "_state_autogen.go",
)
all_srcs = srcs + [name + "_state_autogen.go"]
if "//pkg/state" not in deps:
all_deps = deps + ["//pkg/state"]
else:
all_deps = deps
else:
all_deps = deps
all_srcs = srcs
_go_library(
name = name,
srcs = all_srcs,
deps = all_deps,
**kwargs
)
|