Skip to content

Commit 6849a94

Browse files
authored
Use custom traits instead of libstd's MetadataExt and PermissionsExt. (#343)
* Use custom traits instead of libstd's `MetadataExt` and `PermissionsExt`. Define our own copy of `MetadataExt` and `PermissionsExt` and change the code to use them instead of `std::os::*::fs::MetadataExt` and `std::os::*::fs::PermissionsExt'. In general, we should be moving away from using std's `Ext` traits like this, as they weren't meant to be used in this way. Fixes #342. * Have cap-std re-export the new traits, and update tests. * Update the build.rs scripts to fix Rust feature detection.
1 parent 465c70b commit 6849a94

28 files changed

+366
-131
lines changed

cap-async-std/src/fs/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ pub use cap_primitives::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permis
4040
// Re-export conditional types from `cap_primitives`.
4141
#[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))]
4242
pub use cap_primitives::fs::FileTypeExt;
43+
pub use cap_primitives::fs::MetadataExt;
44+
#[cfg(unix)]
45+
pub use cap_primitives::fs::PermissionsExt;
4346

4447
// Re-export things from `async_std` that we can use as-is.
4548
#[cfg(target_os = "wasi")]

cap-async-std/src/fs_utf8/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ pub use crate::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions};
2525
// Re-export conditional types from `cap_primitives`.
2626
#[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))]
2727
pub use cap_primitives::fs::FileTypeExt;
28+
pub use cap_primitives::fs::MetadataExt;
29+
#[cfg(unix)]
30+
pub use cap_primitives::fs::PermissionsExt;
2831

2932
// Re-export `camino` to make it easy for users to depend on the same
3033
// version we do, because we use its types in our public API.

cap-fs-ext/build.rs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,60 @@ fn use_feature(feature: &str) {
2121

2222
/// Test whether the rustc at `var("RUSTC")` supports the given feature.
2323
fn has_feature(feature: &str) -> bool {
24+
can_compile(&format!(
25+
"#![allow(stable_features)]\n#![feature({})]",
26+
feature
27+
))
28+
}
29+
30+
/// Test whether the rustc at `var("RUSTC")` can compile the given code.
31+
fn can_compile<T: AsRef<str>>(test: T) -> bool {
32+
use std::process::Stdio;
33+
2434
let out_dir = var("OUT_DIR").unwrap();
2535
let rustc = var("RUSTC").unwrap();
36+
let target = var("TARGET").unwrap();
37+
38+
// Use `RUSTC_WRAPPER` if it's set, unless it's set to an empty string,
39+
// as documented [here].
40+
// [here]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads
41+
let wrapper = var("RUSTC_WRAPPER")
42+
.ok()
43+
.and_then(|w| if w.is_empty() { None } else { Some(w) });
2644

27-
let mut child = std::process::Command::new(rustc)
28-
.arg("--crate-type=rlib") // Don't require `main`.
45+
let mut cmd = if let Some(wrapper) = wrapper {
46+
let mut cmd = std::process::Command::new(wrapper);
47+
// The wrapper's first argument is supposed to be the path to rustc.
48+
cmd.arg(rustc);
49+
cmd
50+
} else {
51+
std::process::Command::new(rustc)
52+
};
53+
54+
cmd.arg("--crate-type=rlib") // Don't require `main`.
2955
.arg("--emit=metadata") // Do as little as possible but still parse.
56+
.arg("--target")
57+
.arg(target)
3058
.arg("--out-dir")
31-
.arg(out_dir) // Put the output somewhere inconsequential.
59+
.arg(out_dir); // Put the output somewhere inconsequential.
60+
61+
// If Cargo wants to set RUSTFLAGS, use that.
62+
if let Ok(rustflags) = var("CARGO_ENCODED_RUSTFLAGS") {
63+
if !rustflags.is_empty() {
64+
for arg in rustflags.split('\x1f') {
65+
cmd.arg(arg);
66+
}
67+
}
68+
}
69+
70+
let mut child = cmd
3271
.arg("-") // Read from stdin.
33-
.stdin(std::process::Stdio::piped()) // Stdin is a pipe.
72+
.stdin(Stdio::piped()) // Stdin is a pipe.
73+
.stderr(Stdio::null()) // Errors from feature detection aren't interesting and can be confusing.
3474
.spawn()
3575
.unwrap();
3676

37-
writeln!(child.stdin.take().unwrap(), "#![feature({})]", feature).unwrap();
77+
writeln!(child.stdin.take().unwrap(), "{}", test.as_ref()).unwrap();
3878

3979
child.wait().unwrap().success()
4080
}

cap-fs-ext/src/metadata_ext.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,17 @@ impl MetadataExt for std::fs::Metadata {
7575
impl MetadataExt for cap_primitives::fs::Metadata {
7676
#[inline]
7777
fn dev(&self) -> u64 {
78-
std::os::unix::fs::MetadataExt::dev(self)
78+
cap_primitives::fs::MetadataExt::dev(self)
7979
}
8080

8181
#[inline]
8282
fn ino(&self) -> u64 {
83-
std::os::unix::fs::MetadataExt::ino(self)
83+
cap_primitives::fs::MetadataExt::ino(self)
8484
}
8585

8686
#[inline]
8787
fn nlink(&self) -> u64 {
88-
std::os::unix::fs::MetadataExt::nlink(self)
88+
cap_primitives::fs::MetadataExt::nlink(self)
8989
}
9090
}
9191

cap-primitives/build.rs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,60 @@ fn use_feature(feature: &str) {
2525

2626
/// Test whether the rustc at `var("RUSTC")` supports the given feature.
2727
fn has_feature(feature: &str) -> bool {
28+
can_compile(&format!(
29+
"#![allow(stable_features)]\n#![feature({})]",
30+
feature
31+
))
32+
}
33+
34+
/// Test whether the rustc at `var("RUSTC")` can compile the given code.
35+
fn can_compile<T: AsRef<str>>(test: T) -> bool {
36+
use std::process::Stdio;
37+
2838
let out_dir = var("OUT_DIR").unwrap();
2939
let rustc = var("RUSTC").unwrap();
40+
let target = var("TARGET").unwrap();
41+
42+
// Use `RUSTC_WRAPPER` if it's set, unless it's set to an empty string,
43+
// as documented [here].
44+
// [here]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads
45+
let wrapper = var("RUSTC_WRAPPER")
46+
.ok()
47+
.and_then(|w| if w.is_empty() { None } else { Some(w) });
3048

31-
let mut child = std::process::Command::new(rustc)
32-
.arg("--crate-type=rlib") // Don't require `main`.
49+
let mut cmd = if let Some(wrapper) = wrapper {
50+
let mut cmd = std::process::Command::new(wrapper);
51+
// The wrapper's first argument is supposed to be the path to rustc.
52+
cmd.arg(rustc);
53+
cmd
54+
} else {
55+
std::process::Command::new(rustc)
56+
};
57+
58+
cmd.arg("--crate-type=rlib") // Don't require `main`.
3359
.arg("--emit=metadata") // Do as little as possible but still parse.
60+
.arg("--target")
61+
.arg(target)
3462
.arg("--out-dir")
35-
.arg(out_dir) // Put the output somewhere inconsequential.
63+
.arg(out_dir); // Put the output somewhere inconsequential.
64+
65+
// If Cargo wants to set RUSTFLAGS, use that.
66+
if let Ok(rustflags) = var("CARGO_ENCODED_RUSTFLAGS") {
67+
if !rustflags.is_empty() {
68+
for arg in rustflags.split('\x1f') {
69+
cmd.arg(arg);
70+
}
71+
}
72+
}
73+
74+
let mut child = cmd
3675
.arg("-") // Read from stdin.
37-
.stdin(std::process::Stdio::piped()) // Stdin is a pipe.
76+
.stdin(Stdio::piped()) // Stdin is a pipe.
77+
.stderr(Stdio::null()) // Errors from feature detection aren't interesting and can be confusing.
3878
.spawn()
3979
.unwrap();
4080

41-
writeln!(child.stdin.take().unwrap(), "#![feature({})]", feature).unwrap();
81+
writeln!(child.stdin.take().unwrap(), "{}", test.as_ref()).unwrap();
4282

4383
child.wait().unwrap().success()
4484
}

0 commit comments

Comments
 (0)