diff --git a/go/private/rules/binary.bzl b/go/private/rules/binary.bzl index 8d95020ef9..2015f84d0f 100644 --- a/go/private/rules/binary.bzl +++ b/go/private/rules/binary.bzl @@ -34,6 +34,7 @@ load( ) load( "//go/private:mode.bzl", + "LINKMODES_EXECUTABLE", "LINKMODE_C_ARCHIVE", "LINKMODE_C_SHARED", "LINKMODE_NORMAL", @@ -124,19 +125,35 @@ def _go_binary_impl(ctx): executable = executable, ) + if go.mode.link in LINKMODES_EXECUTABLE: + # The executable is automatically added to the runfiles. + default_info = DefaultInfo( + files = depset([executable]), + runfiles = runfiles, + executable = executable, + ) + else: + # 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_info = DefaultInfo( + files = depset([executable]), + default_runfiles = runfiles, + data_runfiles = runfiles.merge(ctx.runfiles([executable])), + ) + providers = [ library, source, archive, + default_info, OutputGroupInfo( cgo_exports = archive.cgo_exports, compilation_outputs = [archive.data.file], ), - DefaultInfo( - files = depset([executable]), - runfiles = runfiles, - executable = executable, - ), ] # If the binary's linkmode is c-archive or c-shared, expose CcInfo diff --git a/tests/core/go_binary/non_executable_test.go b/tests/core/go_binary/non_executable_test.go index e1a352426a..e1a9c0d492 100644 --- a/tests/core/go_binary/non_executable_test.go +++ b/tests/core/go_binary/non_executable_test.go @@ -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 not in ["src/main", "src/main.exe"]: + 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) } @@ -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) + } +}