Skip to content

Commit 33d5c83

Browse files
committed
Merge remote-tracking branch 'origin/master' into custom-profile-pr-rfc
2 parents b437782 + 249b31b commit 33d5c83

File tree

38 files changed

+551
-239
lines changed

38 files changed

+551
-239
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ crossbeam-utils = "0.6"
2727
crypto-hash = "0.3.1"
2828
curl = { version = "0.4.21", features = ['http2'] }
2929
curl-sys = "0.4.18"
30-
env_logger = "0.6.0"
30+
env_logger = "0.7.0"
3131
pretty_env_logger = { version = "0.3", optional = true }
3232
failure = "0.1.5"
3333
filetime = "0.2"

crates/cargo-test-support/src/paths.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::env;
66
use std::fs;
77
use std::io::{self, ErrorKind};
88
use std::path::{Path, PathBuf};
9+
use std::process::Command;
910
use std::sync::atomic::{AtomicUsize, Ordering};
1011
use std::sync::Mutex;
1112

@@ -252,3 +253,14 @@ pub fn get_lib_extension(kind: &str) -> &str {
252253
_ => unreachable!(),
253254
}
254255
}
256+
257+
/// Returns the sysroot as queried from rustc.
258+
pub fn sysroot() -> String {
259+
let output = Command::new("rustc")
260+
.arg("--print=sysroot")
261+
.output()
262+
.expect("rustc to run");
263+
assert!(output.status.success());
264+
let sysroot = String::from_utf8(output.stdout).unwrap();
265+
sysroot.trim().to_string()
266+
}

src/cargo/core/compiler/compilation.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,13 @@ impl<'cfg> Compilation<'cfg> {
203203
super::filter_dynamic_search_path(self.native_dirs.iter(), &self.root_output);
204204
search_path.push(self.deps_output.clone());
205205
search_path.push(self.root_output.clone());
206-
search_path.push(self.target_dylib_path.clone());
206+
// For build-std, we don't want to accidentally pull in any shared
207+
// libs from the sysroot that ships with rustc. This may not be
208+
// required (at least I cannot craft a situation where it
209+
// matters), but is here to be safe.
210+
if self.config.cli_unstable().build_std.is_none() {
211+
search_path.push(self.target_dylib_path.clone());
212+
}
207213
search_path
208214
};
209215

src/cargo/core/compiler/context/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use super::custom_build::{self, BuildDeps, BuildScriptOutputs, BuildScripts};
1818
use super::fingerprint::Fingerprint;
1919
use super::job_queue::JobQueue;
2020
use super::layout::Layout;
21+
use super::standard_lib;
2122
use super::unit_dependencies::{UnitDep, UnitGraph};
2223
use super::{BuildContext, Compilation, CompileMode, Executor, FileFlavor, Kind};
2324

@@ -301,7 +302,11 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
301302
let dest = self.bcx.profiles.get_dir_name(profile_kind);
302303
let host_layout = Layout::new(self.bcx.ws, None, &dest)?;
303304
let target_layout = match self.bcx.build_config.requested_target.as_ref() {
304-
Some(target) => Some(Layout::new(self.bcx.ws, Some(target), &dest)?),
305+
Some(target) => {
306+
let layout = Layout::new(self.bcx.ws, Some(target), &dest)?;
307+
standard_lib::prepare_sysroot(&layout)?;
308+
Some(layout)
309+
}
305310
None => None,
306311
};
307312
self.primary_packages

src/cargo/core/compiler/job_queue.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use super::job::{
1717
Freshness::{self, Dirty, Fresh},
1818
Job,
1919
};
20+
use super::standard_lib;
2021
use super::timings::Timings;
2122
use super::{BuildContext, BuildPlan, CompileMode, Context, Unit};
2223
use crate::core::compiler::ProfileKind;
@@ -608,7 +609,7 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
608609
id: u32,
609610
unit: &Unit<'a>,
610611
artifact: Artifact,
611-
cx: &mut Context<'_, '_>,
612+
cx: &mut Context<'a, '_>,
612613
) -> CargoResult<()> {
613614
if unit.mode.is_run_custom_build() && cx.bcx.show_warnings(unit.pkg.package_id()) {
614615
self.emit_warnings(None, unit, cx)?;
@@ -618,6 +619,23 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
618619
Artifact::All => self.timings.unit_finished(id, unlocked),
619620
Artifact::Metadata => self.timings.unit_rmeta_finished(id, unlocked),
620621
}
622+
if unit.is_std && unit.kind == super::Kind::Target && !cx.bcx.build_config.build_plan {
623+
// This is a bit of an unusual place to copy files around, and
624+
// ideally this would be somewhere like the Work closure
625+
// (`link_targets`). The tricky issue is handling rmeta files for
626+
// pipelining. Since those are emitted asynchronously, the code
627+
// path (like `on_stderr_line`) does not have enough information
628+
// to know where the sysroot is, and that it is an std unit. If
629+
// possible, it might be nice to eventually move this to the
630+
// worker thread, but may be tricky to have the paths available.
631+
// Another possibility is to disable pipelining between std ->
632+
// non-std. The pipelining opportunities are small, and are not a
633+
// huge win (in a full build, only proc_macro overlaps for 2
634+
// seconds out of a 90s build on my system). Care must also be
635+
// taken to properly copy these artifacts for Fresh units.
636+
let rmeta = artifact == Artifact::Metadata;
637+
standard_lib::add_sysroot_artifact(cx, unit, rmeta)?;
638+
}
621639
Ok(())
622640
}
623641

src/cargo/core/compiler/layout.rs

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
//! .rustc-info.json
1313
//!
1414
//! # All final artifacts are linked into this directory from `deps`.
15+
//! # Note that named profiles will soon be included as separate directories
16+
//! # here. They have a restricted format, similar to Rust identifiers, so
17+
//! # Cargo-specific directories added in the future should use some prefix
18+
//! # like `.` to avoid name collisions.
1519
//! debug/ # or release/
1620
//!
1721
//! # File used to lock the directory to prevent multiple cargo processes
@@ -46,6 +50,11 @@
4650
//! # incremental is enabled.
4751
//! incremental/
4852
//!
53+
//! # The sysroot for -Zbuild-std builds. This only appears in
54+
//! # target-triple directories (not host), and only if -Zbuild-std is
55+
//! # enabled.
56+
//! .sysroot/
57+
//!
4958
//! # This is the location at which the output of all custom build
5059
//! # commands are rooted.
5160
//! build/
@@ -116,6 +125,10 @@ pub struct Layout {
116125
examples: PathBuf,
117126
/// The directory for rustdoc output: `$root/doc`
118127
doc: PathBuf,
128+
/// The local sysroot for the build-std feature.
129+
sysroot: Option<PathBuf>,
130+
/// The "lib" directory within `sysroot`.
131+
sysroot_libdir: Option<PathBuf>,
119132
/// The lockfile for a build (`.cargo-lock`). Will be unlocked when this
120133
/// struct is `drop`ped.
121134
_lock: FileLock,
@@ -139,18 +152,21 @@ impl Layout {
139152
// Flexible target specifications often point at json files, so interpret
140153
// the target triple as a Path and then just use the file stem as the
141154
// component for the directory name in that case.
142-
if let Some(triple) = triple {
143-
let triple = Path::new(triple);
144-
if triple.extension().and_then(|s| s.to_str()) == Some("json") {
145-
root.push(
146-
triple
147-
.file_stem()
155+
let triple_path = if let Some(s) = triple {
156+
let p = Path::new(s);
157+
let tp = if p.extension().and_then(|s| s.to_str()) == Some("json") {
158+
Path::new(
159+
p.file_stem()
148160
.ok_or_else(|| failure::format_err!("invalid target"))?,
149-
);
161+
)
150162
} else {
151-
root.push(triple);
152-
}
153-
}
163+
p
164+
};
165+
root.push(tp);
166+
Some(tp)
167+
} else {
168+
None
169+
};
154170
let dest = root.join(dest);
155171
// If the root directory doesn't already exist go ahead and create it
156172
// here. Use this opportunity to exclude it from backups as well if the
@@ -167,6 +183,17 @@ impl Layout {
167183
let root = root.into_path_unlocked();
168184
let dest = dest.into_path_unlocked();
169185

186+
// Compute the sysroot path for the build-std feature.
187+
let build_std = ws.config().cli_unstable().build_std.as_ref();
188+
let (sysroot, sysroot_libdir) = if let Some(tp) = build_std.and(triple_path) {
189+
// This uses a leading dot to avoid collision with named profiles.
190+
let sysroot = dest.join(".sysroot");
191+
let sysroot_libdir = sysroot.join("lib").join("rustlib").join(tp).join("lib");
192+
(Some(sysroot), Some(sysroot_libdir))
193+
} else {
194+
(None, None)
195+
};
196+
170197
Ok(Layout {
171198
deps: dest.join("deps"),
172199
build: dest.join("build"),
@@ -176,6 +203,8 @@ impl Layout {
176203
doc: root.join("doc"),
177204
root,
178205
dest,
206+
sysroot,
207+
sysroot_libdir,
179208
_lock: lock,
180209
})
181210
}
@@ -223,6 +252,16 @@ impl Layout {
223252
pub fn build(&self) -> &Path {
224253
&self.build
225254
}
255+
/// The local sysroot for the build-std feature.
256+
///
257+
/// Returns None if build-std is not enabled or this is the Host layout.
258+
pub fn sysroot(&self) -> Option<&Path> {
259+
self.sysroot.as_ref().map(|p| p.as_ref())
260+
}
261+
/// The "lib" directory within `sysroot`.
262+
pub fn sysroot_libdir(&self) -> Option<&Path> {
263+
self.sysroot_libdir.as_ref().map(|p| p.as_ref())
264+
}
226265
}
227266

228267
#[cfg(not(target_os = "macos"))]

src/cargo/core/compiler/mod.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use crate::util::paths;
5050
use crate::util::{self, machine_message, ProcessBuilder};
5151
use crate::util::{internal, join_paths, profile};
5252

53-
/// Indicates whether an object is for the host architcture or the target architecture.
53+
/// Indicates whether an object is for the host architecture or the target architecture.
5454
///
5555
/// These will be the same unless cross-compiling.
5656
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord, Serialize)]
@@ -915,6 +915,16 @@ fn build_base_args<'a, 'cfg>(
915915
let dir = cx.files().layout(unit.kind).incremental().as_os_str();
916916
opt(cmd, "-C", "incremental=", Some(dir));
917917
}
918+
919+
if unit.is_std {
920+
// -Zforce-unstable-if-unmarked prevents the accidental use of
921+
// unstable crates within the sysroot (such as "extern crate libc" or
922+
// any non-public crate in the sysroot).
923+
//
924+
// RUSTC_BOOTSTRAP allows unstable features on stable.
925+
cmd.arg("-Zforce-unstable-if-unmarked")
926+
.env("RUSTC_BOOTSTRAP", "1");
927+
}
918928
Ok(())
919929
}
920930

@@ -968,7 +978,17 @@ fn build_deps_args<'a, 'cfg>(
968978

969979
let mut unstable_opts = false;
970980

981+
if let Some(sysroot) = cx.files().layout(Kind::Target).sysroot() {
982+
if unit.kind == Kind::Target {
983+
cmd.arg("--sysroot").arg(sysroot);
984+
}
985+
}
986+
971987
for dep in deps {
988+
if !unit.is_std && dep.unit.is_std {
989+
// Dependency to sysroot crate uses --sysroot.
990+
continue;
991+
}
972992
if dep.unit.mode.is_run_custom_build() {
973993
cmd.env("OUT_DIR", &cx.files().build_script_out_dir(&dep.unit));
974994
}

src/cargo/core/compiler/standard_lib.rs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
//! Code for building the standard library.
22
3-
use crate::core::compiler::{BuildContext, CompileMode, Kind, Unit};
3+
use super::layout::Layout;
4+
use crate::core::compiler::{BuildContext, CompileMode, Context, FileFlavor, Kind, Unit};
45
use crate::core::profiles::UnitFor;
56
use crate::core::resolver::ResolveOpts;
67
use crate::core::{Dependency, PackageId, PackageSet, Resolve, SourceId, Workspace};
78
use crate::ops::{self, Packages};
89
use crate::util::errors::CargoResult;
10+
use crate::util::paths;
911
use std::collections::{HashMap, HashSet};
1012
use std::env;
1113
use std::path::PathBuf;
@@ -141,9 +143,15 @@ pub fn generate_std_roots<'a>(
141143
bcx.build_config.profile_kind.clone(),
142144
);
143145
let features = std_resolve.features_sorted(pkg.package_id());
144-
Ok(bcx
145-
.units
146-
.intern(pkg, lib, profile, Kind::Target, mode, features))
146+
Ok(bcx.units.intern(
147+
pkg,
148+
lib,
149+
profile,
150+
Kind::Target,
151+
mode,
152+
features,
153+
/*is_std*/ true,
154+
))
147155
})
148156
.collect::<CargoResult<Vec<_>>>()
149157
}
@@ -173,3 +181,33 @@ fn detect_sysroot_src_path(ws: &Workspace<'_>) -> CargoResult<PathBuf> {
173181
}
174182
Ok(src_path)
175183
}
184+
185+
/// Prepare the output directory for the local sysroot.
186+
pub fn prepare_sysroot(layout: &Layout) -> CargoResult<()> {
187+
if let Some(libdir) = layout.sysroot_libdir() {
188+
if libdir.exists() {
189+
paths::remove_dir_all(libdir)?;
190+
}
191+
paths::create_dir_all(libdir)?;
192+
}
193+
Ok(())
194+
}
195+
196+
/// Copy an artifact to the sysroot.
197+
pub fn add_sysroot_artifact<'a>(
198+
cx: &Context<'a, '_>,
199+
unit: &Unit<'a>,
200+
rmeta: bool,
201+
) -> CargoResult<()> {
202+
let outputs = cx.outputs(unit)?;
203+
let outputs = outputs
204+
.iter()
205+
.filter(|output| output.flavor == FileFlavor::Linkable { rmeta })
206+
.map(|output| &output.path);
207+
for path in outputs {
208+
let libdir = cx.files().layout(Kind::Target).sysroot_libdir().unwrap();
209+
let dst = libdir.join(path.file_name().unwrap());
210+
paths::link_or_copy(path, dst)?;
211+
}
212+
Ok(())
213+
}

0 commit comments

Comments
 (0)