summaryrefslogtreecommitdiffhomepage
path: root/tools/nogo/defs.bzl
diff options
context:
space:
mode:
Diffstat (limited to 'tools/nogo/defs.bzl')
-rw-r--r--tools/nogo/defs.bzl162
1 files changed, 108 insertions, 54 deletions
diff --git a/tools/nogo/defs.bzl b/tools/nogo/defs.bzl
index 0c48a7a5a..ddf5816a6 100644
--- a/tools/nogo/defs.bzl
+++ b/tools/nogo/defs.bzl
@@ -29,6 +29,7 @@ NogoTargetInfo = provider(
fields = {
"goarch": "the build architecture (GOARCH)",
"goos": "the build OS target (GOOS)",
+ "worker_debug": "transitive debugging",
},
)
@@ -36,6 +37,7 @@ def _nogo_target_impl(ctx):
return [NogoTargetInfo(
goarch = ctx.attr.goarch,
goos = ctx.attr.goos,
+ worker_debug = ctx.attr.worker_debug,
)]
nogo_target = go_rule(
@@ -50,6 +52,10 @@ nogo_target = go_rule(
doc = "the Go OS target (propagated to other rules).",
mandatory = True,
),
+ "worker_debug": attr.bool(
+ doc = "whether worker debugging should be enabled.",
+ default = False,
+ ),
},
)
@@ -61,7 +67,7 @@ def _nogo_objdump_tool_impl(ctx):
# we need the tool to handle this case by creating a temporary file.
#
# [1] https://github.com/golang/go/issues/41051
- nogo_target_info = ctx.attr._nogo_target[NogoTargetInfo]
+ nogo_target_info = ctx.attr._target[NogoTargetInfo]
go_ctx = go_context(ctx, goos = nogo_target_info.goos, goarch = nogo_target_info.goarch)
env_prefix = " ".join(["%s=%s" % (key, value) for (key, value) in go_ctx.env.items()])
dumper = ctx.actions.declare_file(ctx.label.name)
@@ -94,7 +100,7 @@ nogo_objdump_tool = go_rule(
rule,
implementation = _nogo_objdump_tool_impl,
attrs = {
- "_nogo_target": attr.label(
+ "_target": attr.label(
default = "//tools/nogo:target",
cfg = "target",
),
@@ -112,7 +118,7 @@ NogoStdlibInfo = provider(
def _nogo_stdlib_impl(ctx):
# Build the standard library facts.
- nogo_target_info = ctx.attr._nogo_target[NogoTargetInfo]
+ nogo_target_info = ctx.attr._target[NogoTargetInfo]
go_ctx = go_context(ctx, goos = nogo_target_info.goos, goarch = nogo_target_info.goarch)
facts = ctx.actions.declare_file(ctx.label.name + ".facts")
raw_findings = ctx.actions.declare_file(ctx.label.name + ".raw_findings")
@@ -120,22 +126,33 @@ def _nogo_stdlib_impl(ctx):
Srcs = [f.path for f in go_ctx.stdlib_srcs],
GOOS = go_ctx.goos,
GOARCH = go_ctx.goarch,
- Tags = go_ctx.tags,
+ Tags = go_ctx.gotags,
)
config_file = ctx.actions.declare_file(ctx.label.name + ".cfg")
ctx.actions.write(config_file, config.to_json())
- ctx.actions.run(
- inputs = [config_file] + go_ctx.stdlib_srcs,
- outputs = [facts, raw_findings],
- tools = depset(go_ctx.runfiles.to_list() + ctx.files._nogo_objdump_tool),
- executable = ctx.files._nogo_check[0],
- mnemonic = "NogoStandardLibraryAnalysis",
- progress_message = "Analyzing Go Standard Library",
- arguments = go_ctx.nogo_args + [
- "-objdump_tool=%s" % ctx.files._nogo_objdump_tool[0].path,
+ args_file = ctx.actions.declare_file(ctx.label.name + "_args_file")
+ ctx.actions.write(
+ output = args_file,
+ content = "\n".join(go_ctx.nogo_args + [
+ "-objdump_tool=%s" % ctx.files._objdump_tool[0].path,
"-stdlib=%s" % config_file.path,
"-findings=%s" % raw_findings.path,
"-facts=%s" % facts.path,
+ ]),
+ )
+ ctx.actions.run(
+ inputs = [config_file] + go_ctx.stdlib_srcs + [args_file],
+ outputs = [facts, raw_findings],
+ tools = depset(go_ctx.runfiles.to_list() + ctx.files._objdump_tool),
+ executable = ctx.files._check[0],
+ mnemonic = "GoStandardLibraryAnalysis",
+ # Note that this does not support work execution currently. There is an
+ # issue with stdout pollution that is not yet resolved, so this is kept
+ # as a separate menomic.
+ progress_message = "Analyzing Go Standard Library",
+ arguments = [
+ "--worker_debug=%s" % nogo_target_info.worker_debug,
+ "@%s" % args_file.path,
],
)
@@ -149,15 +166,15 @@ nogo_stdlib = go_rule(
rule,
implementation = _nogo_stdlib_impl,
attrs = {
- "_nogo_check": attr.label(
+ "_check": attr.label(
default = "//tools/nogo/check:check",
cfg = "host",
),
- "_nogo_objdump_tool": attr.label(
+ "_objdump_tool": attr.label(
default = "//tools/nogo:objdump_tool",
cfg = "host",
),
- "_nogo_target": attr.label(
+ "_target": attr.label(
default = "//tools/nogo:target",
cfg = "target",
),
@@ -174,7 +191,6 @@ NogoInfo = provider(
fields = {
"facts": "serialized package facts",
"raw_findings": "raw package findings (if relevant)",
- "escapes": "escape-only findings (if relevant)",
"importpath": "package import path",
"binaries": "package binary files",
"srcs": "srcs (for go_test support)",
@@ -277,18 +293,17 @@ def _nogo_aspect_impl(target, ctx):
inputs.append(stdlib_facts)
# The nogo tool operates on a configuration serialized in JSON format.
- nogo_target_info = ctx.attr._nogo_target[NogoTargetInfo]
+ nogo_target_info = ctx.attr._target[NogoTargetInfo]
go_ctx = go_context(ctx, goos = nogo_target_info.goos, goarch = nogo_target_info.goarch)
facts = ctx.actions.declare_file(target.label.name + ".facts")
raw_findings = ctx.actions.declare_file(target.label.name + ".raw_findings")
- escapes = ctx.actions.declare_file(target.label.name + ".escapes")
config = struct(
ImportPath = importpath,
GoFiles = [src.path for src in srcs if src.path.endswith(".go")],
NonGoFiles = [src.path for src in srcs if not src.path.endswith(".go")],
GOOS = go_ctx.goos,
GOARCH = go_ctx.goarch,
- Tags = go_ctx.tags,
+ Tags = go_ctx.gotags,
FactMap = fact_map,
ImportMap = import_map,
StdlibFacts = stdlib_facts.path,
@@ -296,20 +311,28 @@ def _nogo_aspect_impl(target, ctx):
config_file = ctx.actions.declare_file(target.label.name + ".cfg")
ctx.actions.write(config_file, config.to_json())
inputs.append(config_file)
- ctx.actions.run(
- inputs = inputs,
- outputs = [facts, raw_findings, escapes],
- tools = depset(go_ctx.runfiles.to_list() + ctx.files._nogo_objdump_tool),
- executable = ctx.files._nogo_check[0],
- mnemonic = "NogoAnalysis",
- progress_message = "Analyzing %s" % target.label,
- arguments = go_ctx.nogo_args + [
+ args_file = ctx.actions.declare_file(ctx.label.name + "_args_file")
+ ctx.actions.write(
+ output = args_file,
+ content = "\n".join(go_ctx.nogo_args + [
"-binary=%s" % target_objfile.path,
- "-objdump_tool=%s" % ctx.files._nogo_objdump_tool[0].path,
+ "-objdump_tool=%s" % ctx.files._objdump_tool[0].path,
"-package=%s" % config_file.path,
"-findings=%s" % raw_findings.path,
"-facts=%s" % facts.path,
- "-escapes=%s" % escapes.path,
+ ]),
+ )
+ ctx.actions.run(
+ inputs = inputs + [args_file],
+ outputs = [facts, raw_findings],
+ tools = depset(go_ctx.runfiles.to_list() + ctx.files._objdump_tool),
+ executable = ctx.files._check[0],
+ mnemonic = "GoStaticAnalysis",
+ progress_message = "Analyzing %s" % target.label,
+ execution_requirements = {"supports-workers": "1"},
+ arguments = [
+ "--worker_debug=%s" % nogo_target_info.worker_debug,
+ "@%s" % args_file.path,
],
)
@@ -322,15 +345,16 @@ def _nogo_aspect_impl(target, ctx):
all_raw_findings = [stdlib_info.raw_findings] + depset(all_raw_findings).to_list() + [raw_findings]
# Return the package facts as output.
- return [NogoInfo(
- facts = facts,
- raw_findings = all_raw_findings,
- escapes = escapes,
- importpath = importpath,
- binaries = binaries,
- srcs = srcs,
- deps = deps,
- )]
+ return [
+ NogoInfo(
+ facts = facts,
+ raw_findings = all_raw_findings,
+ importpath = importpath,
+ binaries = binaries,
+ srcs = srcs,
+ deps = deps,
+ ),
+ ]
nogo_aspect = go_rule(
aspect,
@@ -341,47 +365,60 @@ nogo_aspect = go_rule(
"embed",
],
attrs = {
- "_nogo_check": attr.label(
+ "_check": attr.label(
default = "//tools/nogo/check:check",
cfg = "host",
),
- "_nogo_stdlib": attr.label(
- default = "//tools/nogo:stdlib",
- cfg = "host",
- ),
- "_nogo_objdump_tool": attr.label(
+ "_objdump_tool": attr.label(
default = "//tools/nogo:objdump_tool",
cfg = "host",
),
- "_nogo_target": attr.label(
+ "_target": attr.label(
default = "//tools/nogo:target",
cfg = "target",
),
+ # The name of this attribute must not be _stdlib, since that
+ # appears to be reserved for some internal bazel use.
+ "_nogo_stdlib": attr.label(
+ default = "//tools/nogo:stdlib",
+ cfg = "host",
+ ),
},
)
def _nogo_test_impl(ctx):
"""Check nogo findings."""
+ nogo_target_info = ctx.attr._target[NogoTargetInfo]
# Ensure there's a single dependency.
if len(ctx.attr.deps) != 1:
fail("nogo_test requires exactly one dep.")
raw_findings = ctx.attr.deps[0][NogoInfo].raw_findings
- escapes = ctx.attr.deps[0][NogoInfo].escapes
# Build a step that applies the configuration.
config_srcs = ctx.attr.config[NogoConfigInfo].srcs
findings = ctx.actions.declare_file(ctx.label.name + ".findings")
+ args_file = ctx.actions.declare_file(ctx.label.name + "_args_file")
+ ctx.actions.write(
+ output = args_file,
+ content = "\n".join(
+ ["-input=%s" % f.path for f in raw_findings] +
+ ["-config=%s" % f.path for f in config_srcs] +
+ ["-output=%s" % findings.path],
+ ),
+ )
ctx.actions.run(
- inputs = raw_findings + ctx.files.srcs + config_srcs,
+ inputs = raw_findings + ctx.files.srcs + config_srcs + [args_file],
outputs = [findings],
tools = depset(ctx.files._filter),
executable = ctx.files._filter[0],
mnemonic = "GoStaticAnalysis",
progress_message = "Generating %s" % ctx.label,
- arguments = ["-input=%s" % f.path for f in raw_findings] +
- ["-config=%s" % f.path for f in config_srcs] +
- ["-output=%s" % findings.path],
+ execution_requirements = {"supports-workers": "1"},
+ arguments = [
+ "--worker_debug=%s" % nogo_target_info.worker_debug,
+ "@%s" % args_file.path,
+ ],
)
# Build a runner that checks the filtered facts.
@@ -392,7 +429,7 @@ def _nogo_test_impl(ctx):
runner = ctx.actions.declare_file(ctx.label.name)
runner_content = [
"#!/bin/bash",
- "exec %s -input=%s" % (ctx.files._filter[0].short_path, findings.short_path),
+ "exec %s -check -input=%s" % (ctx.files._filter[0].short_path, findings.short_path),
"",
]
ctx.actions.write(runner, "\n".join(runner_content), is_executable = True)
@@ -409,8 +446,6 @@ def _nogo_test_impl(ctx):
# pays attention to the mnemoic above, so this must be
# what is expected by the tooling.
nogo_findings = depset([findings]),
- # Expose all escape analysis findings (see above).
- nogo_escapes = depset([escapes]),
)]
nogo_test = rule(
@@ -428,7 +463,26 @@ nogo_test = rule(
allow_files = True,
doc = "Relevant src files. This is ignored except to make the nogo_test directly affected by the files.",
),
+ "_target": attr.label(
+ default = "//tools/nogo:target",
+ cfg = "target",
+ ),
"_filter": attr.label(default = "//tools/nogo/filter:filter"),
},
test = True,
)
+
+def _nogo_aspect_tricorder_impl(target, ctx):
+ if ctx.rule.kind != "nogo_test" or OutputGroupInfo not in target:
+ return []
+ if not hasattr(target[OutputGroupInfo], "nogo_findings"):
+ return []
+ return [
+ OutputGroupInfo(tricorder = target[OutputGroupInfo].nogo_findings),
+ ]
+
+# Trivial aspect that forwards the findings from a nogo_test rule to
+# go/tricorder, which reads from the `tricorder` output group.
+nogo_aspect_tricorder = aspect(
+ implementation = _nogo_aspect_tricorder_impl,
+)