Skip to content

Commit d288ed6

Browse files
Add out_dir support in cargo_dep_env (#1571)
* Add `out_dir` support in `cargo_dep_env` This is handy for things like passing a `PROTOC` value to `prost-build`. Also fix the other tests for `cargo_dep_env`, looks like I forgot to actually run them... * Fix buildifier and add directory checking * Add some comments * Fix buildifier Co-authored-by: UebelAndre <[email protected]>
1 parent 78d6c1b commit d288ed6

File tree

5 files changed

+114
-7
lines changed

5 files changed

+114
-7
lines changed

cargo/cargo_build_script.bzl

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,8 +450,36 @@ def _cargo_dep_env_implementation(ctx):
450450
outputs = [empty_dir],
451451
executable = "true",
452452
)
453+
454+
build_infos = []
455+
out_dir = ctx.file.out_dir
456+
if out_dir:
457+
if not out_dir.is_directory:
458+
fail("out_dir must be a directory artifact")
459+
460+
# BuildInfos in this list are collected up for all transitive cargo_build_script
461+
# dependencies. This is important for any flags set in `dep_env` which reference this
462+
# `out_dir`.
463+
#
464+
# TLDR: This BuildInfo propagates up build script dependencies.
465+
build_infos.append(BuildInfo(
466+
dep_env = empty_file,
467+
flags = empty_file,
468+
link_flags = empty_file,
469+
link_search_paths = empty_file,
470+
out_dir = out_dir,
471+
rustc_env = empty_file,
472+
))
453473
return [
454474
DefaultInfo(files = depset(ctx.files.src)),
475+
# Parts of this BuildInfo is used when building all transitive dependencies
476+
# (cargo_build_script and otherwise), alongside the DepInfo. This is how other rules
477+
# identify this one as a valid dependency, but we don't otherwise have a use for it.
478+
#
479+
# TLDR: This BuildInfo propagates up normal (non build script) depenencies.
480+
#
481+
# In the future, we could consider setting rustc_env here, and also propagating dep_dir
482+
# so files in it can be referenced there.
455483
BuildInfo(
456484
dep_env = empty_file,
457485
flags = empty_file,
@@ -460,11 +488,14 @@ def _cargo_dep_env_implementation(ctx):
460488
out_dir = empty_dir,
461489
rustc_env = empty_file,
462490
),
491+
# Information here is used directly by dependencies, and it is an error to have more than
492+
# one dependency which sets this. This is the main way to specify information from build
493+
# scripts, which is what we're looking to do.
463494
_DepInfo(
464495
dep_env = ctx.file.src,
465496
direct_crates = depset(),
466497
link_search_path_files = depset(),
467-
transitive_build_infos = depset(),
498+
transitive_build_infos = depset(direct = build_infos),
468499
transitive_crate_outputs = depset(),
469500
transitive_crates = depset(),
470501
transitive_noncrates = depset(),
@@ -480,6 +511,16 @@ cargo_dep_env = rule(
480511
"for build scripts which depend on this crate."
481512
),
482513
attrs = {
514+
"out_dir": attr.label(
515+
doc = dedent("""\
516+
Folder containing additional inputs when building all direct dependencies.
517+
518+
This has the same effect as a `cargo_build_script` which prints
519+
puts files into `$OUT_DIR`, but without requiring a build script.
520+
"""),
521+
allow_single_file = True,
522+
mandatory = False,
523+
),
483524
"src": attr.label(
484525
doc = dedent("""\
485526
File containing additional environment variables to set for build scripts of direct dependencies.

test/dep_env/BUILD.bazel

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"""Tests for passing configuration to cargo_build_script rules"""
22

33
load("//cargo:cargo_build_script.bzl", "cargo_build_script", "cargo_dep_env")
4-
load("//rust:defs.bzl", "rust_binary", "rust_library")
4+
load("//rust:defs.bzl", "rust_library", "rust_test")
5+
load(":dep_env.bzl", "create_dep_dir")
56

67
cargo_build_script(
78
name = "set_a_build",
@@ -36,16 +37,47 @@ cargo_build_script(
3637
deps = [":set_b"],
3738
)
3839

39-
rust_binary(
40+
cargo_build_script(
41+
name = "read_dep_dir",
42+
srcs = ["read_dep_dir.rs"],
43+
edition = "2018",
44+
deps = [":set_dep_dir"],
45+
)
46+
47+
rust_test(
4048
name = "build_read_a",
41-
srcs = ["empty_main.rs"],
49+
srcs = ["read_a.rs"],
4250
edition = "2018",
4351
deps = [":read_a"],
4452
)
4553

46-
rust_binary(
54+
rust_test(
4755
name = "build_read_b",
48-
srcs = ["empty_main.rs"],
56+
srcs = ["read_b.rs"],
4957
edition = "2018",
5058
deps = [":read_b"],
5159
)
60+
61+
rust_test(
62+
name = "build_read_dep_dir",
63+
srcs = ["read_dep_dir.rs"],
64+
edition = "2018",
65+
deps = [":read_dep_dir"],
66+
)
67+
68+
create_dep_dir(
69+
name = "dep_dir",
70+
)
71+
72+
cargo_dep_env(
73+
name = "set_dep_dir",
74+
src = "set_dep_dir.env",
75+
out_dir = "dep_dir",
76+
)
77+
78+
genrule(
79+
name = "gen_set_dep_dir",
80+
srcs = ["dep_dir"],
81+
outs = ["set_dep_dir.env"],
82+
cmd = "echo DEP_DIR=\\$${pwd}/$(execpath dep_dir) > $@",
83+
)

test/dep_env/dep_env.bzl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""Tests for passing configuration to cargo_build_script rules"""
2+
3+
def _create_dep_dir(ctx):
4+
out = ctx.actions.declare_directory("dep_dir")
5+
ctx.actions.run_shell(
6+
outputs = [out],
7+
arguments = [out.path],
8+
command = 'echo contents > "$@/a_file"',
9+
)
10+
return [DefaultInfo(files = depset(direct = [out]))]
11+
12+
create_dep_dir = rule(
13+
implementation = _create_dep_dir,
14+
)

test/dep_env/empty_main.rs

Lines changed: 0 additions & 1 deletion
This file was deleted.

test/dep_env/read_dep_dir.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use std::{env::var, fs, io::Result};
2+
3+
fn main() {
4+
let dep_dir = &var("DEP_DIR").expect("DEP_DIR should be set");
5+
let entries = fs::read_dir(dep_dir)
6+
.expect("Failed to open DEP_DIR directory")
7+
.collect::<Result<Vec<_>>>()
8+
.expect("Failed to read DEP_DIR directory entries");
9+
let entries = entries
10+
.iter()
11+
.map(|entry| {
12+
entry
13+
.path()
14+
.file_name()
15+
.unwrap()
16+
.to_string_lossy()
17+
.to_string()
18+
})
19+
.collect::<Vec<_>>();
20+
assert_eq!(entries, vec!["a_file".to_string()]);
21+
}

0 commit comments

Comments
 (0)