Add a `cargo_dep_env` rule for setting build.rs environment variables (#1415)
From the docs:
> A rule for generating variables for dependent `cargo_build_script`s
> without a build script. This is useful for using Bazel rules instead
> of a build script, while also generating configuration information
> for build scripts which depend on this crate.
diff --git a/cargo/cargo_build_script.bzl b/cargo/cargo_build_script.bzl
index d53c6e1..dfd4fd0 100644
--- a/cargo/cargo_build_script.bzl
+++ b/cargo/cargo_build_script.bzl
@@ -5,6 +5,9 @@
load("//rust:defs.bzl", "rust_binary", "rust_common")
# buildifier: disable=bzl-visibility
+load("//rust/private:providers.bzl", _DepInfo = "DepInfo")
+
+# buildifier: disable=bzl-visibility
load("//rust/private:rustc.bzl", "BuildInfo", "get_compilation_mode_opts", "get_linker_and_args")
# buildifier: disable=bzl-visibility
@@ -435,3 +438,61 @@
if name.endswith("_build_script"):
return name[:-len("_build_script")]
return name
+
+def _cargo_dep_env_implementation(ctx):
+ empty_file = ctx.actions.declare_file(ctx.label.name + ".empty_file")
+ empty_dir = ctx.actions.declare_directory(ctx.label.name + ".empty_dir")
+ ctx.actions.write(
+ output = empty_file,
+ content = "",
+ )
+ ctx.actions.run(
+ outputs = [empty_dir],
+ executable = "true",
+ )
+ return [
+ DefaultInfo(files = depset(ctx.files.src)),
+ BuildInfo(
+ dep_env = empty_file,
+ flags = empty_file,
+ link_flags = empty_file,
+ link_search_paths = empty_file,
+ out_dir = empty_dir,
+ rustc_env = empty_file,
+ ),
+ _DepInfo(
+ dep_env = ctx.file.src,
+ direct_crates = depset(),
+ link_search_path_files = depset(),
+ transitive_build_infos = depset(),
+ transitive_crate_outputs = depset(),
+ transitive_crates = depset(),
+ transitive_noncrates = depset(),
+ ),
+ ]
+
+cargo_dep_env = rule(
+ implementation = _cargo_dep_env_implementation,
+ doc = (
+ "A rule for generating variables for dependent `cargo_build_script`s " +
+ "without a build script. This is useful for using Bazel rules instead " +
+ "of a build script, while also generating configuration information " +
+ "for build scripts which depend on this crate."
+ ),
+ attrs = {
+ "src": attr.label(
+ doc = dedent("""\
+ File containing additional environment variables to set for build scripts of direct dependencies.
+
+ This has the same effect as a `cargo_build_script` which prints
+ `cargo:VAR=VALUE` lines, but without requiring a build script.
+
+ This files should contain a single variable per line, of format
+ `NAME=value`, and newlines may be included in a value by ending a
+ line with a trailing back-slash (`\\\\`).
+ """),
+ allow_single_file = True,
+ mandatory = True,
+ ),
+ },
+)
diff --git a/test/dep_env/BUILD.bazel b/test/dep_env/BUILD.bazel
new file mode 100644
index 0000000..64addcd
--- /dev/null
+++ b/test/dep_env/BUILD.bazel
@@ -0,0 +1,51 @@
+"""Tests for passing configuration to cargo_build_script rules"""
+
+load("//cargo:cargo_build_script.bzl", "cargo_build_script", "cargo_dep_env")
+load("//rust:defs.bzl", "rust_binary", "rust_library")
+
+cargo_build_script(
+ name = "set_a_build",
+ srcs = ["set_a.rs"],
+ edition = "2018",
+ links = "X",
+)
+
+rust_library(
+ name = "set_a",
+ srcs = ["empty.rs"],
+ edition = "2018",
+ deps = [":set_a_build"],
+)
+
+cargo_dep_env(
+ name = "set_b",
+ src = "set_b.env",
+)
+
+cargo_build_script(
+ name = "read_a",
+ srcs = ["read_a.rs"],
+ edition = "2018",
+ deps = [":set_a"],
+)
+
+cargo_build_script(
+ name = "read_b",
+ srcs = ["read_b.rs"],
+ edition = "2018",
+ deps = [":set_b"],
+)
+
+rust_binary(
+ name = "build_read_a",
+ srcs = ["empty_main.rs"],
+ edition = "2018",
+ deps = [":read_a"],
+)
+
+rust_binary(
+ name = "build_read_b",
+ srcs = ["empty_main.rs"],
+ edition = "2018",
+ deps = [":read_b"],
+)
diff --git a/test/dep_env/empty.rs b/test/dep_env/empty.rs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/dep_env/empty.rs
@@ -0,0 +1 @@
+
diff --git a/test/dep_env/empty_main.rs b/test/dep_env/empty_main.rs
new file mode 100644
index 0000000..f328e4d
--- /dev/null
+++ b/test/dep_env/empty_main.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/test/dep_env/read_a.rs b/test/dep_env/read_a.rs
new file mode 100644
index 0000000..8775f81
--- /dev/null
+++ b/test/dep_env/read_a.rs
@@ -0,0 +1,5 @@
+use std::env::var;
+
+fn main() {
+ assert_eq!(var("DEP_X_A").unwrap(), "a_value");
+}
diff --git a/test/dep_env/read_b.rs b/test/dep_env/read_b.rs
new file mode 100644
index 0000000..b63db42
--- /dev/null
+++ b/test/dep_env/read_b.rs
@@ -0,0 +1,5 @@
+use std::env::var;
+
+fn main() {
+ assert_eq!(var("DEP_Y_B").unwrap(), "b_value");
+}
diff --git a/test/dep_env/set_a.rs b/test/dep_env/set_a.rs
new file mode 100644
index 0000000..7e8082a
--- /dev/null
+++ b/test/dep_env/set_a.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("cargo:A=a_value");
+}
diff --git a/test/dep_env/set_b.env b/test/dep_env/set_b.env
new file mode 100644
index 0000000..4657007
--- /dev/null
+++ b/test/dep_env/set_b.env
@@ -0,0 +1 @@
+DEP_Y_B=b_value