Skip to content

Commit e9dd306

Browse files
committed
Change build-std to use --sysroot.
1 parent 7d2b578 commit e9dd306

File tree

9 files changed

+131
-24
lines changed

9 files changed

+131
-24
lines changed

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

@@ -304,7 +305,11 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
304305
};
305306
let host_layout = Layout::new(self.bcx.ws, None, dest)?;
306307
let target_layout = match self.bcx.build_config.requested_target.as_ref() {
307-
Some(target) => Some(Layout::new(self.bcx.ws, Some(target), dest)?),
308+
Some(target) => {
309+
let layout = Layout::new(self.bcx.ws, Some(target), dest)?;
310+
standard_lib::prepare_sysroot(&layout)?;
311+
Some(layout)
312+
}
308313
None => None,
309314
};
310315
self.primary_packages

src/cargo/core/compiler/job_queue.rs

Lines changed: 6 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::{PackageId, TargetKind};
@@ -607,7 +608,7 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
607608
id: u32,
608609
unit: &Unit<'a>,
609610
artifact: Artifact,
610-
cx: &mut Context<'_, '_>,
611+
cx: &mut Context<'a, '_>,
611612
) -> CargoResult<()> {
612613
if unit.mode.is_run_custom_build() && cx.bcx.show_warnings(unit.pkg.package_id()) {
613614
self.emit_warnings(None, unit, cx)?;
@@ -617,6 +618,10 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
617618
Artifact::All => self.timings.unit_finished(id, unlocked),
618619
Artifact::Metadata => self.timings.unit_rmeta_finished(id, unlocked),
619620
}
621+
if unit.is_std && unit.kind == super::Kind::Target && !cx.bcx.build_config.build_plan {
622+
let rmeta = artifact == Artifact::Metadata;
623+
standard_lib::add_sysroot_artifact(cx, unit, rmeta)?;
624+
}
620625
Ok(())
621626
}
622627

src/cargo/core/compiler/layout.rs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ pub struct Layout {
116116
examples: PathBuf,
117117
/// The directory for rustdoc output: `$root/doc`
118118
doc: PathBuf,
119+
/// The local sysroot for the build-std feature.
120+
sysroot: Option<PathBuf>,
121+
/// The "lib" directory within `sysroot`.
122+
sysroot_libdir: Option<PathBuf>,
119123
/// The lockfile for a build (`.cargo-lock`). Will be unlocked when this
120124
/// struct is `drop`ped.
121125
_lock: FileLock,
@@ -139,18 +143,21 @@ impl Layout {
139143
// Flexible target specifications often point at json files, so interpret
140144
// the target triple as a Path and then just use the file stem as the
141145
// 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()
146+
let triple_path = if let Some(s) = triple {
147+
let p = Path::new(s);
148+
let tp = if p.extension().and_then(|s| s.to_str()) == Some("json") {
149+
Path::new(
150+
p.file_stem()
148151
.ok_or_else(|| failure::format_err!("invalid target"))?,
149-
);
152+
)
150153
} else {
151-
root.push(triple);
152-
}
153-
}
154+
p
155+
};
156+
root.push(tp);
157+
Some(tp)
158+
} else {
159+
None
160+
};
154161
let dest = root.join(dest);
155162
// If the root directory doesn't already exist go ahead and create it
156163
// here. Use this opportunity to exclude it from backups as well if the
@@ -167,6 +174,16 @@ impl Layout {
167174
let root = root.into_path_unlocked();
168175
let dest = dest.into_path_unlocked();
169176

177+
// Compute the sysroot path for the build-std feature.
178+
let build_std = ws.config().cli_unstable().build_std.as_ref();
179+
let (sysroot, sysroot_libdir) = if let Some(tp) = build_std.and(triple_path) {
180+
let sysroot = dest.join(".sysroot");
181+
let sysroot_libdir = sysroot.join("lib").join("rustlib").join(tp).join("lib");
182+
(Some(sysroot), Some(sysroot_libdir))
183+
} else {
184+
(None, None)
185+
};
186+
170187
Ok(Layout {
171188
deps: dest.join("deps"),
172189
build: dest.join("build"),
@@ -176,6 +193,8 @@ impl Layout {
176193
doc: root.join("doc"),
177194
root,
178195
dest,
196+
sysroot,
197+
sysroot_libdir,
179198
_lock: lock,
180199
})
181200
}
@@ -223,6 +242,16 @@ impl Layout {
223242
pub fn build(&self) -> &Path {
224243
&self.build
225244
}
245+
/// The local sysroot for the build-std feature.
246+
///
247+
/// Returns None if build-std is not enabled or this is the Host layout.
248+
pub fn sysroot(&self) -> Option<&Path> {
249+
self.sysroot.as_ref().map(|p| p.as_ref())
250+
}
251+
/// The "lib" directory within `sysroot`.
252+
pub fn sysroot_libdir(&self) -> Option<&Path> {
253+
self.sysroot_libdir.as_ref().map(|p| p.as_ref())
254+
}
226255
}
227256

228257
#[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.release,
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+
}

src/cargo/core/compiler/unit.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ pub struct UnitInner<'a> {
5151
/// The `cfg` features to enable for this unit.
5252
/// This must be sorted.
5353
pub features: Vec<&'a str>,
54+
/// Whether this is a standard library unit.
55+
pub is_std: bool,
5456
}
5557

5658
impl UnitInner<'_> {
@@ -144,6 +146,7 @@ impl<'a> UnitInterner<'a> {
144146
kind: Kind,
145147
mode: CompileMode,
146148
features: Vec<&'a str>,
149+
is_std: bool,
147150
) -> Unit<'a> {
148151
let inner = self.intern_inner(&UnitInner {
149152
pkg,
@@ -152,6 +155,7 @@ impl<'a> UnitInterner<'a> {
152155
kind,
153156
mode,
154157
features,
158+
is_std,
155159
});
156160
Unit { inner }
157161
}

src/cargo/core/compiler/unit_dependencies.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ fn new_unit_dep_with_profile<'a>(
573573
let unit = state
574574
.bcx
575575
.units
576-
.intern(pkg, target, profile, kind, mode, features);
576+
.intern(pkg, target, profile, kind, mode, features, state.is_std);
577577
Ok(UnitDep {
578578
unit,
579579
unit_for,

src/cargo/ops/cargo_clean.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,9 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
9494
)
9595
};
9696
let features = resolve.features_sorted(pkg.package_id());
97-
units.push(
98-
bcx.units
99-
.intern(pkg, target, profile, *kind, *mode, features),
100-
);
97+
units.push(bcx.units.intern(
98+
pkg, target, profile, *kind, *mode, features, /*is_std*/ false,
99+
));
101100
}
102101
}
103102
}

src/cargo/ops/cargo_compile.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -703,8 +703,15 @@ fn generate_targets<'a>(
703703
bcx.build_config.release,
704704
);
705705
let features = resolve.features_sorted(pkg.package_id());
706-
bcx.units
707-
.intern(pkg, target, profile, kind, target_mode, features)
706+
bcx.units.intern(
707+
pkg,
708+
target,
709+
profile,
710+
kind,
711+
target_mode,
712+
features,
713+
/*is_std*/ false,
714+
)
708715
};
709716

710717
// Create a list of proposed targets.

0 commit comments

Comments
 (0)