Skip to content

Commit fa81451

Browse files
Auto merge of #147536 - mati865:gnullvm-self-contained, r=<try>
Windows-gnullvm self-contained try-job: dist-x86_64-linux try-job: dist-x86_64-windows-gnullvm
2 parents 0b278a5 + 66b6bc0 commit fa81451

File tree

7 files changed

+95
-19
lines changed

7 files changed

+95
-19
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -685,8 +685,9 @@ fn link_natively(
685685
codegen_backend: &'static str,
686686
) {
687687
info!("preparing {:?} to {:?}", crate_type, out_filename);
688-
let (linker_path, flavor) = linker_and_flavor(sess);
689-
let self_contained_components = self_contained_components(sess, crate_type, &linker_path);
688+
let self_contained_components = self_contained_components(sess, crate_type);
689+
let (linker_path, flavor) =
690+
linker_and_flavor(sess, self_contained_components.is_linker_enabled());
690691

691692
// On AIX, we ship all libraries as .a big_af archive
692693
// the expected format is lib<name>.a(libname.so) for the actual
@@ -1314,7 +1315,7 @@ pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool
13141315
}
13151316

13161317
/// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
1317-
pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
1318+
pub fn linker_and_flavor(sess: &Session, self_contained: bool) -> (PathBuf, LinkerFlavor) {
13181319
fn infer_from(
13191320
sess: &Session,
13201321
linker: Option<PathBuf>,
@@ -1413,6 +1414,15 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
14131414
return ret;
14141415
}
14151416

1417+
// FIXME: do it better
1418+
if sess.target.os == "windows"
1419+
&& sess.target.env == "gnu"
1420+
&& sess.target.abi == "llvm"
1421+
&& self_contained
1422+
{
1423+
return (PathBuf::from("rust-lld.exe"), LinkerFlavor::Gnu(Cc::No, Lld::Yes));
1424+
}
1425+
14161426
if let Some(ret) = infer_from(
14171427
sess,
14181428
sess.target.linker.as_deref().map(PathBuf::from),
@@ -1760,7 +1770,21 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
17601770
}
17611771

17621772
// Returns true if linker is located within sysroot
1763-
fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool {
1773+
fn detect_self_contained_mingw(sess: &Session) -> bool {
1774+
// FIXME: this sort of duplicates `infer_from()` inside `linker_and_flavor()`
1775+
let path_buf = sess
1776+
.opts
1777+
.cg
1778+
.linker
1779+
.as_ref()
1780+
.map(|l| l.as_path())
1781+
.or_else(|| sess.target.linker.as_ref().map(|linker| Path::new(linker.as_ref())));
1782+
let linker = if let Some(linker) = path_buf {
1783+
linker
1784+
} else {
1785+
return false;
1786+
};
1787+
17641788
// Assume `-C linker=rust-lld` as self-contained mode
17651789
if linker == Path::new("rust-lld") {
17661790
return true;
@@ -1772,7 +1796,7 @@ fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool {
17721796
};
17731797
for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
17741798
let full_path = dir.join(&linker_with_extension);
1775-
// If linker comes from sysroot assume self-contained mode
1799+
// If linker doesn't come from sysroot assume non-self-contained mode
17761800
if full_path.is_file() && !full_path.starts_with(sess.opts.sysroot.path()) {
17771801
return false;
17781802
}
@@ -1783,11 +1807,7 @@ fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool {
17831807
/// Various toolchain components used during linking are used from rustc distribution
17841808
/// instead of being found somewhere on the host system.
17851809
/// We only provide such support for a very limited number of targets.
1786-
fn self_contained_components(
1787-
sess: &Session,
1788-
crate_type: CrateType,
1789-
linker: &Path,
1790-
) -> LinkSelfContainedComponents {
1810+
fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfContainedComponents {
17911811
// Turn the backwards compatible bool values for `self_contained` into fully inferred
17921812
// `LinkSelfContainedComponents`.
17931813
let self_contained =
@@ -1816,7 +1836,7 @@ fn self_contained_components(
18161836
LinkSelfContainedDefault::InferredForMingw => {
18171837
sess.host == sess.target
18181838
&& sess.target.vendor != "uwp"
1819-
&& detect_self_contained_mingw(sess, linker)
1839+
&& detect_self_contained_mingw(sess)
18201840
}
18211841
}
18221842
};

compiler/rustc_target/src/spec/base/windows_gnullvm.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use std::borrow::Cow;
22

3+
use crate::spec::crt_objects::pre_mingw_self_contained;
34
use crate::spec::{
4-
BinaryFormat, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions, cvs,
5+
BinaryFormat, Cc, DebuginfoKind, LinkSelfContainedDefault, LinkerFlavor, Lld, SplitDebuginfo,
6+
TargetOptions, add_link_args, cvs,
57
};
68

79
pub(crate) fn opts() -> TargetOptions {
@@ -14,10 +16,11 @@ pub(crate) fn opts() -> TargetOptions {
1416
&["-nolibc", "--unwindlib=none"],
1517
);
1618
// Order of `late_link_args*` does not matter with LLD.
17-
let late_link_args = TargetOptions::link_args(
18-
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
19-
&["-lmingw32", "-lmingwex", "-lmsvcrt", "-lkernel32", "-luser32"],
20-
);
19+
let mingw_libs = &["-lmingw32", "-lmingwex", "-lmsvcrt", "-lkernel32", "-luser32"];
20+
21+
let mut late_link_args =
22+
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs);
23+
add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs);
2124

2225
TargetOptions {
2326
os: "windows".into(),
@@ -35,6 +38,8 @@ pub(crate) fn opts() -> TargetOptions {
3538
binary_format: BinaryFormat::Coff,
3639
allows_weak_linkage: false,
3740
pre_link_args,
41+
pre_link_objects_self_contained: pre_mingw_self_contained(),
42+
link_self_contained: LinkSelfContainedDefault::InferredForMingw,
3843
late_link_args,
3944
abi_return_struct_as_int: true,
4045
emit_debug_gdb_scripts: false,

compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub(crate) fn target() -> Target {
66
base.features = "+cx16,+sse3,+sahf".into();
77
base.plt_by_default = false;
88
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
9+
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &["-m", "i386pep"]);
910
base.max_atomic_width = Some(128);
1011
base.linker = Some("x86_64-w64-mingw32-clang".into());
1112

src/bootstrap/src/core/build_steps/compile.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ fn copy_self_contained_objects(
450450
DependencyType::TargetSelfContained,
451451
);
452452
}
453-
} else if target.is_windows_gnu() {
453+
} else if target.is_windows_gnu() || target.is_windows_gnullvm() {
454454
for obj in ["crt2.o", "dllcrt2.o"].iter() {
455455
let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
456456
let dst = libdir_self_contained.join(obj);

src/bootstrap/src/core/build_steps/dist.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,44 @@ fn runtime_dll_dist(rust_root: &Path, target: TargetSelection, builder: &Builder
344344
}
345345
}
346346

347+
fn make_win_llvm_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
348+
if builder.config.dry_run() {
349+
return;
350+
}
351+
352+
let (_, lib_path) = get_cc_search_dirs(target, builder);
353+
354+
// Libraries necessary to link the windows-gnu toolchains.
355+
// System libraries will be preferred if they are available (see #67429).
356+
let target_libs = [
357+
// MinGW libs
358+
"libunwind.a",
359+
"libunwind.dll.a",
360+
"libmingw32.a",
361+
"libmingwex.a",
362+
"libmsvcrt.a",
363+
// Windows import libs, remove them once std transitions to raw-dylib
364+
"libkernel32.a",
365+
"libuser32.a",
366+
"libntdll.a",
367+
"libuserenv.a",
368+
"libws2_32.a",
369+
"libdbghelp.a",
370+
];
371+
372+
//Find mingw artifacts we want to bundle
373+
let target_libs = find_files(&target_libs, &lib_path);
374+
375+
//Copy platform libs to platform-specific lib directory
376+
let plat_target_lib_self_contained_dir =
377+
plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
378+
fs::create_dir_all(&plat_target_lib_self_contained_dir)
379+
.expect("creating plat_target_lib_self_contained_dir failed");
380+
for src in target_libs {
381+
builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
382+
}
383+
}
384+
347385
fn get_cc_search_dirs(
348386
target: TargetSelection,
349387
builder: &Builder<'_>,
@@ -394,14 +432,20 @@ impl Step for Mingw {
394432

395433
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
396434
let target = self.target;
397-
if !target.ends_with("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
435+
if !target.contains("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
398436
return None;
399437
}
400438

401439
let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple);
402440
tarball.set_product_name("Rust MinGW");
403441

404-
make_win_dist(tarball.image_dir(), target, builder);
442+
if target.ends_with("pc-windows-gnu") {
443+
make_win_dist(tarball.image_dir(), target, builder);
444+
} else if target.ends_with("pc-windows-gnullvm") {
445+
make_win_llvm_dist(tarball.image_dir(), target, builder);
446+
} else {
447+
unreachable!();
448+
}
405449

406450
Some(tarball.generate())
407451
}

src/bootstrap/src/core/builder/cargo.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,8 @@ impl Builder<'_> {
646646
if let Mode::Rustc | Mode::ToolRustcPrivate | Mode::ToolBootstrap | Mode::ToolTarget = mode
647647
{
648648
rustflags.arg("--cfg=windows_raw_dylib");
649+
} else if mode == Mode::Std && target.ends_with("gnullvm") {
650+
rustflags.arg("--cfg=windows_raw_dylib");
649651
}
650652

651653
if use_new_symbol_mangling {

src/bootstrap/src/core/config/target_selection.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ impl TargetSelection {
8686
self.ends_with("windows-gnu")
8787
}
8888

89+
pub fn is_windows_gnullvm(&self) -> bool {
90+
self.ends_with("windows-gnullvm")
91+
}
92+
8993
pub fn is_cygwin(&self) -> bool {
9094
self.is_windows() &&
9195
// ref. https://cygwin.com/pipermail/cygwin/2022-February/250802.html

0 commit comments

Comments
 (0)