From a01ba7c725bcbbb37288c997fc7919fb9b7cb89c Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Fri, 16 Aug 2024 02:52:59 -0400 Subject: [PATCH] Optimize CcInfo computation (#4020) This shows up around 4% of buildbuddy analysis phase image After this change, it goes away. It seems like Bazel is able to make this lazy, which is good since it's only used for building LINKMODE_C_ARCHIVE/LINKMODE_C_SHARED which is fairly rare. **What type of PR is this?** Performance improvement **What does this PR do? Why is it needed?** Avoid computing CcInfo for every intermediate library when it's not needed **Which issues(s) does this PR fix?** Fixes # **Other notes for review** --- docs/go/core/rules.md | 74 ++-- go/private/common.bzl | 6 - go/private/context.bzl | 18 +- go/private/providers.bzl | 2 +- go/private/rules/binary.bzl | 509 +++++++++++++++------------- tests/legacy/cgo_select/BUILD.bazel | 6 + 6 files changed, 312 insertions(+), 303 deletions(-) diff --git a/docs/go/core/rules.md b/docs/go/core/rules.md index c11614e464..10f2414a84 100644 --- a/docs/go/core/rules.md +++ b/docs/go/core/rules.md @@ -130,16 +130,16 @@ go_binary(name, base This builds an executable from a set of source files, - which must all be in the `main` package. You can run the binary with - `bazel run`, or you can build it with `bazel build` and run it directly.

- ***Note:*** `name` should be the same as the desired name of the generated binary.

- **Providers:** - - + which must all be in the `main` package. You can run the binary with + `bazel run`, or you can build it with `bazel build` and run it directly.

+ ***Note:*** `name` should be the same as the desired name of the generated binary.

+ **Providers:** + + ### **Attributes** @@ -147,33 +147,33 @@ This builds an executable from a set of source files, | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | |
name | A unique name for this target. | Name | required | | -| basename | The basename of this binary. The binary basename may also be platform-dependent: on Windows, we add an .exe extension. | String | optional | "" | -| cdeps | The list of other libraries that the c code depends on. This can be anything that would be allowed in [cc_library deps] Only valid if cgo = True. | List of labels | optional | [] | -| cgo | If True, the package may contain [cgo] code, and srcs may contain C, C++, Objective-C, and Objective-C++ files and non-Go assembly files. When cgo is enabled, these files will be compiled with the C/C++ toolchain and included in the package. Note that this attribute does not force cgo to be enabled. Cgo is enabled for non-cross-compiling builds when a C/C++ toolchain is configured. | Boolean | optional | False | -| clinkopts | List of flags to add to the C link command. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. Only valid if cgo = True. | List of strings | optional | [] | -| copts | List of flags to add to the C compilation command. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. Only valid if cgo = True. | List of strings | optional | [] | -| cppopts | List of flags to add to the C/C++ preprocessor command. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. Only valid if cgo = True. | List of strings | optional | [] | -| cxxopts | List of flags to add to the C++ compilation command. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. Only valid if cgo = True. | List of strings | optional | [] | -| data | List of files needed by this rule at run-time. This may include data files needed or other programs that may be executed. The [bazel] package may be used to locate run files; they may appear in different places depending on the operating system and environment. See [data dependencies] for more information on data files. | List of labels | optional | [] | -| deps | List of Go libraries this package imports directly. These may be go_library rules or compatible rules with the [GoLibrary] provider. | List of labels | optional | [] | -| embed | List of Go libraries whose sources should be compiled together with this binary's sources. Labels listed here must name go_library, go_proto_library, or other compatible targets with the [GoLibrary] and [GoSource] providers. Embedded libraries must all have the same importpath, which must match the importpath for this go_binary if one is specified. At most one embedded library may have cgo = True, and the embedding binary may not also have cgo = True. See [Embedding] for more information. | List of labels | optional | [] | -| embedsrcs | The list of files that may be embedded into the compiled package using //go:embed directives. All files must be in the same logical directory or a subdirectory as source files. All source files containing //go:embed directives must be in the same logical directory. It's okay to mix static and generated source files and static and generated embeddable files. | List of labels | optional | [] | -| env | Environment variables to set when the binary is executed with bazel run. The values (but not keys) are subject to [location expansion](https://docs.bazel.build/versions/main/skylark/macros.html) but not full [make variable expansion](https://docs.bazel.build/versions/main/be/make-variables.html). | Dictionary: String -> String | optional | {} | -| gc_goopts | List of flags to add to the Go compilation command when using the gc compiler. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. | List of strings | optional | [] | -| gc_linkopts | List of flags to add to the Go link command when using the gc compiler. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. | List of strings | optional | [] | -| goarch | Forces a binary to be cross-compiled for a specific architecture. It's usually better to control this on the command line with --platforms.

This disables cgo by default, since a cross-compiling C/C++ toolchain is rarely available. To force cgo, set pure = off.

See [Cross compilation] for more information. | String | optional | "auto" | -| goos | Forces a binary to be cross-compiled for a specific operating system. It's usually better to control this on the command line with --platforms.

This disables cgo by default, since a cross-compiling C/C++ toolchain is rarely available. To force cgo, set pure = off.

See [Cross compilation] for more information. | String | optional | "auto" | -| gotags | Enables a list of build tags when evaluating [build constraints]. Useful for conditional compilation. | List of strings | optional | [] | -| importpath | The import path of this binary. Binaries can't actually be imported, but this may be used by [go_path] and other tools to report the location of source files. This may be inferred from embedded libraries. | String | optional | "" | -| linkmode | Determines how the binary should be built and linked. This accepts some of the same values as `go build -buildmode` and works the same way.

| String | optional | "auto" | -| msan | Controls whether code is instrumented for memory sanitization. May be one of on, off, or auto. Not available when cgo is disabled. In most cases, it's better to control this on the command line with --@io_bazel_rules_go//go/config:msan. See [mode attributes], specifically [msan]. | String | optional | "auto" | -| out | Sets the output filename for the generated executable. When set, go_binary will write this file without mode-specific directory prefixes, without linkmode-specific prefixes like "lib", and without platform-specific suffixes like ".exe". Note that without a mode-specific directory prefix, the output file (but not its dependencies) will be invalidated in Bazel's cache when changing configurations. | String | optional | "" | -| pgoprofile | Provides a pprof file to be used for profile guided optimization when compiling go targets. A pprof file can also be provided via --@io_bazel_rules_go//go/config:pgoprofile=<label of a pprof file>. Profile guided optimization is only supported on go 1.20+. See https://go.dev/doc/pgo for more information. | Label | optional | //go/config:empty | -| pure | Controls whether cgo source code and dependencies are compiled and linked, similar to setting CGO_ENABLED. May be one of on, off, or auto. If auto, pure mode is enabled when no C/C++ toolchain is configured or when cross-compiling. It's usually better to control this on the command line with --@io_bazel_rules_go//go/config:pure. See [mode attributes], specifically [pure]. | String | optional | "auto" | -| race | Controls whether code is instrumented for race detection. May be one of on, off, or auto. Not available when cgo is disabled. In most cases, it's better to control this on the command line with --@io_bazel_rules_go//go/config:race. See [mode attributes], specifically [race]. | String | optional | "auto" | -| srcs | The list of Go source files that are compiled to create the package. Only .go, .s, and .syso files are permitted, unless the cgo attribute is set, in which case, .c .cc .cpp .cxx .h .hh .hpp .hxx .inc .m .mm files are also permitted. Files may be filtered at build time using Go [build constraints]. | List of labels | optional | [] | -| static | Controls whether a binary is statically linked. May be one of on, off, or auto. Not available on all platforms or in all modes. It's usually better to control this on the command line with --@io_bazel_rules_go//go/config:static. See [mode attributes], specifically [static]. | String | optional | "auto" | -| x_defs | Map of defines to add to the go link command. See [Defines and stamping] for examples of how to use these. | Dictionary: String -> String | optional | {} | +| basename | The basename of this binary. The binary basename may also be platform-dependent: on Windows, we add an .exe extension. | String | optional | "" | +| cdeps | The list of other libraries that the c code depends on. This can be anything that would be allowed in [cc_library deps] Only valid if cgo = True. | List of labels | optional | [] | +| cgo | If True, the package may contain [cgo] code, and srcs may contain C, C++, Objective-C, and Objective-C++ files and non-Go assembly files. When cgo is enabled, these files will be compiled with the C/C++ toolchain and included in the package. Note that this attribute does not force cgo to be enabled. Cgo is enabled for non-cross-compiling builds when a C/C++ toolchain is configured. | Boolean | optional | False | +| clinkopts | List of flags to add to the C link command. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. Only valid if cgo = True. | List of strings | optional | [] | +| copts | List of flags to add to the C compilation command. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. Only valid if cgo = True. | List of strings | optional | [] | +| cppopts | List of flags to add to the C/C++ preprocessor command. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. Only valid if cgo = True. | List of strings | optional | [] | +| cxxopts | List of flags to add to the C++ compilation command. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. Only valid if cgo = True. | List of strings | optional | [] | +| data | List of files needed by this rule at run-time. This may include data files needed or other programs that may be executed. The [bazel] package may be used to locate run files; they may appear in different places depending on the operating system and environment. See [data dependencies] for more information on data files. | List of labels | optional | [] | +| deps | List of Go libraries this package imports directly. These may be go_library rules or compatible rules with the [GoLibrary] provider. | List of labels | optional | [] | +| embed | List of Go libraries whose sources should be compiled together with this binary's sources. Labels listed here must name go_library, go_proto_library, or other compatible targets with the [GoLibrary] and [GoSource] providers. Embedded libraries must all have the same importpath, which must match the importpath for this go_binary if one is specified. At most one embedded library may have cgo = True, and the embedding binary may not also have cgo = True. See [Embedding] for more information. | List of labels | optional | [] | +| embedsrcs | The list of files that may be embedded into the compiled package using //go:embed directives. All files must be in the same logical directory or a subdirectory as source files. All source files containing //go:embed directives must be in the same logical directory. It's okay to mix static and generated source files and static and generated embeddable files. | List of labels | optional | [] | +| env | Environment variables to set when the binary is executed with bazel run. The values (but not keys) are subject to [location expansion](https://docs.bazel.build/versions/main/skylark/macros.html) but not full [make variable expansion](https://docs.bazel.build/versions/main/be/make-variables.html). | Dictionary: String -> String | optional | {} | +| gc_goopts | List of flags to add to the Go compilation command when using the gc compiler. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. | List of strings | optional | [] | +| gc_linkopts | List of flags to add to the Go link command when using the gc compiler. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. | List of strings | optional | [] | +| goarch | Forces a binary to be cross-compiled for a specific architecture. It's usually better to control this on the command line with --platforms.

This disables cgo by default, since a cross-compiling C/C++ toolchain is rarely available. To force cgo, set pure = off.

See [Cross compilation] for more information. | String | optional | "auto" | +| goos | Forces a binary to be cross-compiled for a specific operating system. It's usually better to control this on the command line with --platforms.

This disables cgo by default, since a cross-compiling C/C++ toolchain is rarely available. To force cgo, set pure = off.

See [Cross compilation] for more information. | String | optional | "auto" | +| gotags | Enables a list of build tags when evaluating [build constraints]. Useful for conditional compilation. | List of strings | optional | [] | +| importpath | The import path of this binary. Binaries can't actually be imported, but this may be used by [go_path] and other tools to report the location of source files. This may be inferred from embedded libraries. | String | optional | "" | +| linkmode | Determines how the binary should be built and linked. This accepts some of the same values as `go build -buildmode` and works the same way.

| String | optional | "auto" | +| msan | Controls whether code is instrumented for memory sanitization. May be one of on, off, or auto. Not available when cgo is disabled. In most cases, it's better to control this on the command line with --@io_bazel_rules_go//go/config:msan. See [mode attributes], specifically [msan]. | String | optional | "auto" | +| out | Sets the output filename for the generated executable. When set, go_binary will write this file without mode-specific directory prefixes, without linkmode-specific prefixes like "lib", and without platform-specific suffixes like ".exe". Note that without a mode-specific directory prefix, the output file (but not its dependencies) will be invalidated in Bazel's cache when changing configurations. | String | optional | "" | +| pgoprofile | Provides a pprof file to be used for profile guided optimization when compiling go targets. A pprof file can also be provided via --@io_bazel_rules_go//go/config:pgoprofile=<label of a pprof file>. Profile guided optimization is only supported on go 1.20+. See https://go.dev/doc/pgo for more information. | Label | optional | //go/config:empty | +| pure | Controls whether cgo source code and dependencies are compiled and linked, similar to setting CGO_ENABLED. May be one of on, off, or auto. If auto, pure mode is enabled when no C/C++ toolchain is configured or when cross-compiling. It's usually better to control this on the command line with --@io_bazel_rules_go//go/config:pure. See [mode attributes], specifically [pure]. | String | optional | "auto" | +| race | Controls whether code is instrumented for race detection. May be one of on, off, or auto. Not available when cgo is disabled. In most cases, it's better to control this on the command line with --@io_bazel_rules_go//go/config:race. See [mode attributes], specifically [race]. | String | optional | "auto" | +| srcs | The list of Go source files that are compiled to create the package. Only .go, .s, and .syso files are permitted, unless the cgo attribute is set, in which case, .c .cc .cpp .cxx .h .hh .hpp .hxx .inc .m .mm files are also permitted. Files may be filtered at build time using Go [build constraints]. | List of labels | optional | [] | +| static | Controls whether a binary is statically linked. May be one of on, off, or auto. Not available on all platforms or in all modes. It's usually better to control this on the command line with --@io_bazel_rules_go//go/config:static. See [mode attributes], specifically [static]. | String | optional | "auto" | +| x_defs | Map of defines to add to the go link command. See [Defines and stamping] for examples of how to use these. | Dictionary: String -> String | optional | {} | diff --git a/go/private/common.bzl b/go/private/common.bzl index a238558654..2d5d016b4f 100644 --- a/go/private/common.bzl +++ b/go/private/common.bzl @@ -172,12 +172,6 @@ def as_tuple(v): return tuple(v.to_list()) fail("as_tuple failed on {}".format(v)) -_STRUCT_TYPE = type(struct()) - -def is_struct(v): - """Returns true if v is a struct.""" - return type(v) == _STRUCT_TYPE - def count_group_matches(v, prefix, suffix): """Counts reluctant substring matches between prefix and suffix. diff --git a/go/private/context.bzl b/go/private/context.bzl index 465f8e81f3..469e3ee234 100644 --- a/go/private/context.bzl +++ b/go/private/context.bzl @@ -49,7 +49,6 @@ load( "COVERAGE_OPTIONS_DENYLIST", "GO_TOOLCHAIN", "as_iterable", - "is_struct", ) load( ":mode.bzl", @@ -282,7 +281,6 @@ def _library_to_source(go, attr, library, coverage_instrumented): "cxxopts": _expand_opts(go, "cxxopts", getattr(attr, "cxxopts", [])), "clinkopts": _expand_opts(go, "clinkopts", getattr(attr, "clinkopts", [])), "cgo_exports": [], - "cc_info": None, "pgoprofile": getattr(attr, "pgoprofile", None), } @@ -310,11 +308,10 @@ def _library_to_source(go, attr, library, coverage_instrumented): # sources. compilepkg will catch these instead. if f.extension in ("c", "cc", "cxx", "cpp", "hh", "hpp", "hxx"): fail("source {} has C/C++ extension, but cgo was not enabled (set 'cgo = True')".format(f.path)) + if library.resolve: library.resolve(go, attr, source, _merge_embed) - source["cc_info"] = _collect_cc_infos(attr_deps + generated_deps, source["cdeps"]) - return GoSource(**source) def _collect_runfiles(go, data, deps): @@ -327,19 +324,6 @@ def _collect_runfiles(go, data, deps): [get_source(t).runfiles for t in deps], ) -def _collect_cc_infos(deps, cdeps): - cc_infos = [] - for dep in cdeps: - if CcInfo in dep: - cc_infos.append(dep[CcInfo]) - for dep in deps: - # dep may be a struct, which doesn't support indexing by providers. - if is_struct(dep): - continue - if GoSource in dep: - cc_infos.append(dep[GoSource].cc_info) - return cc_common.merge_cc_infos(cc_infos = cc_infos) - def _check_binary_dep(go, dep, edge): """Checks that this rule doesn't depend on a go_binary or go_test. diff --git a/go/private/providers.bzl b/go/private/providers.bzl index bf33e4addd..e3becb68f0 100644 --- a/go/private/providers.bzl +++ b/go/private/providers.bzl @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# A represenatation of the inputs to a go package. +# A representation of the inputs to a go package. # This is a configuration independent provider. # You must call resolve with a mode to produce a GoSource. # See go/providers.rst#GoLibrary for full documentation. diff --git a/go/private/rules/binary.bzl b/go/private/rules/binary.bzl index 833a1c40ea..a13351d97c 100644 --- a/go/private/rules/binary.bzl +++ b/go/private/rules/binary.bzl @@ -37,6 +37,7 @@ load( "//go/private:providers.bzl", "GoLibrary", "GoSDK", + "GoSource", ) load( "//go/private/rules:transition.bzl", @@ -94,6 +95,24 @@ def new_cc_import( ), ) +def _go_cc_aspect_impl(target, ctx): + if GoSource not in target: + return [] + + deps = ( + getattr(ctx.rule.attr, "cdeps", []) + + getattr(ctx.rule.attr, "deps", []) + + getattr(ctx.rule.attr, "embed", []) + ) + return [ + cc_common.merge_cc_infos(cc_infos = [dep[CcInfo] for dep in deps]), + ] + +_go_cc_aspect = aspect( + implementation = _go_cc_aspect_impl, + attr_aspects = ["deps", "embed"], +) + def _go_binary_impl(ctx): """go_binary_impl emits actions for compiling and linking a go executable.""" go = go_context(ctx, include_deprecated_properties = False) @@ -179,257 +198,263 @@ def _go_binary_impl(ctx): elif go.mode.link == LINKMODE_C_ARCHIVE: cc_import_kwargs["static_library"] = executable cc_import_kwargs["alwayslink"] = True - ccinfo = new_cc_import(go, **cc_import_kwargs) - ccinfo = cc_common.merge_cc_infos( - cc_infos = [ccinfo, source.cc_info], - ) + + cc_infos = [new_cc_import(go, **cc_import_kwargs)] + cc_infos.extend([dep[CcInfo] for dep in ctx.attr.cdeps + ctx.attr.deps + ctx.attr.embed if CcInfo in dep]) + + ccinfo = cc_common.merge_cc_infos(cc_infos = cc_infos) providers.append(ccinfo) return providers -_go_binary_kwargs = { - "implementation": _go_binary_impl, - "attrs": { - "srcs": attr.label_list( - allow_files = go_exts + asm_exts + cgo_exts + syso_exts, - doc = """The list of Go source files that are compiled to create the package. - Only `.go`, `.s`, and `.syso` files are permitted, unless the `cgo` - attribute is set, in which case, - `.c .cc .cpp .cxx .h .hh .hpp .hxx .inc .m .mm` - files are also permitted. Files may be filtered at build time - using Go [build constraints]. - """, - ), - "data": attr.label_list( - allow_files = True, - doc = """List of files needed by this rule at run-time. This may include data files - needed or other programs that may be executed. The [bazel] package may be - used to locate run files; they may appear in different places depending on the - operating system and environment. See [data dependencies] for more - information on data files. - """, - ), - "deps": attr.label_list( - providers = [GoLibrary], - doc = """List of Go libraries this package imports directly. - These may be `go_library` rules or compatible rules with the [GoLibrary] provider. - """, - cfg = go_transition, - ), - "embed": attr.label_list( - providers = [GoLibrary], - doc = """List of Go libraries whose sources should be compiled together with this - binary's sources. Labels listed here must name `go_library`, - `go_proto_library`, or other compatible targets with the [GoLibrary] and - [GoSource] providers. Embedded libraries must all have the same `importpath`, - which must match the `importpath` for this `go_binary` if one is - specified. At most one embedded library may have `cgo = True`, and the - embedding binary may not also have `cgo = True`. See [Embedding] for - more information. - """, - cfg = go_transition, - ), - "embedsrcs": attr.label_list( - allow_files = True, - doc = """The list of files that may be embedded into the compiled package using - `//go:embed` directives. All files must be in the same logical directory - or a subdirectory as source files. All source files containing `//go:embed` - directives must be in the same logical directory. It's okay to mix static and - generated source files and static and generated embeddable files. - """, - ), - "env": attr.string_dict( - doc = """Environment variables to set when the binary is executed with bazel run. - The values (but not keys) are subject to - [location expansion](https://docs.bazel.build/versions/main/skylark/macros.html) but not full - [make variable expansion](https://docs.bazel.build/versions/main/be/make-variables.html). - """, - ), - "importpath": attr.string( - doc = """The import path of this binary. Binaries can't actually be imported, but this - may be used by [go_path] and other tools to report the location of source - files. This may be inferred from embedded libraries. - """, - ), - "gc_goopts": attr.string_list( - doc = """List of flags to add to the Go compilation command when using the gc compiler. - Subject to ["Make variable"] substitution and [Bourne shell tokenization]. - """, - ), - "gc_linkopts": attr.string_list( - doc = """List of flags to add to the Go link command when using the gc compiler. - Subject to ["Make variable"] substitution and [Bourne shell tokenization]. - """, - ), - "x_defs": attr.string_dict( - doc = """Map of defines to add to the go link command. - See [Defines and stamping] for examples of how to use these. - """, - ), - "basename": attr.string( - doc = """The basename of this binary. The binary - basename may also be platform-dependent: on Windows, we add an .exe extension. - """, - ), - "out": attr.string( - doc = """Sets the output filename for the generated executable. When set, `go_binary` - will write this file without mode-specific directory prefixes, without - linkmode-specific prefixes like "lib", and without platform-specific suffixes - like ".exe". Note that without a mode-specific directory prefix, the - output file (but not its dependencies) will be invalidated in Bazel's cache - when changing configurations. - """, - ), - "cgo": attr.bool( - doc = """If `True`, the package may contain [cgo] code, and `srcs` may contain - C, C++, Objective-C, and Objective-C++ files and non-Go assembly files. - When cgo is enabled, these files will be compiled with the C/C++ toolchain - and included in the package. Note that this attribute does not force cgo - to be enabled. Cgo is enabled for non-cross-compiling builds when a C/C++ - toolchain is configured. - """, - ), - "cdeps": attr.label_list( - doc = """The list of other libraries that the c code depends on. - This can be anything that would be allowed in [cc_library deps] - Only valid if `cgo` = `True`. - """, - ), - "cppopts": attr.string_list( - doc = """List of flags to add to the C/C++ preprocessor command. - Subject to ["Make variable"] substitution and [Bourne shell tokenization]. - Only valid if `cgo` = `True`. - """, - ), - "copts": attr.string_list( - doc = """List of flags to add to the C compilation command. - Subject to ["Make variable"] substitution and [Bourne shell tokenization]. - Only valid if `cgo` = `True`. - """, - ), - "cxxopts": attr.string_list( - doc = """List of flags to add to the C++ compilation command. - Subject to ["Make variable"] substitution and [Bourne shell tokenization]. - Only valid if `cgo` = `True`. - """, - ), - "clinkopts": attr.string_list( - doc = """List of flags to add to the C link command. - Subject to ["Make variable"] substitution and [Bourne shell tokenization]. - Only valid if `cgo` = `True`. - """, - ), - "pure": attr.string( - default = "auto", - doc = """Controls whether cgo source code and dependencies are compiled and linked, - similar to setting `CGO_ENABLED`. May be one of `on`, `off`, - or `auto`. If `auto`, pure mode is enabled when no C/C++ - toolchain is configured or when cross-compiling. It's usually better to - control this on the command line with - `--@io_bazel_rules_go//go/config:pure`. See [mode attributes], specifically - [pure]. - """, - ), - "static": attr.string( - default = "auto", - doc = """Controls whether a binary is statically linked. May be one of `on`, - `off`, or `auto`. Not available on all platforms or in all - modes. It's usually better to control this on the command line with - `--@io_bazel_rules_go//go/config:static`. See [mode attributes], - specifically [static]. - """, - ), - "race": attr.string( - default = "auto", - doc = """Controls whether code is instrumented for race detection. May be one of - `on`, `off`, or `auto`. Not available when cgo is - disabled. In most cases, it's better to control this on the command line with - `--@io_bazel_rules_go//go/config:race`. See [mode attributes], specifically - [race]. - """, - ), - "msan": attr.string( - default = "auto", - doc = """Controls whether code is instrumented for memory sanitization. May be one of - `on`, `off`, or `auto`. Not available when cgo is - disabled. In most cases, it's better to control this on the command line with - `--@io_bazel_rules_go//go/config:msan`. See [mode attributes], specifically - [msan]. - """, - ), - "gotags": attr.string_list( - doc = """Enables a list of build tags when evaluating [build constraints]. Useful for - conditional compilation. - """, - ), - "goos": attr.string( - default = "auto", - doc = """Forces a binary to be cross-compiled for a specific operating system. It's - usually better to control this on the command line with `--platforms`. +def _go_binary_kwargs(go_cc_aspects = []): + return { + "implementation": _go_binary_impl, + "attrs": { + "srcs": attr.label_list( + allow_files = go_exts + asm_exts + cgo_exts + syso_exts, + doc = """The list of Go source files that are compiled to create the package. + Only `.go`, `.s`, and `.syso` files are permitted, unless the `cgo` + attribute is set, in which case, + `.c .cc .cpp .cxx .h .hh .hpp .hxx .inc .m .mm` + files are also permitted. Files may be filtered at build time + using Go [build constraints]. + """, + ), + "data": attr.label_list( + allow_files = True, + doc = """List of files needed by this rule at run-time. This may include data files + needed or other programs that may be executed. The [bazel] package may be + used to locate run files; they may appear in different places depending on the + operating system and environment. See [data dependencies] for more + information on data files. + """, + ), + "deps": attr.label_list( + providers = [GoLibrary], + aspects = go_cc_aspects, + doc = """List of Go libraries this package imports directly. + These may be `go_library` rules or compatible rules with the [GoLibrary] provider. + """, + cfg = go_transition, + ), + "embed": attr.label_list( + providers = [GoLibrary], + aspects = go_cc_aspects, + doc = """List of Go libraries whose sources should be compiled together with this + binary's sources. Labels listed here must name `go_library`, + `go_proto_library`, or other compatible targets with the [GoLibrary] and + [GoSource] providers. Embedded libraries must all have the same `importpath`, + which must match the `importpath` for this `go_binary` if one is + specified. At most one embedded library may have `cgo = True`, and the + embedding binary may not also have `cgo = True`. See [Embedding] for + more information. + """, + cfg = go_transition, + ), + "embedsrcs": attr.label_list( + allow_files = True, + doc = """The list of files that may be embedded into the compiled package using + `//go:embed` directives. All files must be in the same logical directory + or a subdirectory as source files. All source files containing `//go:embed` + directives must be in the same logical directory. It's okay to mix static and + generated source files and static and generated embeddable files. + """, + ), + "env": attr.string_dict( + doc = """Environment variables to set when the binary is executed with bazel run. + The values (but not keys) are subject to + [location expansion](https://docs.bazel.build/versions/main/skylark/macros.html) but not full + [make variable expansion](https://docs.bazel.build/versions/main/be/make-variables.html). + """, + ), + "importpath": attr.string( + doc = """The import path of this binary. Binaries can't actually be imported, but this + may be used by [go_path] and other tools to report the location of source + files. This may be inferred from embedded libraries. + """, + ), + "gc_goopts": attr.string_list( + doc = """List of flags to add to the Go compilation command when using the gc compiler. + Subject to ["Make variable"] substitution and [Bourne shell tokenization]. + """, + ), + "gc_linkopts": attr.string_list( + doc = """List of flags to add to the Go link command when using the gc compiler. + Subject to ["Make variable"] substitution and [Bourne shell tokenization]. + """, + ), + "x_defs": attr.string_dict( + doc = """Map of defines to add to the go link command. + See [Defines and stamping] for examples of how to use these. + """, + ), + "basename": attr.string( + doc = """The basename of this binary. The binary + basename may also be platform-dependent: on Windows, we add an .exe extension. + """, + ), + "out": attr.string( + doc = """Sets the output filename for the generated executable. When set, `go_binary` + will write this file without mode-specific directory prefixes, without + linkmode-specific prefixes like "lib", and without platform-specific suffixes + like ".exe". Note that without a mode-specific directory prefix, the + output file (but not its dependencies) will be invalidated in Bazel's cache + when changing configurations. + """, + ), + "cgo": attr.bool( + doc = """If `True`, the package may contain [cgo] code, and `srcs` may contain + C, C++, Objective-C, and Objective-C++ files and non-Go assembly files. + When cgo is enabled, these files will be compiled with the C/C++ toolchain + and included in the package. Note that this attribute does not force cgo + to be enabled. Cgo is enabled for non-cross-compiling builds when a C/C++ + toolchain is configured. + """, + ), + "cdeps": attr.label_list( + doc = """The list of other libraries that the c code depends on. + This can be anything that would be allowed in [cc_library deps] + Only valid if `cgo` = `True`. + """, + ), + "cppopts": attr.string_list( + doc = """List of flags to add to the C/C++ preprocessor command. + Subject to ["Make variable"] substitution and [Bourne shell tokenization]. + Only valid if `cgo` = `True`. + """, + ), + "copts": attr.string_list( + doc = """List of flags to add to the C compilation command. + Subject to ["Make variable"] substitution and [Bourne shell tokenization]. + Only valid if `cgo` = `True`. + """, + ), + "cxxopts": attr.string_list( + doc = """List of flags to add to the C++ compilation command. + Subject to ["Make variable"] substitution and [Bourne shell tokenization]. + Only valid if `cgo` = `True`. + """, + ), + "clinkopts": attr.string_list( + doc = """List of flags to add to the C link command. + Subject to ["Make variable"] substitution and [Bourne shell tokenization]. + Only valid if `cgo` = `True`. + """, + ), + "pure": attr.string( + default = "auto", + doc = """Controls whether cgo source code and dependencies are compiled and linked, + similar to setting `CGO_ENABLED`. May be one of `on`, `off`, + or `auto`. If `auto`, pure mode is enabled when no C/C++ + toolchain is configured or when cross-compiling. It's usually better to + control this on the command line with + `--@io_bazel_rules_go//go/config:pure`. See [mode attributes], specifically + [pure]. + """, + ), + "static": attr.string( + default = "auto", + doc = """Controls whether a binary is statically linked. May be one of `on`, + `off`, or `auto`. Not available on all platforms or in all + modes. It's usually better to control this on the command line with + `--@io_bazel_rules_go//go/config:static`. See [mode attributes], + specifically [static]. + """, + ), + "race": attr.string( + default = "auto", + doc = """Controls whether code is instrumented for race detection. May be one of + `on`, `off`, or `auto`. Not available when cgo is + disabled. In most cases, it's better to control this on the command line with + `--@io_bazel_rules_go//go/config:race`. See [mode attributes], specifically + [race]. + """, + ), + "msan": attr.string( + default = "auto", + doc = """Controls whether code is instrumented for memory sanitization. May be one of + `on`, `off`, or `auto`. Not available when cgo is + disabled. In most cases, it's better to control this on the command line with + `--@io_bazel_rules_go//go/config:msan`. See [mode attributes], specifically + [msan]. + """, + ), + "gotags": attr.string_list( + doc = """Enables a list of build tags when evaluating [build constraints]. Useful for + conditional compilation. + """, + ), + "goos": attr.string( + default = "auto", + doc = """Forces a binary to be cross-compiled for a specific operating system. It's + usually better to control this on the command line with `--platforms`. - This disables cgo by default, since a cross-compiling C/C++ toolchain is - rarely available. To force cgo, set `pure` = `off`. + This disables cgo by default, since a cross-compiling C/C++ toolchain is + rarely available. To force cgo, set `pure` = `off`. - See [Cross compilation] for more information. - """, - ), - "goarch": attr.string( - default = "auto", - doc = """Forces a binary to be cross-compiled for a specific architecture. It's usually - better to control this on the command line with `--platforms`. + See [Cross compilation] for more information. + """, + ), + "goarch": attr.string( + default = "auto", + doc = """Forces a binary to be cross-compiled for a specific architecture. It's usually + better to control this on the command line with `--platforms`. - This disables cgo by default, since a cross-compiling C/C++ toolchain is - rarely available. To force cgo, set `pure` = `off`. + This disables cgo by default, since a cross-compiling C/C++ toolchain is + rarely available. To force cgo, set `pure` = `off`. - See [Cross compilation] for more information. - """, - ), - "linkmode": attr.string( - default = "auto", - values = ["auto"] + LINKMODES, - doc = """Determines how the binary should be built and linked. This accepts some of - the same values as `go build -buildmode` and works the same way. -

- - """, - ), - "pgoprofile": attr.label( - allow_files = True, - doc = """Provides a pprof file to be used for profile guided optimization when compiling go targets. - A pprof file can also be provided via `--@io_bazel_rules_go//go/config:pgoprofile=