Skip to content

Commit 3a569b8

Browse files
authored
Link flags are passed to transitive rdeps (#346)
And absolute paths are redacted into $EXEC_ROOT-relative paths This mirrors Cargo's behaviour of accumulating link flags and passing them to the linker - otherwise there's not much point in sys libraries outputting them. This currently over-adds out_dirs and link flags to all actions, rather than just those that will invoke the linker - we can reduce that if we have a clear indication of what targets will invoke a linker, but I wanted to go with a safe-but-over-invalidating solution rather than picking a bad heuristic.
1 parent f188c9b commit 3a569b8

File tree

15 files changed

+346
-108
lines changed

15 files changed

+346
-108
lines changed

WORKSPACE

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,6 @@ rbe_autoconfig(
9999

100100
load("@io_bazel_rules_rust//:workspace.bzl", "bazel_version")
101101
bazel_version(name = "bazel_version")
102+
103+
load("@examples//hello_sys:workspace.bzl", "remote_deps")
104+
remote_deps()

cargo/cargo_build_script.bzl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ def _cargo_build_script_run(ctx, script):
99
env_out = ctx.actions.declare_file(ctx.label.name + ".env")
1010
dep_env_out = ctx.actions.declare_file(ctx.label.name + ".depenv")
1111
flags_out = ctx.actions.declare_file(ctx.label.name + ".flags")
12+
link_flags = ctx.actions.declare_file(ctx.label.name + ".linkflags")
1213
manifest_dir = "%s.runfiles/%s" % (script.path, ctx.label.workspace_name or ctx.workspace_name)
1314
compilation_mode_opt_level = get_compilation_mode_opts(ctx, toolchain).opt_level
1415

@@ -33,10 +34,10 @@ def _cargo_build_script_run(ctx, script):
3334
"CARGO_MANIFEST_DIR": manifest_dir,
3435
"HOST": toolchain.exec_triple,
3536
"OPT_LEVEL": compilation_mode_opt_level,
36-
"OUT_DIR": out_dir.path,
3737
"RUSTC": toolchain.rustc.path,
3838
"RUST_BACKTRACE": "full",
3939
"TARGET": toolchain.target_triple,
40+
# OUT_DIR is set by the runner itself, rather than on the action.
4041
}
4142

4243
# Pull in env vars which may be required for the cc_toolchain to work (e.g. on OSX, the SDK version).
@@ -77,8 +78,8 @@ def _cargo_build_script_run(ctx, script):
7778

7879
ctx.actions.run_shell(
7980
command = cmd,
80-
arguments = [ctx.executable._cargo_build_script_runner.path, script.path, crate_name, env_out.path, flags_out.path, dep_env_out.path],
81-
outputs = [out_dir, env_out, flags_out, dep_env_out],
81+
arguments = [ctx.executable._cargo_build_script_runner.path, script.path, crate_name, out_dir.path, env_out.path, flags_out.path, link_flags.path, dep_env_out.path],
82+
outputs = [out_dir, env_out, flags_out, link_flags, dep_env_out],
8283
tools = tools,
8384
inputs = dep_env_files,
8485
mnemonic = "CargoBuildScriptRun",
@@ -91,6 +92,7 @@ def _cargo_build_script_run(ctx, script):
9192
rustc_env = env_out,
9293
dep_env = dep_env_out,
9394
flags = flags_out,
95+
link_flags = link_flags,
9496
),
9597
]
9698

cargo/cargo_build_script_runner/bin.rs

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@
1616
// by rust_library/rust_binary.
1717
extern crate cargo_build_script_output_parser;
1818

19-
use cargo_build_script_output_parser::BuildScriptOutput;
19+
use cargo_build_script_output_parser::{BuildScriptOutput, CompileAndLinkFlags};
2020
use std::env;
21-
use std::fs::{File, create_dir_all};
22-
use std::io::Write;
21+
use std::fs::{create_dir_all, write};
2322
use std::path::Path;
2423
use std::process::{exit, Command};
2524

@@ -33,13 +32,8 @@ fn main() {
3332

3433
let mut args = env::args().skip(1);
3534
let manifest_dir_env = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR was not set");
36-
let out_dir_env = env::var("OUT_DIR").expect("OUT_DIR was not set");
37-
// For some reason RBE does not creat the output directory, force create it
38-
create_dir_all(out_dir_env.clone()).expect(&format!("Failed to create OUT_DIR: {}", out_dir_env));
3935
let rustc_env = env::var("RUSTC").expect("RUSTC was not set");
40-
// Because of the Bazel's sandbox, bazel cannot provide full path, convert all relative path to correct path.
4136
let manifest_dir = exec_root.join(&manifest_dir_env);
42-
let out_dir = exec_root.join(&out_dir_env);
4337
let rustc = exec_root.join(&rustc_env);
4438

4539
let cc = env::var_os("CC").map(|env_var| {
@@ -51,13 +45,17 @@ fn main() {
5145
}
5246
});
5347

54-
match (args.next(), args.next(), args.next(), args.next(), args.next()) {
55-
(Some(progname), Some(crate_name), Some(envfile), Some(flagfile), Some(depenvfile)) => {
48+
match (args.next(), args.next(), args.next(), args.next(), args.next(), args.next(), args.next()) {
49+
(Some(progname), Some(crate_name), Some(out_dir), Some(envfile), Some(flagfile), Some(linkflags), Some(depenvfile)) => {
50+
let out_dir_abs = exec_root.join(&out_dir);
51+
// For some reason Google's RBE does not create the output directory, force create it.
52+
create_dir_all(&out_dir_abs).expect(&format!("Failed to make output directory: {:?}", out_dir_abs));
53+
5654
let mut command = Command::new(exec_root.join(&progname));
5755
command
5856
.args(args)
5957
.current_dir(manifest_dir.clone())
60-
.env("OUT_DIR", out_dir)
58+
.env("OUT_DIR", out_dir_abs)
6159
.env("CARGO_MANIFEST_DIR", manifest_dir)
6260
.env("RUSTC", rustc);
6361

@@ -66,21 +64,20 @@ fn main() {
6664
}
6765

6866
let output = BuildScriptOutput::from_command(&mut command);
69-
let mut f =
70-
File::create(&envfile).expect(&format!("Unable to create file {}", envfile));
71-
f.write_all(BuildScriptOutput::to_env(&output).as_bytes())
72-
.expect(&format!("Unable to write file {}", envfile));
73-
let mut f =
74-
File::create(&depenvfile).expect(&format!("Unable to create file {}", depenvfile));
75-
f.write_all(BuildScriptOutput::to_dep_env(&output, &crate_name).as_bytes())
76-
.expect(&format!("Unable to write file {}", depenvfile));
77-
let mut f =
78-
File::create(&flagfile).expect(&format!("Unable to create file {}", flagfile));
79-
f.write_all(BuildScriptOutput::to_flags(&output).as_bytes())
80-
.expect(&format!("Unable to write file {}", flagfile));
67+
write(&envfile, BuildScriptOutput::to_env(&output).as_bytes())
68+
.expect(&format!("Unable to write file {:?}", envfile));
69+
write(&depenvfile, BuildScriptOutput::to_dep_env(&output, &crate_name).as_bytes())
70+
.expect(&format!("Unable to write file {:?}", depenvfile));
71+
72+
let CompileAndLinkFlags { compile_flags, link_flags } = BuildScriptOutput::to_flags(&output, &exec_root.to_string_lossy());
73+
74+
write(&flagfile, compile_flags.as_bytes())
75+
.expect(&format!("Unable to write file {:?}", flagfile));
76+
write(&linkflags, link_flags.as_bytes())
77+
.expect(&format!("Unable to write file {:?}", linkflags));
8178
}
8279
_ => {
83-
eprintln!("Usage: $0 progname crate_name envfile flagfile depenvfile [arg1...argn]");
80+
eprintln!("Usage: $0 progname crate_name out_dir envfile flagfile linkflagfile depenvfile [arg1...argn]");
8481
exit(1);
8582
}
8683
}

cargo/cargo_build_script_runner/lib.rs

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
use std::io::{BufRead, BufReader, Read};
1818
use std::process::{Command, Stdio};
1919

20+
#[derive(Debug, PartialEq, Eq)]
21+
pub struct CompileAndLinkFlags {
22+
pub compile_flags: String,
23+
pub link_flags: String,
24+
}
25+
2026
/// Enum containing all the considered return value from the script
2127
#[derive(Debug, Clone, PartialEq, Eq)]
2228
pub enum BuildScriptOutput {
@@ -141,17 +147,23 @@ impl BuildScriptOutput {
141147
}
142148

143149
/// Convert a vector of [BuildScriptOutput] into a flagfile.
144-
pub fn to_flags(v: &Vec<BuildScriptOutput>) -> String {
145-
v.iter()
146-
.filter_map(|x| match x {
147-
BuildScriptOutput::Cfg(e) => Some(format!("--cfg={}", e)),
148-
BuildScriptOutput::Flags(e) => Some(e.to_owned()),
149-
BuildScriptOutput::LinkLib(e) => Some(format!("-l{}", e)),
150-
BuildScriptOutput::LinkSearch(e) => Some(format!("-L{}", e)),
151-
_ => None,
152-
})
153-
.collect::<Vec<_>>()
154-
.join(" ")
150+
pub fn to_flags(v: &Vec<BuildScriptOutput>, exec_root: &str) -> CompileAndLinkFlags {
151+
let mut compile_flags = Vec::new();
152+
let mut link_flags = Vec::new();
153+
154+
for flag in v {
155+
match flag {
156+
BuildScriptOutput::Cfg(e) => compile_flags.push(format!("--cfg={}", e)),
157+
BuildScriptOutput::Flags(e) => compile_flags.push(e.to_owned()),
158+
BuildScriptOutput::LinkLib(e) => link_flags.push(format!("-l{}", e)),
159+
BuildScriptOutput::LinkSearch(e) => link_flags.push(format!("-L{}", e)),
160+
_ => { },
161+
}
162+
}
163+
CompileAndLinkFlags {
164+
compile_flags: compile_flags.join(" "),
165+
link_flags: link_flags.join(" ").replace(exec_root, "${EXEC_ROOT}"),
166+
}
155167
}
156168
}
157169

@@ -166,7 +178,7 @@ mod tests {
166178
"
167179
cargo:rustc-link-lib=sdfsdf
168180
cargo:rustc-env=FOO=BAR
169-
cargo:rustc-link-search=bleh
181+
cargo:rustc-link-search=/some/absolute/path/bleh
170182
cargo:rustc-env=BAR=FOO
171183
cargo:rustc-flags=-Lblah
172184
cargo:rerun-if-changed=ignored
@@ -180,7 +192,7 @@ cargo:version_number=1010107f
180192
assert_eq!(result.len(), 8);
181193
assert_eq!(result[0], BuildScriptOutput::LinkLib("sdfsdf".to_owned()));
182194
assert_eq!(result[1], BuildScriptOutput::Env("FOO=BAR".to_owned()));
183-
assert_eq!(result[2], BuildScriptOutput::LinkSearch("bleh".to_owned()));
195+
assert_eq!(result[2], BuildScriptOutput::LinkSearch("/some/absolute/path/bleh".to_owned()));
184196
assert_eq!(result[3], BuildScriptOutput::Env("BAR=FOO".to_owned()));
185197
assert_eq!(result[4], BuildScriptOutput::Flags("-Lblah".to_owned()));
186198
assert_eq!(
@@ -199,8 +211,13 @@ cargo:version_number=1010107f
199211
"FOO=BAR BAR=FOO".to_owned()
200212
);
201213
assert_eq!(
202-
BuildScriptOutput::to_flags(&result),
203-
"-lsdfsdf -Lbleh -Lblah --cfg=feature=awesome".to_owned()
214+
BuildScriptOutput::to_flags(&result, "/some/absolute/path"),
215+
CompileAndLinkFlags {
216+
// -Lblah was output as a rustc-flags, so even though it probably _should_ be a link
217+
// flag, we don't treat it like one.
218+
compile_flags: "-Lblah --cfg=feature=awesome".to_owned(),
219+
link_flags: "-lsdfsdf -L${EXEC_ROOT}/bleh".to_owned(),
220+
}
204221
);
205222
}
206223

examples/WORKSPACE

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,7 @@ rust_wasm_bindgen_repositories()
6969
load("@io_bazel_rules_rust//:workspace.bzl", "bazel_version")
7070

7171
bazel_version(name = "bazel_version")
72+
73+
load("@examples//hello_sys:workspace.bzl", "remote_deps")
74+
75+
remote_deps()

examples/hello_sys/BUILD

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
load(
4+
"@io_bazel_rules_rust//rust:rust.bzl",
5+
"rust_binary",
6+
)
7+
8+
rust_binary(
9+
name = "hello_sys",
10+
srcs = ["src/main.rs"],
11+
edition = "2018",
12+
deps = ["@bzip2"],
13+
)
14+
15+
sh_test(
16+
name = "test",
17+
srcs = ["test.sh"],
18+
args = ["$(location :hello_sys)"],
19+
data = [":hello_sys"],
20+
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
load(
2+
"@io_bazel_rules_rust//rust:rust.bzl",
3+
"rust_library",
4+
)
5+
6+
rust_library(
7+
name = "bzip2",
8+
srcs = glob(["**/*.rs"]),
9+
crate_root = "src/lib.rs",
10+
crate_type = "lib",
11+
edition = "2015",
12+
rustc_flags = [
13+
"--cap-lints=allow",
14+
],
15+
version = "0.3.3",
16+
visibility = ["//visibility:public"],
17+
deps = [
18+
"@bzip2_sys",
19+
"@libc",
20+
],
21+
)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
load(
2+
"@io_bazel_rules_rust//rust:rust.bzl",
3+
"rust_library",
4+
)
5+
load(
6+
"@io_bazel_rules_rust//cargo:cargo_build_script.bzl",
7+
"cargo_build_script",
8+
)
9+
10+
cargo_build_script(
11+
name = "bzip2_sys_build_script",
12+
srcs = glob(["**/*.rs"]),
13+
crate_root = "build.rs",
14+
data = glob(["**"]),
15+
edition = "2015",
16+
rustc_flags = [
17+
"--cap-lints=allow",
18+
],
19+
version = "0.1.9+1.0.8",
20+
deps = [
21+
"@cc",
22+
"@pkg_config",
23+
],
24+
)
25+
26+
rust_library(
27+
name = "bzip2_sys",
28+
srcs = glob(["**/*.rs"]),
29+
crate_root = "lib.rs",
30+
crate_type = "lib",
31+
edition = "2015",
32+
rustc_flags = [
33+
"--cap-lints=allow",
34+
],
35+
version = "0.1.9+1.0.8",
36+
visibility = ["//visibility:public"],
37+
deps = [
38+
":bzip2_sys_build_script",
39+
"@libc",
40+
],
41+
)

examples/hello_sys/cc-1.0.54.BUILD

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
load(
2+
"@io_bazel_rules_rust//rust:rust.bzl",
3+
"rust_library",
4+
)
5+
6+
rust_library(
7+
name = "cc",
8+
srcs = glob(["**/*.rs"]),
9+
crate_root = "src/lib.rs",
10+
crate_type = "lib",
11+
edition = "2018",
12+
rustc_flags = [
13+
"--cap-lints=allow",
14+
],
15+
version = "1.0.54",
16+
visibility = ["//visibility:public"],
17+
)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
load(
2+
"@io_bazel_rules_rust//rust:rust.bzl",
3+
"rust_library",
4+
)
5+
6+
rust_library(
7+
name = "pkg_config",
8+
srcs = glob(["**/*.rs"]),
9+
crate_root = "src/lib.rs",
10+
crate_type = "lib",
11+
edition = "2015",
12+
rustc_flags = [
13+
"--cap-lints=allow",
14+
],
15+
version = "0.3.17",
16+
visibility = ["//visibility:public"],
17+
)

0 commit comments

Comments
 (0)