From c03a5f01fc5831fed370269ca7ddf316d4eacaff Mon Sep 17 00:00:00 2001 From: maleo Date: Fri, 16 May 2025 08:25:48 +0000 Subject: [PATCH 1/2] Always write the binary to the mode specific directory and create a symlink if "out" is specified. This reduces cache invalidation on mode changes. --- docs/go/core/rules.md | 4 ++-- go/private/rules/binary.bzl | 31 +++++++++++++++++-------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/docs/go/core/rules.md b/docs/go/core/rules.md index f084cc81d0..06c58099bd 100644 --- a/docs/go/core/rules.md +++ b/docs/go/core/rules.md @@ -144,7 +144,7 @@ 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 | "" | +| basename | The basename of this binary. The binary basename may also be platform-dependent: on Windows, we add an .exe extension. When not set, it will default to the label name. | 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 | [] | @@ -164,7 +164,7 @@ This builds an executable from a set of source files, | 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 | "" | +| out | Sets the output symlink filename for the generated executable. | 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" | diff --git a/go/private/rules/binary.bzl b/go/private/rules/binary.bzl index 064831bbe8..f175dd1b5e 100644 --- a/go/private/rules/binary.bzl +++ b/go/private/rules/binary.bzl @@ -136,24 +136,31 @@ def _go_binary_impl(ctx): name = ctx.attr.basename if not name: name = ctx.label.name - executable = None - if ctx.attr.out: - # Use declare_file instead of attr.output(). When users set output files - # directly, Bazel warns them not to use the same name as the rule, which is - # the common case with go_binary. - executable = ctx.actions.declare_file(ctx.attr.out) - archive, executable, runfiles = go.binary( + archive, executable_binary, runfiles = go.binary( go, name = name, source = go_info, gc_linkopts = gc_linkopts(ctx), version_file = ctx.version_file, info_file = ctx.info_file, - executable = executable, + executable = None, ) validation_output = archive.data._validation_output nogo_diagnostics = archive.data._nogo_diagnostics + if ctx.attr.out: + # Use declare_file instead of attr.output(). When users set output files + # directly, Bazel warns them not to use the same name as the rule, which is + # the common case with go_binary. + executable = ctx.actions.declare_file(ctx.attr.out) + ctx.actions.symlink( + output = executable, + target_file = executable_binary, + is_executable = True, + ) + else: + executable = executable_binary + providers = [ archive, OutputGroupInfo( @@ -305,15 +312,11 @@ def _go_binary_kwargs(go_cc_aspects = []): "basename": attr.string( doc = """The basename of this binary. The binary basename may also be platform-dependent: on Windows, we add an .exe extension. + When not set, it will default to the label name. """, ), "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. + doc = """Sets the output symlink filename for the generated executable. """, ), "cgo": attr.bool( From 3295db9c020d2221cab208e1ec5eb1f66b5fd860 Mon Sep 17 00:00:00 2001 From: maleo Date: Fri, 16 May 2025 09:33:59 +0000 Subject: [PATCH 2/2] Add attribute to infer output name from basename This reduces duplication. --- docs/go/core/rules.md | 5 +++-- go/private/rules/binary.bzl | 22 ++++++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/docs/go/core/rules.md b/docs/go/core/rules.md index 06c58099bd..15b360f92e 100644 --- a/docs/go/core/rules.md +++ b/docs/go/core/rules.md @@ -125,7 +125,7 @@ Rules
 go_binary(name, basename, cdeps, cgo, clinkopts, copts, cppopts, cxxopts, data, deps, embed,
           embedsrcs, env, gc_goopts, gc_linkopts, goarch, goos, gotags, importpath, linkmode, msan,
-          out, pgoprofile, pure, race, srcs, static, x_defs)
+          out, out_auto, pgoprofile, pure, race, srcs, static, x_defs)
 
This builds an executable from a set of source files, @@ -164,7 +164,8 @@ This builds an executable from a set of source files, | 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 symlink filename for the generated executable. | String | optional | "" | +| out | Create a symlink with this name for the generated executable. | String | optional | "" | +| out_auto | Create a symlink with a name inferred from basename for the generated executable. | Boolean | optional | False | | 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" | diff --git a/go/private/rules/binary.bzl b/go/private/rules/binary.bzl index f175dd1b5e..060b06f695 100644 --- a/go/private/rules/binary.bzl +++ b/go/private/rules/binary.bzl @@ -115,6 +115,9 @@ _go_cc_aspect = aspect( def _go_binary_impl(ctx): """go_binary_impl emits actions for compiling and linking a go executable.""" + if ctx.attr.out and ctx.attr.out_auto: + fail("Only one of out and out_auto must be set.") + go = go_context( ctx, include_deprecated_properties = False, @@ -148,11 +151,14 @@ def _go_binary_impl(ctx): validation_output = archive.data._validation_output nogo_diagnostics = archive.data._nogo_diagnostics - if ctx.attr.out: - # Use declare_file instead of attr.output(). When users set output files - # directly, Bazel warns them not to use the same name as the rule, which is - # the common case with go_binary. - executable = ctx.actions.declare_file(ctx.attr.out) + if ctx.attr.out or ctx.attr.out_auto: + if ctx.attr.out: + # Use declare_file instead of attr.output(). When users set output files + # directly, Bazel warns them not to use the same name as the rule, which is + # the common case with go_binary. + executable = ctx.actions.declare_file(ctx.attr.out) + else: + executable = ctx.actions.declare_file(name) ctx.actions.symlink( output = executable, target_file = executable_binary, @@ -316,7 +322,11 @@ def _go_binary_kwargs(go_cc_aspects = []): """, ), "out": attr.string( - doc = """Sets the output symlink filename for the generated executable. + doc = """Create a symlink with this name for the generated executable. + """, + ), + "out_auto": attr.bool( + doc = """Create a symlink with a name inferred from basename for the generated executable. """, ), "cgo": attr.bool(