Skip to content

Commit

Permalink
Don't include non-executable go_binary in dependent's runfiles
Browse files Browse the repository at this point in the history
If a go_binary is built with a non-executable link mode such as
`c-archive`, its dependents currently pick up a runfile dependency on it
since its DefaultInfo specifies the resulting archive as an executable.
This is unnecessary as the dependent should be able to decide whether to
include the file (e.g. dynamic linking) or not (e.g. static linking).

With this commit, the executable field of the DefaultInfo is only
populated if the go_binary is built with an executable link mode.

Follow-up to bazelbuild#3143
  • Loading branch information
fmeum committed May 12, 2022
1 parent 498d6ce commit c84510b
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
15 changes: 13 additions & 2 deletions go/private/rules/binary.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ load(
)
load(
"//go/private:mode.bzl",
"LINKMODES_EXECUTABLE",
"LINKMODE_C_ARCHIVE",
"LINKMODE_C_SHARED",
"LINKMODE_NORMAL",
Expand Down Expand Up @@ -124,6 +125,15 @@ def _go_binary_impl(ctx):
executable = executable,
)

# Workaround for https://github.com/bazelbuild/bazel/issues/15043
# As of Bazel 5.1.1, native rules do not pick up the "files" of a data
# dependency's DefaultInfo, only the "data_runfiles". Since transitive
# non-data dependents should not pick up the executable as a runfile
# implicitly, the deprecated "default_runfiles" and "data_runfiles"
# constructor parameters have to be used.
default_runfiles = runfiles
data_runfiles = default_runfiles.merge(ctx.runfiles([executable]))

providers = [
library,
source,
Expand All @@ -134,8 +144,9 @@ def _go_binary_impl(ctx):
),
DefaultInfo(
files = depset([executable]),
runfiles = runfiles,
executable = executable,
data_runfiles = data_runfiles,
default_runfiles = default_runfiles,
executable = executable if go.mode.link in LINKMODES_EXECUTABLE else None,
),
]

Expand Down
38 changes: 37 additions & 1 deletion tests/core/go_binary/non_executable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,51 @@ func TestMain(m *testing.M) {
Main: `
-- src/BUILD.bazel --
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
load(":rules.bzl", "no_runfiles_check")
go_binary(
name = "archive",
srcs = ["archive.go"],
cgo = True,
linkmode = "c-archive",
)
cc_binary(
name = "main",
srcs = ["main.c"],
deps = [":archive"],
)
no_runfiles_check(
name = "no_runfiles",
target = ":main",
)
-- src/archive.go --
package main
import "C"
func main() {}
-- src/main.c --
int main() {}
-- src/rules.bzl --
def _no_runfiles_check_impl(ctx):
runfiles = ctx.attr.target[DefaultInfo].default_runfiles.files.to_list()
for runfile in runfiles:
if runfile.short_path != "src/main":
fail("Unexpected runfile: %s" % runfile)
no_runfiles_check = rule(
implementation = _no_runfiles_check_impl,
attrs = {
"target": attr.label(),
}
)
`,
})
}

func TestNonExecutableGoBinary(t *testing.T) {
func TestNonExecutableGoBinaryCantBeRun(t *testing.T) {
if err := bazel_testing.RunBazel("build", "//src:archive"); err != nil {
t.Fatal(err)
}
Expand All @@ -49,3 +79,9 @@ func TestNonExecutableGoBinary(t *testing.T) {
t.Errorf("Expected bazel run to fail due to //src:archive not being executable")
}
}

func TestNonExecutableGoBinaryNotInRunfiles(t *testing.T) {
if err := bazel_testing.RunBazel("build", "//src:no_runfiles"); err != nil {
t.Fatal(err)
}
}

0 comments on commit c84510b

Please sign in to comment.