Skip to content

Commit da8dd69

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 2fcbda6 + 2b5ac0b commit da8dd69

File tree

8 files changed

+108
-28
lines changed

8 files changed

+108
-28
lines changed

compiler/rustc_codegen_cranelift/src/toolchain.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ use std::path::PathBuf;
44

55
use rustc_codegen_ssa::back::link::linker_and_flavor;
66
use rustc_session::Session;
7+
use rustc_target::spec::LinkSelfContainedComponents;
78

89
/// Tries to infer the path of a binary for the target toolchain from the linker name.
910
pub(crate) fn get_toolchain_binary(sess: &Session, tool: &str) -> PathBuf {
10-
let (mut linker, _linker_flavor) = linker_and_flavor(sess);
11+
let (mut linker, _linker_flavor) =
12+
linker_and_flavor(sess, &LinkSelfContainedComponents::empty());
1113
let linker_file_name =
1214
linker.file_name().unwrap().to_str().expect("linker filename should be valid UTF-8");
1315

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -685,8 +685,8 @@ 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) = linker_and_flavor(sess, &self_contained_components);
690690

691691
// On AIX, we ship all libraries as .a big_af archive
692692
// the expected format is lib<name>.a(libname.so) for the actual
@@ -1318,7 +1318,10 @@ pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool
13181318
}
13191319

13201320
/// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
1321-
pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
1321+
pub fn linker_and_flavor(
1322+
sess: &Session,
1323+
self_contained_components: &LinkSelfContainedComponents,
1324+
) -> (PathBuf, LinkerFlavor) {
13221325
fn infer_from(
13231326
sess: &Session,
13241327
linker: Option<PathBuf>,
@@ -1415,6 +1418,18 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
14151418
return ret;
14161419
}
14171420

1421+
// When using a supported target in self-contained linker mode, we want to use rust-lld directly.
1422+
let self_contained_target = sess.target.os == Os::Windows
1423+
&& sess.target.env == Env::Gnu
1424+
&& sess.target.abi == Abi::Llvm
1425+
&& self_contained_components.is_linker_enabled();
1426+
if self_contained_target
1427+
&& let Some(ret) =
1428+
infer_from(sess, None, Some(LinkerFlavor::Gnu(Cc::No, Lld::Yes)), features)
1429+
{
1430+
return ret;
1431+
}
1432+
14181433
if let Some(ret) = infer_from(
14191434
sess,
14201435
sess.target.linker.as_deref().map(PathBuf::from),
@@ -1761,20 +1776,34 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
17611776
}
17621777
}
17631778

1764-
// Returns true if linker is located within sysroot
1765-
fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool {
1766-
// Assume `-C linker=rust-lld` as self-contained mode
1767-
if linker == Path::new("rust-lld") {
1768-
return true;
1779+
/// Returns true if linker is shipped by Rust.
1780+
// There are currently two different solutions for self-contained mode with mingw-w64:
1781+
// using rust-lld directly (`-gnullvm`) or using shipped cc to call the linker (`-gnu`).
1782+
// Eventually, `-gnu` toolchains might be moved to calling the linker directly.
1783+
fn detect_self_contained_mingw(sess: &Session) -> bool {
1784+
// Passing custom linker means non-self-contained mode.
1785+
if sess.opts.cg.linker.is_some() {
1786+
// Unless running on `-windows-gnu-llvm` and using `-C linker=rust-lld`.
1787+
if sess.target.abi == Abi::Llvm {
1788+
return sess
1789+
.opts
1790+
.cg
1791+
.linker
1792+
.as_ref()
1793+
.is_some_and(|linker| linker == Path::new("rust-lld"));
1794+
}
1795+
1796+
return false;
17691797
}
1770-
let linker_with_extension = if cfg!(windows) && linker.extension().is_none() {
1798+
1799+
let linker_with_extension = if let Some(linker) = sess.target.linker.as_deref().map(Path::new) {
17711800
linker.with_extension("exe")
17721801
} else {
1773-
linker.to_path_buf()
1802+
return false;
17741803
};
17751804
for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
17761805
let full_path = dir.join(&linker_with_extension);
1777-
// If linker comes from sysroot assume self-contained mode
1806+
// If linker doesn't come from sysroot assume non-self-contained mode
17781807
if full_path.is_file() && !full_path.starts_with(sess.opts.sysroot.path()) {
17791808
return false;
17801809
}
@@ -1785,11 +1814,7 @@ fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool {
17851814
/// Various toolchain components used during linking are used from rustc distribution
17861815
/// instead of being found somewhere on the host system.
17871816
/// We only provide such support for a very limited number of targets.
1788-
fn self_contained_components(
1789-
sess: &Session,
1790-
crate_type: CrateType,
1791-
linker: &Path,
1792-
) -> LinkSelfContainedComponents {
1817+
fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfContainedComponents {
17931818
// Turn the backwards compatible bool values for `self_contained` into fully inferred
17941819
// `LinkSelfContainedComponents`.
17951820
let self_contained =
@@ -1818,7 +1843,7 @@ fn self_contained_components(
18181843
LinkSelfContainedDefault::InferredForMingw => {
18191844
sess.host == sess.target
18201845
&& sess.target.abi != Abi::Uwp
1821-
&& detect_self_contained_mingw(sess, linker)
1846+
&& detect_self_contained_mingw(sess)
18221847
}
18231848
}
18241849
};

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

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

3+
use crate::spec::crt_objects::pre_mingw_self_contained;
34
use crate::spec::{
4-
Abi, BinaryFormat, Cc, DebuginfoKind, Env, LinkerFlavor, Lld, Os, SplitDebuginfo,
5-
TargetOptions, cvs,
5+
Abi, BinaryFormat, Cc, DebuginfoKind, Env, LinkSelfContainedDefault, LinkerFlavor, Lld, Os,
6+
SplitDebuginfo, TargetOptions, add_link_args, cvs,
67
};
78

89
pub(crate) fn opts() -> TargetOptions {
@@ -15,10 +16,11 @@ pub(crate) fn opts() -> TargetOptions {
1516
&["-nolibc", "--unwindlib=none"],
1617
);
1718
// Order of `late_link_args*` does not matter with LLD.
18-
let late_link_args = TargetOptions::link_args(
19-
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
20-
&["-lmingw32", "-lmingwex", "-lmsvcrt", "-lkernel32", "-luser32"],
21-
);
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);
2224

2325
TargetOptions {
2426
os: Os::Windows,
@@ -36,6 +38,8 @@ pub(crate) fn opts() -> TargetOptions {
3638
binary_format: BinaryFormat::Coff,
3739
allows_weak_linkage: false,
3840
pre_link_args,
41+
pre_link_objects_self_contained: pre_mingw_self_contained(),
42+
link_self_contained: LinkSelfContainedDefault::InferredForMingw,
3943
late_link_args,
4044
abi_return_struct_as_int: true,
4145
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
@@ -448,7 +448,7 @@ fn copy_self_contained_objects(
448448
DependencyType::TargetSelfContained,
449449
);
450450
}
451-
} else if target.is_windows_gnu() {
451+
} else if target.is_windows_gnu() || target.is_windows_gnullvm() {
452452
for obj in ["crt2.o", "dllcrt2.o"].iter() {
453453
let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
454454
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-gnullvm 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/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

src/tools/build-manifest/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ impl Builder {
476476
}
477477
// so is rust-mingw if it's available for the target
478478
PkgType::RustMingw => {
479-
if host.ends_with("pc-windows-gnu") {
479+
if host.contains("pc-windows-gnu") {
480480
components.push(host_component(pkg));
481481
}
482482
}

0 commit comments

Comments
 (0)