Skip to content

Commit

Permalink
Fix //go/config:linkmode flag value not being effective (#3627)
Browse files Browse the repository at this point in the history
The value of the flag was always overriden by the `linkmode` `go_binary`
attribute, even if that attribute was at its default (`normal`) value.
Instead, use a default of `auto` to distinguish this case from the case
where no attribute value has been set explicitly.

Fixes #3614
Closes #3615
  • Loading branch information
fmeum committed Jul 18, 2023
1 parent 2626ff9 commit 61c1e91
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 3 deletions.
2 changes: 1 addition & 1 deletion docs/go/core/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ This builds an executable from a set of source files,
| <a id="go_binary-goos"></a>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 <code>--platforms</code>.<br><br> This disables cgo by default, since a cross-compiling C/C++ toolchain is rarely available. To force cgo, set <code>pure</code> = <code>off</code>.<br><br> See [Cross compilation] for more information. | String | optional | "auto" |
| <a id="go_binary-gotags"></a>gotags | Enables a list of build tags when evaluating [build constraints]. Useful for conditional compilation. | List of strings | optional | [] |
| <a id="go_binary-importpath"></a>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 | "" |
| <a id="go_binary-linkmode"></a>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. <br><br> <ul> <li>`normal`: Builds a normal executable with position-dependent code.</li> <li>`pie`: Builds a position-independent executable.</li> <li>`plugin`: Builds a shared library that can be loaded as a Go plugin. Only supported on platforms that support plugins.</li> <li>`c-shared`: Builds a shared library that can be linked into a C program.</li> <li>`c-archive`: Builds an archive that can be linked into a C program.</li> </ul> | String | optional | "normal" |
| <a id="go_binary-linkmode"></a>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. <br><br> <ul> <li>`auto` (default): Controlled by `//go/config:linkmode`, which defaults to `normal`.</li> <li>`normal`: Builds a normal executable with position-dependent code.</li> <li>`pie`: Builds a position-independent executable.</li> <li>`plugin`: Builds a shared library that can be loaded as a Go plugin. Only supported on platforms that support plugins.</li> <li>`c-shared`: Builds a shared library that can be linked into a C program.</li> <li>`c-archive`: Builds an archive that can be linked into a C program.</li> </ul> | String | optional | "auto" |
| <a id="go_binary-msan"></a>msan | Controls whether code is instrumented for memory sanitization. May be one of <code>on</code>, <code>off</code>, or <code>auto</code>. Not available when cgo is disabled. In most cases, it's better to control this on the command line with <code>--@io_bazel_rules_go//go/config:msan</code>. See [mode attributes], specifically [msan]. | String | optional | "auto" |
| <a id="go_binary-out"></a>out | Sets the output filename for the generated executable. When set, <code>go_binary</code> 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 | "" |
| <a id="go_binary-pure"></a>pure | Controls whether cgo source code and dependencies are compiled and linked, similar to setting <code>CGO_ENABLED</code>. May be one of <code>on</code>, <code>off</code>, or <code>auto</code>. If <code>auto</code>, 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 <code>--@io_bazel_rules_go//go/config:pure</code>. See [mode attributes], specifically [pure]. | String | optional | "auto" |
Expand Down
6 changes: 4 additions & 2 deletions go/private/rules/binary.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ load(
)
load(
"//go/private:mode.bzl",
"LINKMODES",
"LINKMODES_EXECUTABLE",
"LINKMODE_C_ARCHIVE",
"LINKMODE_C_SHARED",
"LINKMODE_NORMAL",
"LINKMODE_PLUGIN",
"LINKMODE_SHARED",
)
Expand Down Expand Up @@ -385,11 +385,13 @@ _go_binary_kwargs = {
""",
),
"linkmode": attr.string(
default = LINKMODE_NORMAL,
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.
<br><br>
<ul>
<li>`auto` (default): Controlled by `//go/config:linkmode`, which defaults to `normal`.</li>
<li>`normal`: Builds a normal executable with position-dependent code.</li>
<li>`pie`: Builds a position-independent executable.</li>
<li>`plugin`: Builds a shared library that can be loaded as a Go plugin. Only supported on platforms that support plugins.</li>
Expand Down
9 changes: 9 additions & 0 deletions tests/core/go_binary/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
load("@io_bazel_rules_go//go/tools/bazel_testing:def.bzl", "go_bazel_test")
load(":many_deps.bzl", "many_deps")
load(":linkmode.bzl", "linkmode_pie_wrapper")

test_suite(name = "go_binary")

Expand Down Expand Up @@ -101,6 +102,12 @@ go_binary(
tags = ["manual"],
)

linkmode_pie_wrapper(
name = "hello_pie_setting_bin",
tags = ["manual"],
target = ":hello_nopie_bin",
)

go_test(
name = "pie_test",
srcs = [
Expand All @@ -112,10 +119,12 @@ go_test(
"@io_bazel_rules_go//go/platform:darwin": [
":hello_nopie_bin",
":hello_pie_bin",
":hello_pie_setting_bin",
],
"@io_bazel_rules_go//go/platform:linux": [
":hello_nopie_bin",
":hello_pie_bin",
":hello_pie_setting_bin",
],
"//conditions:default": [],
}),
Expand Down
35 changes: 35 additions & 0 deletions tests/core/go_binary/linkmode.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
_LINKMODE_SETTING = "//go/config:linkmode"

def _linkmode_pie_transition_impl(settings, attr):
return {
_LINKMODE_SETTING: "pie",
}

_linkmode_pie_transition = transition(
implementation = _linkmode_pie_transition_impl,
inputs = [_LINKMODE_SETTING],
outputs = [_LINKMODE_SETTING],
)

def _linkmode_pie_wrapper(ctx):
in_binary = ctx.attr.target[0][DefaultInfo].files.to_list()[0]
out_binary = ctx.actions.declare_file(ctx.attr.name)
ctx.actions.symlink(output = out_binary, target_file = in_binary)
return [
DefaultInfo(
files = depset([out_binary]),
),
]

linkmode_pie_wrapper = rule(
implementation = _linkmode_pie_wrapper,
doc = """Provides the (only) file produced by target, but after transitioning the linkmode setting to PIE.""",
attrs = {
"target": attr.label(
cfg = _linkmode_pie_transition,
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
)
12 changes: 12 additions & 0 deletions tests/core/go_binary/pie_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ func openELF(dir, bin string) (*elf.File, error) {
return elf.NewFile(f)
}

func TestPIESetting(t *testing.T) {
e, err := openELF("tests/core/go_binary", "hello_pie_setting_bin")
if err != nil {
t.Fatal(err)
}

// PIE binaries are implemented as shared libraries.
if e.Type != elf.ET_DYN {
t.Error("ELF binary is not position-independent.")
}
}

func TestPIE(t *testing.T) {
e, err := openELF("tests/core/go_binary", "hello_pie_bin")
if err != nil {
Expand Down

0 comments on commit 61c1e91

Please sign in to comment.