Skip to content

Commit

Permalink
Merge branch 'master' into zbarsky/libmerge
Browse files Browse the repository at this point in the history
  • Loading branch information
dzbarsky authored Aug 29, 2024
2 parents aea63e3 + 6f5f6f3 commit d10b887
Show file tree
Hide file tree
Showing 17 changed files with 303 additions and 181 deletions.
3 changes: 3 additions & 0 deletions docs/go/core/rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
[go_path]: #go_path
[go_source]: #go_source
[go_test]: #go_test
[go_reset_target]: #go_reset_target
[Examples]: examples.md#examples
[Defines and stamping]: defines_and_stamping.md#defines-and-stamping
[Stamping with the workspace status script]: defines_and_stamping.md#stamping-with-the-workspace-status-script
Expand Down Expand Up @@ -117,6 +118,7 @@ load("//go/private/rules:cross.bzl", _go_cross_binary = "go_cross_binary")
load("//go/private/rules:library.bzl", _go_library = "go_library")
load("//go/private/rules:source.bzl", _go_source = "go_source")
load("//go/private/rules:test.bzl", _go_test = "go_test")
load("//go/private/rules:transition.bzl", _go_reset_target = "go_reset_target")
load("//go/private/tools:path.bzl", _go_path = "go_path")

go_library = _go_library
Expand All @@ -125,3 +127,4 @@ go_test = _go_test
go_source = _go_source
go_path = _go_path
go_cross_binary = _go_cross_binary
go_reset_target = _go_reset_target
37 changes: 37 additions & 0 deletions docs/go/core/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
[go_path]: #go_path
[go_source]: #go_source
[go_test]: #go_test
[go_reset_target]: #go_reset_target
[Examples]: examples.md#examples
[Defines and stamping]: defines_and_stamping.md#defines-and-stamping
[Stamping with the workspace status script]: defines_and_stamping.md#stamping-with-the-workspace-status-script
Expand Down Expand Up @@ -286,6 +287,42 @@ go_path(<a href="#go_path-name">name</a>, <a href="#go_path-data">data</a>, <a h



<a id="#go_reset_target"></a>

## go_reset_target

<pre>
go_reset_target(<a href="#go_reset_target-name">name</a>, <a href="#go_reset_target-dep">dep</a>)
</pre>

Forwards providers from a target and default Go binary settings.

go_reset_target depends on a single target and builds it to be a Go tool binary. It
forwards Go providers and DefaultInfo.

go_reset_target does two things using transitions:
1. builds the tool with 'cfg = "exec"' so they work on the execution platform.
2. Sets most Go settings to default value and disables nogo.

This is used for Go tool binaries that shouldn't depend on the link mode or tags of the
target configuration and neither the tools nor the code they potentially
generate should be subject to Nogo's static analysis. This is helpful, for example, so
a tool isn't built as a shared library with race instrumentation. This acts as an
intermediate rule that allows users to apply these transitions.


### **Attributes**


| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="go_reset_target-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="go_reset_target-dep"></a>dep | The target to forward providers from and apply go_tool_transition to. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |





<a id="#go_source"></a>

## go_source
Expand Down
4 changes: 2 additions & 2 deletions docs/go/extras/extras.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ This rule has moved. See [gazelle rule] in the Gazelle repository.

<pre>
gomock(<a href="#gomock-name">name</a>, <a href="#gomock-out">out</a>, <a href="#gomock-library">library</a>, <a href="#gomock-source_importpath">source_importpath</a>, <a href="#gomock-source">source</a>, <a href="#gomock-interfaces">interfaces</a>, <a href="#gomock-package">package</a>, <a href="#gomock-self_package">self_package</a>, <a href="#gomock-aux_files">aux_files</a>,
<a href="#gomock-mockgen_tool">mockgen_tool</a>, <a href="#gomock-imports">imports</a>, <a href="#gomock-copyright_file">copyright_file</a>, <a href="#gomock-mock_names">mock_names</a>, <a href="#gomock-typed">typed</a>, <a href="#gomock-kwargs">kwargs</a>)
<a href="#gomock-mockgen_tool">mockgen_tool</a>, <a href="#gomock-mockgen_args">mockgen_args</a>, <a href="#gomock-imports">imports</a>, <a href="#gomock-copyright_file">copyright_file</a>, <a href="#gomock-mock_names">mock_names</a>, <a href="#gomock-kwargs">kwargs</a>)
</pre>

Calls [mockgen](https://github.com/golang/mock) to generates a Go file containing mocks from the given library.
Expand All @@ -57,10 +57,10 @@ If `source` is given, the mocks are generated in source mode; otherwise in refle
| <a id="gomock-self_package"></a>self_package | the full package import path for the generated code. The purpose of this flag is to prevent import cycles in the generated code by trying to include its own package. See [mockgen's -self_package](https://github.com/golang/mock#flags) for more information. | <code>""</code> |
| <a id="gomock-aux_files"></a>aux_files | a map from source files to their package path. This only needed when <code>source</code> is provided. See [mockgen's -aux_files](https://github.com/golang/mock#flags) for more information. | <code>{}</code> |
| <a id="gomock-mockgen_tool"></a>mockgen_tool | the mockgen tool to run. | <code>Label("//extras/gomock:mockgen")</code> |
| <a id="gomock-mockgen_args"></a>mockgen_args | additional arguments to pass to the mockgen tool. | <code>[]</code> |
| <a id="gomock-imports"></a>imports | dictionary of name-path pairs of explicit imports to use. See [mockgen's -imports](https://github.com/golang/mock#flags) for more information. | <code>{}</code> |
| <a id="gomock-copyright_file"></a>copyright_file | optional file containing copyright to prepend to the generated contents. See [mockgen's -copyright_file](https://github.com/golang/mock#flags) for more information. | <code>None</code> |
| <a id="gomock-mock_names"></a>mock_names | dictionary of interface name to mock name pairs to change the output names of the mock objects. Mock names default to 'Mock' prepended to the name of the interface. See [mockgen's -mock_names](https://github.com/golang/mock#flags) for more information. | <code>{}</code> |
| <a id="gomock-typed"></a>typed | generate type-safe 'Return', 'Do', 'DoAndReturn' functions. See [mockgen's -typed](https://github.com/uber-go/mock#flags) for more information. | <code>False</code> |
| <a id="gomock-kwargs"></a>kwargs | <p align="center"> - </p> | none |


31 changes: 16 additions & 15 deletions extras/gomock.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,6 @@ _gomock_source = rule(
allow_single_file = True,
mandatory = False,
),
"typed": attr.bool(
doc = "Generate type-safe 'Return', 'Do', 'DoAndReturn' functions.",
mandatory = False,
),
"mockgen_tool": attr.label(
doc = "The mockgen tool to run",
default = _MOCKGEN_TOOL,
Expand All @@ -164,14 +160,18 @@ _gomock_source = rule(
cfg = "exec",
mandatory = False,
),
"mockgen_args": attr.string_list(
doc = "Additional arguments to pass to the mockgen tool",
mandatory = False,
),
"_go_context_data": attr.label(
default = "//:go_context_data",
),
},
toolchains = [GO_TOOLCHAIN],
)

def gomock(name, out, library = None, source_importpath = "", source = None, interfaces = [], package = "", self_package = "", aux_files = {}, mockgen_tool = _MOCKGEN_TOOL, imports = {}, copyright_file = None, mock_names = {}, typed = False, **kwargs):
def gomock(name, out, library = None, source_importpath = "", source = None, interfaces = [], package = "", self_package = "", aux_files = {}, mockgen_tool = _MOCKGEN_TOOL, mockgen_args = [], imports = {}, copyright_file = None, mock_names = {}, **kwargs):
"""Calls [mockgen](https://github.com/golang/mock) to generates a Go file containing mocks from the given library.
If `source` is given, the mocks are generated in source mode; otherwise in reflective mode.
Expand All @@ -187,11 +187,11 @@ def gomock(name, out, library = None, source_importpath = "", source = None, int
self_package: the full package import path for the generated code. The purpose of this flag is to prevent import cycles in the generated code by trying to include its own package. See [mockgen's -self_package](https://github.com/golang/mock#flags) for more information.
aux_files: a map from source files to their package path. This only needed when `source` is provided. See [mockgen's -aux_files](https://github.com/golang/mock#flags) for more information.
mockgen_tool: the mockgen tool to run.
mockgen_args: additional arguments to pass to the mockgen tool.
imports: dictionary of name-path pairs of explicit imports to use. See [mockgen's -imports](https://github.com/golang/mock#flags) for more information.
copyright_file: optional file containing copyright to prepend to the generated contents. See [mockgen's -copyright_file](https://github.com/golang/mock#flags) for more information.
mock_names: dictionary of interface name to mock name pairs to change the output names of the mock objects. Mock names default to 'Mock' prepended to the name of the interface. See [mockgen's -mock_names](https://github.com/golang/mock#flags) for more information.
typed: generate type-safe 'Return', 'Do', 'DoAndReturn' functions. See [mockgen's -typed](https://github.com/uber-go/mock#flags) for more information.
kwargs: [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) to all Bazel rules.
kwargs: common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) to all Bazel rules.
"""
if source:
_gomock_source(
Expand All @@ -204,10 +204,10 @@ def gomock(name, out, library = None, source_importpath = "", source = None, int
self_package = self_package,
aux_files = aux_files,
mockgen_tool = mockgen_tool,
mockgen_args = mockgen_args,
imports = imports,
copyright_file = copyright_file,
mock_names = mock_names,
typed = typed,
**kwargs
)
else:
Expand All @@ -219,10 +219,10 @@ def gomock(name, out, library = None, source_importpath = "", source = None, int
package = package,
self_package = self_package,
mockgen_tool = mockgen_tool,
mockgen_args = mockgen_args,
imports = imports,
copyright_file = copyright_file,
mock_names = mock_names,
typed = typed,
**kwargs
)

Expand Down Expand Up @@ -367,10 +367,6 @@ _gomock_prog_exec = rule(
allow_single_file = True,
mandatory = False,
),
"typed": attr.bool(
doc = "Generate type-safe 'Return', 'Do', 'DoAndReturn' functions.",
mandatory = False,
),
"prog_bin": attr.label(
doc = "The program binary generated by mockgen's -prog_only and compiled by bazel.",
allow_single_file = True,
Expand All @@ -386,6 +382,11 @@ _gomock_prog_exec = rule(
cfg = "exec",
mandatory = False,
),
"mockgen_args": attr.string_list(
doc = "Additional arguments to pass to the mockgen tool",
mandatory = False,
default = [],
),
"_go_context_data": attr.label(
default = "//:go_context_data",
),
Expand All @@ -409,7 +410,7 @@ def _handle_shared_args(ctx, args):
if len(ctx.attr.mock_names) > 0:
mock_names = ",".join(["{0}={1}".format(name, pkg) for name, pkg in ctx.attr.mock_names.items()])
args += ["-mock_names", mock_names]
if ctx.attr.typed:
args += ["-typed"]
if ctx.attr.mockgen_args:
args += ctx.attr.mockgen_args

return args, needed_files
7 changes: 7 additions & 0 deletions go/def.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ load(
"//go/private/rules:source.bzl",
_go_source = "go_source",
)
load(
"//go/private/rules:transition.bzl",
_go_reset_target = "go_reset_target",
)
load(
"//go/private/rules:wrappers.bzl",
_go_binary_macro = "go_binary_macro",
Expand Down Expand Up @@ -171,6 +175,9 @@ go_source = _go_source
# See docs/go/core/rules.md#go_path for full documentation.
go_path = _go_path

# See docs/go/core/rules.md#go_reset_target for full documentation.
go_reset_target = _go_reset_target

# See docs/go/core/rules.md#go_cross_binary for full documentation.
go_cross_binary = _go_cross_binary

Expand Down
9 changes: 2 additions & 7 deletions go/nogo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,9 @@
.. footer:: The ``nogo`` logo was derived from the Go gopher, which was designed by Renee French. (http://reneefrench.blogspot.com/) The design is licensed under the Creative Commons 3.0 Attributions license. Read this article for more details: http://blog.golang.org/gopher


**WARNING**: This functionality is experimental, so its API might change.
Please do not rely on it for production use, but feel free to use it and file
issues.

``nogo`` is a tool that analyzes the source code of Go programs. It runs
alongside the Go compiler in the Bazel Go rules and rejects programs that
contain disallowed coding patterns. In addition, ``nogo`` may report
compiler-like errors.
in an action after the Go compiler in the Bazel Go rules and rejects sources that
contain disallowed coding patterns from the configured analyzers.

``nogo`` is a powerful tool for preventing bugs and code anti-patterns early
in the development process. It may be used to run the same analyses as `vet`_,
Expand Down
21 changes: 13 additions & 8 deletions go/private/actions/compilepkg.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def _embedroot_arg(src):
def _embedlookupdir_arg(src):
root_relative = src.dirname[len(src.root.path):]
if root_relative.startswith("/"):
root_relative = root_relative[len("/"):]
root_relative = root_relative[1:]
return root_relative

def emit_compilepkg(
Expand Down Expand Up @@ -88,6 +88,9 @@ def emit_compilepkg(
if bool(nogo) != bool(out_nogo_validation):
fail("nogo must be specified if and only if out_nogo_validation is specified")

if cover and go.coverdata:
archives = archives + [go.coverdata]

sdk = go.sdk
inputs_direct = (sources + embedsrcs + [sdk.package_list] +
[archive.data.export_file for archive in archives])
Expand All @@ -111,19 +114,17 @@ def emit_compilepkg(
uniquify = True,
expand_directories = False,
)

cover_mode = None
cover_archive = None
if cover and go.coverdata:
cover_archive = go.coverdata
inputs_direct.append(cover_archive.data.export_file)
args.add("-arc", _archive(cover_archive))
if go.mode.race:
cover_mode = "atomic"
else:
cover_mode = "set"
args.add("-cover_mode", cover_mode)
args.add("-cover_format", go.mode.cover_format)
args.add_all(cover, before_each = "-cover")

args.add_all(archives, before_each = "-arc", map_each = _archive)
if recompile_internal_deps:
args.add_all(recompile_internal_deps, before_each = "-recompile_internal_deps")
Expand Down Expand Up @@ -210,12 +211,13 @@ def emit_compilepkg(
_run_nogo(
go,
sources = sources,
cgo_go_srcs = cgo_go_srcs_for_nogo,
importpath = importpath,
importmap = importmap,
archives = archives + ([cover_archive] if cover_archive else []),
archives = archives,
recompile_internal_deps = recompile_internal_deps,
cover_mode = cover_mode,
cgo_go_srcs = cgo_go_srcs_for_nogo,
testfilter = testfilter,
out_facts = out_facts,
out_log = out_nogo_log,
out_validation = out_nogo_validation,
Expand All @@ -226,12 +228,13 @@ def _run_nogo(
go,
*,
sources,
cgo_go_srcs,
importpath,
importmap,
archives,
recompile_internal_deps,
cover_mode,
cgo_go_srcs,
testfilter,
out_facts,
out_log,
out_validation,
Expand Down Expand Up @@ -262,6 +265,8 @@ def _run_nogo(
if importmap:
args.add("-p", importmap)
args.add("-package_list", sdk.package_list)
if testfilter:
args.add("-testfilter", testfilter)

args.add_all(archives, before_each = "-facts", map_each = _facts)
args.add("-out_facts", out_facts)
Expand Down
12 changes: 5 additions & 7 deletions go/private/context.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -359,16 +359,14 @@ def new_go_info(

# TODO(zbarsky): Remove this once downstream has a chance to migrate.
if verify_resolver_deps:
has_targets = False
for dep in go_info["deps"]:
if type(dep) == "Target":
has_targets = True
print('Detected Targets in `source["deps"]` as a result of _resolver: ' +
"{}, from target {}. ".format(library.resolve, str(library.label)) +
"Please pass a list of `GoArchive`s instead, for examples `deps = [deps[GoArchive] for dep in deps]`. " +
"This will be an error in the future.")
go_info["deps"] = [get_archive(dep) for dep in go_info["deps"]]
break
if has_targets:
print('Detected Targets in `source["deps"]` as a result of _resolver. ' +
"Please pass a list of `GoArchive`s instead, for examples `deps = [deps[GoArchive] for dep in deps]`. " +
"This will be an error in the future.")
go_info["deps"] = [get_archive(dep) for dep in go_info["deps"]]

return GoInfo(**go_info)

Expand Down
19 changes: 12 additions & 7 deletions go/private/rules/transition.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -317,21 +317,26 @@ go_reset_target = rule(
"dep": attr.label(
mandatory = True,
cfg = go_tool_transition,
doc = """The target to forward providers from and apply go_tool_transition to.""",
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
doc = """Forwards providers from a target and applies go_tool_transition.
doc = """Forwards providers from a target and default Go binary settings.
go_reset_target depends on a single target, built using go_tool_transition. It
go_reset_target depends on a single target and builds it to be a Go tool binary. It
forwards Go providers and DefaultInfo.
This is used to work around a problem with building tools: Go tools should be
built with 'cfg = "exec"' so they work on the execution platform, but we also
need to apply go_tool_transition so that e.g. a tool isn't built as a shared
library with race instrumentation. This acts as an intermediate rule that allows
to apply both both transitions.
go_reset_target does two things using transitions:
1. builds the tool with 'cfg = "exec"' so they work on the execution platform.
2. Sets most Go settings to default value and disables nogo.
This is used for Go tool binaries that shouldn't depend on the link mode or tags of the
target configuration and neither the tools nor the code they potentially
generate should be subject to Nogo's static analysis. This is helpful, for example, so
a tool isn't built as a shared library with race instrumentation. This acts as an
intermediate rule that allows users to apply these transitions.
""",
)

Expand Down
Loading

0 comments on commit d10b887

Please sign in to comment.