Skip to content

Commit ea3c309

Browse files
authored
Rollup merge of #72999 - mati865:separate-self-contained-dir, r=Mark-Simulacrum
Create self-contained directory and move there some of external binaries/libs One of the steps to reach design described in #68887 (comment) This PR moves things around and allows link code to handle the new directory structure.
2 parents 5e7eec2 + 43905cd commit ea3c309

File tree

5 files changed

+162
-61
lines changed

5 files changed

+162
-61
lines changed

src/bootstrap/compile.rs

+112-52
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::builder::Cargo;
2323
use crate::dist;
2424
use crate::native;
2525
use crate::util::{exe, is_dylib, symlink_dir};
26-
use crate::{Compiler, GitRepo, Mode};
26+
use crate::{Compiler, DependencyType, GitRepo, Mode};
2727

2828
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
2929
use crate::cache::{Interned, INTERNER};
@@ -74,6 +74,7 @@ impl Step for Std {
7474
// Even if we're not building std this stage, the new sysroot must
7575
// still contain the third party objects needed by various targets.
7676
copy_third_party_objects(builder, &compiler, target);
77+
copy_self_contained_objects(builder, &compiler, target);
7778

7879
builder.ensure(StdLink {
7980
compiler: compiler_to_use,
@@ -83,7 +84,8 @@ impl Step for Std {
8384
return;
8485
}
8586

86-
target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter());
87+
target_deps.extend(copy_third_party_objects(builder, &compiler, target));
88+
target_deps.extend(copy_self_contained_objects(builder, &compiler, target));
8789

8890
let mut cargo = builder.cargo(compiler, Mode::Std, target, "build");
8991
std_cargo(builder, target, compiler.stage, &mut cargo);
@@ -109,21 +111,76 @@ impl Step for Std {
109111
}
110112
}
111113

114+
fn copy_and_stamp(
115+
builder: &Builder<'_>,
116+
libdir: &Path,
117+
sourcedir: &Path,
118+
name: &str,
119+
target_deps: &mut Vec<(PathBuf, DependencyType)>,
120+
dependency_type: DependencyType,
121+
) {
122+
let target = libdir.join(name);
123+
builder.copy(&sourcedir.join(name), &target);
124+
125+
target_deps.push((target, dependency_type));
126+
}
127+
112128
/// Copies third party objects needed by various targets.
113129
fn copy_third_party_objects(
114130
builder: &Builder<'_>,
115131
compiler: &Compiler,
116132
target: Interned<String>,
117-
) -> Vec<PathBuf> {
133+
) -> Vec<(PathBuf, DependencyType)> {
118134
let libdir = builder.sysroot_libdir(*compiler, target);
119-
120135
let mut target_deps = vec![];
121136

122-
let mut copy_and_stamp = |sourcedir: &Path, name: &str| {
123-
let target = libdir.join(name);
124-
builder.copy(&sourcedir.join(name), &target);
125-
target_deps.push(target);
137+
// Copies libunwind.a compiled to be linked with x86_64-fortanix-unknown-sgx.
138+
//
139+
// This target needs to be linked to Fortanix's port of llvm's libunwind.
140+
// libunwind requires support for rwlock and printing to stderr,
141+
// which is provided by std for this target.
142+
if target == "x86_64-fortanix-unknown-sgx" {
143+
let src_path_env = "X86_FORTANIX_SGX_LIBS";
144+
let src =
145+
env::var(src_path_env).unwrap_or_else(|_| panic!("{} not found in env", src_path_env));
146+
copy_and_stamp(
147+
builder,
148+
&*libdir,
149+
Path::new(&src),
150+
"libunwind.a",
151+
&mut target_deps,
152+
DependencyType::Target,
153+
);
154+
}
155+
156+
if builder.config.sanitizers && compiler.stage != 0 {
157+
// The sanitizers are only copied in stage1 or above,
158+
// to avoid creating dependency on LLVM.
159+
target_deps.extend(
160+
copy_sanitizers(builder, &compiler, target)
161+
.into_iter()
162+
.map(|d| (d, DependencyType::Target)),
163+
);
164+
}
165+
166+
target_deps
167+
}
168+
169+
/// Copies third party objects needed by various targets for self-contained linkage.
170+
fn copy_self_contained_objects(
171+
builder: &Builder<'_>,
172+
compiler: &Compiler,
173+
target: Interned<String>,
174+
) -> Vec<(PathBuf, DependencyType)> {
175+
// cfg(bootstrap)
176+
// Remove when upgrading bootstrap compiler.
177+
let libdir_self_contained = if compiler.stage == 0 {
178+
builder.sysroot_libdir(*compiler, target).to_path_buf()
179+
} else {
180+
builder.sysroot_libdir(*compiler, target).join("self-contained")
126181
};
182+
t!(fs::create_dir_all(&libdir_self_contained));
183+
let mut target_deps = vec![];
127184

128185
// Copies the CRT objects.
129186
//
@@ -135,29 +192,32 @@ fn copy_third_party_objects(
135192
if target.contains("musl") {
136193
let srcdir = builder.musl_root(target).unwrap().join("lib");
137194
for &obj in &["crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
138-
copy_and_stamp(&srcdir, obj);
195+
copy_and_stamp(
196+
builder,
197+
&libdir_self_contained,
198+
&srcdir,
199+
obj,
200+
&mut target_deps,
201+
DependencyType::TargetSelfContained,
202+
);
139203
}
140204
} else if target.ends_with("-wasi") {
141205
let srcdir = builder.wasi_root(target).unwrap().join("lib/wasm32-wasi");
142-
copy_and_stamp(&srcdir, "crt1.o");
143-
}
144-
145-
// Copies libunwind.a compiled to be linked with x86_64-fortanix-unknown-sgx.
146-
//
147-
// This target needs to be linked to Fortanix's port of llvm's libunwind.
148-
// libunwind requires support for rwlock and printing to stderr,
149-
// which is provided by std for this target.
150-
if target == "x86_64-fortanix-unknown-sgx" {
151-
let src_path_env = "X86_FORTANIX_SGX_LIBS";
152-
let src =
153-
env::var(src_path_env).unwrap_or_else(|_| panic!("{} not found in env", src_path_env));
154-
copy_and_stamp(Path::new(&src), "libunwind.a");
155-
}
156-
157-
if builder.config.sanitizers && compiler.stage != 0 {
158-
// The sanitizers are only copied in stage1 or above,
159-
// to avoid creating dependency on LLVM.
160-
target_deps.extend(copy_sanitizers(builder, &compiler, target));
206+
copy_and_stamp(
207+
builder,
208+
&libdir_self_contained,
209+
&srcdir,
210+
"crt1.o",
211+
&mut target_deps,
212+
DependencyType::TargetSelfContained,
213+
);
214+
} else if target.contains("windows-gnu") {
215+
for obj in ["crt2.o", "dllcrt2.o"].iter() {
216+
let src = compiler_file(builder, builder.cc(target), target, obj);
217+
let target = libdir_self_contained.join(obj);
218+
builder.copy(&src, &target);
219+
target_deps.push((target, DependencyType::TargetSelfContained));
220+
}
161221
}
162222

163223
target_deps
@@ -335,7 +395,7 @@ pub struct StartupObjects {
335395
}
336396

337397
impl Step for StartupObjects {
338-
type Output = Vec<PathBuf>;
398+
type Output = Vec<(PathBuf, DependencyType)>;
339399

340400
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
341401
run.path("src/rtstartup")
@@ -354,7 +414,7 @@ impl Step for StartupObjects {
354414
/// They don't require any library support as they're just plain old object
355415
/// files, so we just use the nightly snapshot compiler to always build them (as
356416
/// no other compilers are guaranteed to be available).
357-
fn run(self, builder: &Builder<'_>) -> Vec<PathBuf> {
417+
fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
358418
let for_compiler = self.compiler;
359419
let target = self.target;
360420
if !target.contains("windows-gnu") {
@@ -388,14 +448,7 @@ impl Step for StartupObjects {
388448

389449
let target = sysroot_dir.join((*file).to_string() + ".o");
390450
builder.copy(dst_file, &target);
391-
target_deps.push(target);
392-
}
393-
394-
for obj in ["crt2.o", "dllcrt2.o"].iter() {
395-
let src = compiler_file(builder, builder.cc(target), target, obj);
396-
let target = sysroot_dir.join(obj);
397-
builder.copy(&src, &target);
398-
target_deps.push(target);
451+
target_deps.push((target, DependencyType::Target));
399452
}
400453

401454
target_deps
@@ -808,14 +861,17 @@ pub fn add_to_sysroot(
808861
sysroot_host_dst: &Path,
809862
stamp: &Path,
810863
) {
864+
let self_contained_dst = &sysroot_dst.join("self-contained");
811865
t!(fs::create_dir_all(&sysroot_dst));
812866
t!(fs::create_dir_all(&sysroot_host_dst));
813-
for (path, host) in builder.read_stamp_file(stamp) {
814-
if host {
815-
builder.copy(&path, &sysroot_host_dst.join(path.file_name().unwrap()));
816-
} else {
817-
builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
818-
}
867+
t!(fs::create_dir_all(&self_contained_dst));
868+
for (path, dependency_type) in builder.read_stamp_file(stamp) {
869+
let dst = match dependency_type {
870+
DependencyType::Host => sysroot_host_dst,
871+
DependencyType::Target => sysroot_dst,
872+
DependencyType::TargetSelfContained => self_contained_dst,
873+
};
874+
builder.copy(&path, &dst.join(path.file_name().unwrap()));
819875
}
820876
}
821877

@@ -824,7 +880,7 @@ pub fn run_cargo(
824880
cargo: Cargo,
825881
tail_args: Vec<String>,
826882
stamp: &Path,
827-
additional_target_deps: Vec<PathBuf>,
883+
additional_target_deps: Vec<(PathBuf, DependencyType)>,
828884
is_check: bool,
829885
) -> Vec<PathBuf> {
830886
if builder.config.dry_run {
@@ -875,15 +931,15 @@ pub fn run_cargo(
875931
if filename.starts_with(&host_root_dir) {
876932
// Unless it's a proc macro used in the compiler
877933
if crate_types.iter().any(|t| t == "proc-macro") {
878-
deps.push((filename.to_path_buf(), true));
934+
deps.push((filename.to_path_buf(), DependencyType::Host));
879935
}
880936
continue;
881937
}
882938

883939
// If this was output in the `deps` dir then this is a precise file
884940
// name (hash included) so we start tracking it.
885941
if filename.starts_with(&target_deps_dir) {
886-
deps.push((filename.to_path_buf(), false));
942+
deps.push((filename.to_path_buf(), DependencyType::Target));
887943
continue;
888944
}
889945

@@ -935,17 +991,21 @@ pub fn run_cargo(
935991
let candidate = format!("{}.lib", path_to_add);
936992
let candidate = PathBuf::from(candidate);
937993
if candidate.exists() {
938-
deps.push((candidate, false));
994+
deps.push((candidate, DependencyType::Target));
939995
}
940996
}
941-
deps.push((path_to_add.into(), false));
997+
deps.push((path_to_add.into(), DependencyType::Target));
942998
}
943999

944-
deps.extend(additional_target_deps.into_iter().map(|d| (d, false)));
1000+
deps.extend(additional_target_deps);
9451001
deps.sort();
9461002
let mut new_contents = Vec::new();
947-
for (dep, proc_macro) in deps.iter() {
948-
new_contents.extend(if *proc_macro { b"h" } else { b"t" });
1003+
for (dep, dependency_type) in deps.iter() {
1004+
new_contents.extend(match *dependency_type {
1005+
DependencyType::Host => b"h",
1006+
DependencyType::Target => b"t",
1007+
DependencyType::TargetSelfContained => b"s",
1008+
});
9491009
new_contents.extend(dep.to_str().unwrap().as_bytes());
9501010
new_contents.extend(b"\0");
9511011
}

src/bootstrap/dist.rs

+19-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::channel;
2222
use crate::compile;
2323
use crate::tool::{self, Tool};
2424
use crate::util::{exe, is_dylib, timeit};
25-
use crate::{Compiler, Mode, LLVM_TOOLS};
25+
use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS};
2626
use time::{self, Timespec};
2727

2828
pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
@@ -306,7 +306,12 @@ fn make_win_dist(
306306
}
307307

308308
//Copy platform tools to platform-specific bin directory
309-
let target_bin_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("bin");
309+
let target_bin_dir = plat_root
310+
.join("lib")
311+
.join("rustlib")
312+
.join(target_triple)
313+
.join("bin")
314+
.join("self-contained");
310315
fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
311316
for src in target_tools {
312317
builder.copy_to_folder(&src, &target_bin_dir);
@@ -321,7 +326,12 @@ fn make_win_dist(
321326
);
322327

323328
//Copy platform libs to platform-specific lib directory
324-
let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib");
329+
let target_lib_dir = plat_root
330+
.join("lib")
331+
.join("rustlib")
332+
.join(target_triple)
333+
.join("lib")
334+
.join("self-contained");
325335
fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
326336
for src in target_libs {
327337
builder.copy_to_folder(&src, &target_lib_dir);
@@ -652,9 +662,13 @@ fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
652662
/// Copy stamped files into an image's `target/lib` directory.
653663
fn copy_target_libs(builder: &Builder<'_>, target: &str, image: &Path, stamp: &Path) {
654664
let dst = image.join("lib/rustlib").join(target).join("lib");
665+
let self_contained_dst = dst.join("self-contained");
655666
t!(fs::create_dir_all(&dst));
656-
for (path, host) in builder.read_stamp_file(stamp) {
657-
if !host || builder.config.build == target {
667+
t!(fs::create_dir_all(&self_contained_dst));
668+
for (path, dependency_type) in builder.read_stamp_file(stamp) {
669+
if dependency_type == DependencyType::TargetSelfContained {
670+
builder.copy(&path, &self_contained_dst.join(path.file_name().unwrap()));
671+
} else if dependency_type == DependencyType::Target || builder.config.build == target {
658672
builder.copy(&path, &dst.join(path.file_name().unwrap()));
659673
}
660674
}

src/bootstrap/lib.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,17 @@ impl Crate {
280280
}
281281
}
282282

283+
/// When building Rust various objects are handled differently.
284+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
285+
pub enum DependencyType {
286+
/// Libraries originating from proc-macros.
287+
Host,
288+
/// Typical Rust libraries.
289+
Target,
290+
/// Non Rust libraries and objects shipped to ease usage of certain targets.
291+
TargetSelfContained,
292+
}
293+
283294
/// The various "modes" of invoking Cargo.
284295
///
285296
/// These entries currently correspond to the various output directories of the
@@ -1097,7 +1108,7 @@ impl Build {
10971108
ret
10981109
}
10991110

1100-
fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, bool)> {
1111+
fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, DependencyType)> {
11011112
if self.config.dry_run {
11021113
return Vec::new();
11031114
}
@@ -1110,9 +1121,14 @@ impl Build {
11101121
if part.is_empty() {
11111122
continue;
11121123
}
1113-
let host = part[0] as char == 'h';
1124+
let dependency_type = match part[0] as char {
1125+
'h' => DependencyType::Host,
1126+
's' => DependencyType::TargetSelfContained,
1127+
't' => DependencyType::Target,
1128+
_ => unreachable!(),
1129+
};
11141130
let path = PathBuf::from(t!(str::from_utf8(&part[1..])));
1115-
paths.push((path, host));
1131+
paths.push((path, dependency_type));
11161132
}
11171133
paths
11181134
}

src/librustc_codegen_ssa/back/link.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,10 @@ fn get_object_file_path(sess: &Session, name: &str) -> PathBuf {
10751075
if file_path.exists() {
10761076
return file_path;
10771077
}
1078+
let file_path = fs.get_selfcontained_lib_path().join(name);
1079+
if file_path.exists() {
1080+
return file_path;
1081+
}
10781082
for search_path in fs.search_paths() {
10791083
let file_path = search_path.dir.join(name);
10801084
if file_path.exists() {
@@ -1470,6 +1474,9 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session) {
14701474
// The location of crates will be determined as needed.
14711475
let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();
14721476
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
1477+
1478+
let lib_path = sess.target_filesearch(PathKind::All).get_selfcontained_lib_path();
1479+
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
14731480
}
14741481

14751482
/// Add options making relocation sections in the produced ELF files read-only

0 commit comments

Comments
 (0)