gvisor/tools/go_stateify/defs.bzl

146 lines
4.3 KiB
Python
Raw Normal View History

"""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.append("-pkg=%s" % ctx.attr.package)
args.append("-arch=%s" % ctx.attr.arch)
if ctx.attr._statepkg:
args.append("-statepkg=%s" % ctx.attr._statepkg)
if ctx.attr.imports:
args.append("-imports=%s" % ",".join(ctx.attr.imports))
args.append("--")
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
)