Skip to content

Commit 7d5b65a

Browse files
authored
Merge pull request #66 from jyn514/build-std
Fetch dependencies for `-Zbuild-std` before entering the sandbox
2 parents c2bb39c + 399d37c commit 7d5b65a

File tree

6 files changed

+99
-16
lines changed

6 files changed

+99
-16
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
55

66
## Unreleased
77

8+
### Added
9+
10+
- New method `Build::fetch_build_std_dependencies` for using `-Zbuild-std` within the sandbox when
11+
networking is disabled. Previously, this would try to fetch the standard library sources, which
12+
would error when networking was blocked.
13+
814
## [0.15.2] - 2022-11-08
915

1016
### Changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,5 @@ windows-sys = {version = "0.36.1", features = ["Win32_Foundation", "Win32_System
4949

5050
[dev-dependencies]
5151
env_logger = "0.8"
52+
rand = "0.8.5"
5253
tiny_http = "0.8.0"

src/build.rs

+16
Original file line numberDiff line numberDiff line change
@@ -314,4 +314,20 @@ impl<'ws> Build<'ws> {
314314
pub fn host_target_dir(&self) -> PathBuf {
315315
self.dir.target_dir()
316316
}
317+
318+
/// Pre-fetching the dependencies for `-Z build-std` outside the sandbox.
319+
///
320+
/// When this function is called, it is possible to use `-Zbuild-std` inside
321+
/// the sandbox to build the standard library from source even when
322+
/// networking is disabled.
323+
#[cfg(any(feature = "unstable", doc))]
324+
#[cfg_attr(docs_rs, doc(cfg(feature = "unstable")))]
325+
pub fn fetch_build_std_dependencies(&self, targets: &[&str]) -> Result<(), Error> {
326+
crate::prepare::fetch_deps(
327+
&self.dir.workspace,
328+
self.toolchain,
329+
&self.host_source_dir(),
330+
targets,
331+
)
332+
}
317333
}

src/prepare.rs

+34-15
Original file line numberDiff line numberDiff line change
@@ -138,21 +138,40 @@ impl<'a> Prepare<'a> {
138138
}
139139

140140
fn fetch_deps(&mut self) -> Result<(), Error> {
141-
let mut missing_deps = false;
142-
let res = Command::new(self.workspace, self.toolchain.cargo())
143-
.args(&["fetch", "--manifest-path", "Cargo.toml"])
144-
.cd(self.source_dir)
145-
.process_lines(&mut |line, _| {
146-
if line.contains("failed to load source for dependency") {
147-
missing_deps = true;
148-
}
149-
})
150-
.run();
151-
match res {
152-
Ok(_) => Ok(()),
153-
Err(_) if missing_deps => Err(PrepareError::MissingDependencies.into()),
154-
err => err.map_err(|e| e.into()),
155-
}
141+
fetch_deps(self.workspace, self.toolchain, self.source_dir, &[])
142+
}
143+
}
144+
145+
pub(crate) fn fetch_deps(
146+
workspace: &Workspace,
147+
toolchain: &Toolchain,
148+
source_dir: &Path,
149+
fetch_build_std_targets: &[&str],
150+
) -> Result<(), Error> {
151+
let mut missing_deps = false;
152+
let mut cmd = Command::new(workspace, toolchain.cargo())
153+
.args(&["fetch", "--manifest-path", "Cargo.toml"])
154+
.cd(source_dir);
155+
// Pass `-Zbuild-std` in case a build in the sandbox wants to use it;
156+
// build-std has to have the source for libstd's dependencies available.
157+
if !fetch_build_std_targets.is_empty() {
158+
toolchain.add_component(workspace, "rust-src")?;
159+
cmd = cmd.args(&["-Zbuild-std"]).env("RUSTC_BOOTSTRAP", "1");
160+
}
161+
for target in fetch_build_std_targets {
162+
cmd = cmd.args(&["--target", target]);
163+
}
164+
let res = cmd
165+
.process_lines(&mut |line, _| {
166+
if line.contains("failed to load source for dependency") {
167+
missing_deps = true;
168+
}
169+
})
170+
.run();
171+
match res {
172+
Ok(_) => Ok(()),
173+
Err(_) if missing_deps => Err(PrepareError::MissingDependencies.into()),
174+
err => err.map_err(|e| e.into()),
156175
}
157176
}
158177

tests/buildtest/mod.rs

+31
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,37 @@ fn test_hello_world() {
2626
});
2727
}
2828

29+
#[test]
30+
#[cfg(feature = "unstable")]
31+
fn test_fetch_build_std() {
32+
use std::path::Path;
33+
34+
let target_file = Path::new(env!("OUT_DIR")).join("target");
35+
let target = std::fs::read_to_string(target_file).unwrap();
36+
37+
runner::run("hello-world", |run| {
38+
run.run(SandboxBuilder::new().enable_networking(false), |build| {
39+
build.fetch_build_std_dependencies(&vec![target.as_str()])?;
40+
let storage = rustwide::logging::LogStorage::new(LevelFilter::Info);
41+
rustwide::logging::capture(&storage, || -> Result<_, Error> {
42+
build
43+
.cargo()
44+
.env("RUSTC_BOOTSTRAP", "1")
45+
.args(&["run", "-Zbuild-std", "--target", &target])
46+
.run()?;
47+
Ok(())
48+
})?;
49+
50+
assert!(storage.to_string().contains("[stdout] Hello, world!\n"));
51+
assert!(storage
52+
.to_string()
53+
.contains("[stdout] Hello, world again!\n"));
54+
Ok(())
55+
})?;
56+
Ok(())
57+
});
58+
}
59+
2960
#[test]
3061
fn path_based_patch() {
3162
runner::run("path-based-patch", |run| {

tests/buildtest/runner.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use failure::Error;
2+
use rand::{distributions::Alphanumeric, Rng};
23
use rustwide::{cmd::SandboxBuilder, Build, BuildBuilder, Crate, Toolchain, Workspace};
34
use std::path::Path;
45

@@ -40,7 +41,16 @@ impl Runner {
4041
sandbox: SandboxBuilder,
4142
f: impl FnOnce(BuildBuilder) -> Result<T, Error>,
4243
) -> Result<T, Error> {
43-
let mut dir = self.workspace.build_dir(&self.crate_name);
44+
// Use a random string at the end to avoid conflicts if multiple tests use the same source crate.
45+
let suffix: String = rand::thread_rng()
46+
.sample_iter(&Alphanumeric)
47+
.take(10)
48+
.map(char::from)
49+
.collect();
50+
51+
let mut dir = self
52+
.workspace
53+
.build_dir(&format!("{}-{suffix}", &self.crate_name));
4454
dir.purge()?;
4555
f(dir.build(&self.toolchain, &self.krate, sandbox))
4656
}

0 commit comments

Comments
 (0)