Skip to content

Commit

Permalink
Add env attribute to go_binary (#3428)
Browse files Browse the repository at this point in the history
Using the new `RunEnvironmentInfo` provider in Bazel 5.3.0, `go_binary`
targets can now specify environment variables to be set when they are
executed with `bazel run`.

Since `RunEnvironmentInfo` generalizes the `testing.TestEnvironment`
provider, the existing usage is updated.
  • Loading branch information
fmeum authored Jan 24, 2023
1 parent a58935a commit cf78385
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
tasks:
ubuntu1804_bazel400:
platform: ubuntu1804
bazel: 5.2.0 # test minimum supported version of bazel
bazel: 5.3.0 # test minimum supported version of bazel
shell_commands:
- tests/core/cgo/generate_imported_dylib.sh
build_targets:
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ The Go rules are tested and supported on the following host platforms:
Users have reported success on several other platforms, but the rules are
only tested on those listed above.

Note: Since version v0.38.0, rules_go requires Bazel ≥ 5.2.0 to work.
Note: Since version v0.38.0, rules_go requires Bazel ≥ 5.3.0 to work.

The ``master`` branch is only guaranteed to work with the latest version of Bazel.

Expand Down
5 changes: 3 additions & 2 deletions docs/go/core/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ Rules

<pre>
go_binary(<a href="#go_binary-name">name</a>, <a href="#go_binary-basename">basename</a>, <a href="#go_binary-cdeps">cdeps</a>, <a href="#go_binary-cgo">cgo</a>, <a href="#go_binary-clinkopts">clinkopts</a>, <a href="#go_binary-copts">copts</a>, <a href="#go_binary-cppopts">cppopts</a>, <a href="#go_binary-cxxopts">cxxopts</a>, <a href="#go_binary-data">data</a>, <a href="#go_binary-deps">deps</a>, <a href="#go_binary-embed">embed</a>,
<a href="#go_binary-embedsrcs">embedsrcs</a>, <a href="#go_binary-gc_goopts">gc_goopts</a>, <a href="#go_binary-gc_linkopts">gc_linkopts</a>, <a href="#go_binary-goarch">goarch</a>, <a href="#go_binary-goos">goos</a>, <a href="#go_binary-gotags">gotags</a>, <a href="#go_binary-importpath">importpath</a>, <a href="#go_binary-linkmode">linkmode</a>, <a href="#go_binary-msan">msan</a>, <a href="#go_binary-out">out</a>,
<a href="#go_binary-pure">pure</a>, <a href="#go_binary-race">race</a>, <a href="#go_binary-srcs">srcs</a>, <a href="#go_binary-static">static</a>, <a href="#go_binary-x_defs">x_defs</a>)
<a href="#go_binary-embedsrcs">embedsrcs</a>, <a href="#go_binary-env">env</a>, <a href="#go_binary-gc_goopts">gc_goopts</a>, <a href="#go_binary-gc_linkopts">gc_linkopts</a>, <a href="#go_binary-goarch">goarch</a>, <a href="#go_binary-goos">goos</a>, <a href="#go_binary-gotags">gotags</a>, <a href="#go_binary-importpath">importpath</a>, <a href="#go_binary-linkmode">linkmode</a>, <a href="#go_binary-msan">msan</a>,
<a href="#go_binary-out">out</a>, <a href="#go_binary-pure">pure</a>, <a href="#go_binary-race">race</a>, <a href="#go_binary-srcs">srcs</a>, <a href="#go_binary-static">static</a>, <a href="#go_binary-x_defs">x_defs</a>)
</pre>

This builds an executable from a set of source files,
Expand Down Expand Up @@ -158,6 +158,7 @@ This builds an executable from a set of source files,
| <a id="go_binary-deps"></a>deps | List of Go libraries this package imports directly. These may be <code>go_library</code> rules or compatible rules with the [GoLibrary] provider. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | [] |
| <a id="go_binary-embed"></a>embed | List of Go libraries whose sources should be compiled together with this binary's sources. Labels listed here must name <code>go_library</code>, <code>go_proto_library</code>, or other compatible targets with the [GoLibrary] and [GoSource] providers. Embedded libraries must all have the same <code>importpath</code>, which must match the <code>importpath</code> for this <code>go_binary</code> if one is specified. At most one embedded library may have <code>cgo = True</code>, and the embedding binary may not also have <code>cgo = True</code>. See [Embedding] for more information. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | [] |
| <a id="go_binary-embedsrcs"></a>embedsrcs | The list of files that may be embedded into the compiled package using <code>//go:embed</code> directives. All files must be in the same logical directory or a subdirectory as source files. All source files containing <code>//go:embed</code> directives must be in the same logical directory. It's okay to mix static and generated source files and static and generated embeddable files. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | [] |
| <a id="go_binary-env"></a>env | Environment variables to set when the binary is executed with bazel run. The values (but not keys) are subject to [location expansion](https://docs.bazel.build/versions/main/skylark/macros.html) but not full [make variable expansion](https://docs.bazel.build/versions/main/be/make-variables.html). | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | {} |
| <a id="go_binary-gc_goopts"></a>gc_goopts | List of flags to add to the Go compilation command when using the gc compiler. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. | List of strings | optional | [] |
| <a id="go_binary-gc_linkopts"></a>gc_linkopts | List of flags to add to the Go link command when using the gc compiler. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. | List of strings | optional | [] |
| <a id="go_binary-goarch"></a>goarch | Forces a binary to be cross-compiled for a specific architecture. 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" |
Expand Down
2 changes: 1 addition & 1 deletion go/private/common.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def get_versioned_shared_lib_extension(path):
# something like 1.2.3, or so.1.2, or dylib.1.2, or foo.1.2
return ""

MINIMUM_BAZEL_VERSION = "5.2.0"
MINIMUM_BAZEL_VERSION = "5.3.0"

def as_list(v):
"""Returns a list, tuple, or depset as a list."""
Expand Down
41 changes: 26 additions & 15 deletions go/private/rules/binary.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -122,36 +122,40 @@ def _go_binary_impl(ctx):
executable = executable,
)

providers = [
library,
source,
archive,
OutputGroupInfo(
cgo_exports = archive.cgo_exports,
compilation_outputs = [archive.data.file],
),
]

if go.mode.link in LINKMODES_EXECUTABLE:
env = {}
for k, v in ctx.attr.env.items():
env[k] = ctx.expand_location(v, ctx.attr.data)
providers.append(RunEnvironmentInfo(environment = env))

# The executable is automatically added to the runfiles.
default_info = DefaultInfo(
providers.append(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(
providers.append(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],
),
]
))

# If the binary's linkmode is c-archive or c-shared, expose CcInfo
if go.cgo_tools and go.mode.link in (LINKMODE_C_ARCHIVE, LINKMODE_C_SHARED):
Expand Down Expand Up @@ -234,6 +238,13 @@ _go_binary_kwargs = {
generated source files and static and generated embeddable files.
""",
),
"env": attr.string_dict(
doc = """Environment variables to set when the binary is executed with bazel run.
The values (but not keys) are subject to
[location expansion](https://docs.bazel.build/versions/main/skylark/macros.html) but not full
[make variable expansion](https://docs.bazel.build/versions/main/be/make-variables.html).
""",
),
"importpath": attr.string(
doc = """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
Expand Down
4 changes: 2 additions & 2 deletions go/private/rules/test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def _go_test_impl(ctx):
for k, v in ctx.attr.env.items():
env[k] = ctx.expand_location(v, ctx.attr.data)

test_environment = testing.TestEnvironment(env, ctx.attr.env_inherit)
run_environment_info = RunEnvironmentInfo(env, ctx.attr.env_inherit)

# Bazel only looks for coverage data if the test target has an
# InstrumentedFilesProvider. If the provider is found and at least one
Expand All @@ -186,7 +186,7 @@ def _go_test_impl(ctx):
dependency_attributes = ["data", "deps", "embed", "embedsrcs"],
extensions = ["go"],
),
test_environment,
run_environment_info,
]

_go_test_kwargs = {
Expand Down
5 changes: 5 additions & 0 deletions tests/core/go_test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,8 @@ go_bazel_test(
name = "env_inherit_test",
srcs = ["env_inherit_test.go"],
)

go_bazel_test(
name = "binary_env_test",
srcs = ["binary_env_test.go"],
)
55 changes: 55 additions & 0 deletions tests/core/go_test/binary_env_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2023 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package binary_env_test

import (
"testing"

"github.com/bazelbuild/rules_go/go/tools/bazel_testing"
)

func TestMain(m *testing.M) {
bazel_testing.TestMain(m, bazel_testing.Args{
Main: `
-- src/BUILD.bazel --
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
go_binary(
name = "main",
srcs = ["env.go"],
env = {"FOO": "bar"},
)
-- src/env.go --
package main
import (
"log"
"os"
)
func main() {
v := os.Getenv("FOO")
if v != "bar" {
log.Fatalf("FOO was not equal to bar")
}
}
`,
})
}

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

0 comments on commit cf78385

Please sign in to comment.