Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix //go/config:linkmode flag value not being effective #3627

Merged
merged 1 commit into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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