Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/toolchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rustc_session::Session;

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

Expand Down
42 changes: 31 additions & 11 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -685,8 +685,9 @@ fn link_natively(
codegen_backend: &'static str,
) {
info!("preparing {:?} to {:?}", crate_type, out_filename);
let (linker_path, flavor) = linker_and_flavor(sess);
let self_contained_components = self_contained_components(sess, crate_type, &linker_path);
let self_contained_components = self_contained_components(sess, crate_type);
let (linker_path, flavor) =
linker_and_flavor(sess, self_contained_components.is_linker_enabled());

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

/// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
pub fn linker_and_flavor(sess: &Session, self_contained: bool) -> (PathBuf, LinkerFlavor) {
fn infer_from(
sess: &Session,
linker: Option<PathBuf>,
Expand Down Expand Up @@ -1413,6 +1414,15 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
return ret;
}

// FIXME: do it better
if sess.target.os == "windows"
&& sess.target.env == "gnu"
&& sess.target.abi == "llvm"
&& self_contained
{
return (PathBuf::from("rust-lld.exe"), LinkerFlavor::Gnu(Cc::No, Lld::Yes));
}

if let Some(ret) = infer_from(
sess,
sess.target.linker.as_deref().map(PathBuf::from),
Expand Down Expand Up @@ -1760,7 +1770,21 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
}

// Returns true if linker is located within sysroot
fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool {
fn detect_self_contained_mingw(sess: &Session) -> bool {
// FIXME: this sort of duplicates `infer_from()` inside `linker_and_flavor()`
let path_buf = sess
.opts
.cg
.linker
.as_ref()
.map(|l| l.as_path())
.or_else(|| sess.target.linker.as_ref().map(|linker| Path::new(linker.as_ref())));
let linker = if let Some(linker) = path_buf {
linker
} else {
return false;
};

// Assume `-C linker=rust-lld` as self-contained mode
if linker == Path::new("rust-lld") {
return true;
Expand All @@ -1772,7 +1796,7 @@ fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool {
};
for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
let full_path = dir.join(&linker_with_extension);
// If linker comes from sysroot assume self-contained mode
// If linker doesn't come from sysroot assume non-self-contained mode
if full_path.is_file() && !full_path.starts_with(sess.opts.sysroot.path()) {
return false;
}
Expand All @@ -1783,11 +1807,7 @@ fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool {
/// Various toolchain components used during linking are used from rustc distribution
/// instead of being found somewhere on the host system.
/// We only provide such support for a very limited number of targets.
fn self_contained_components(
sess: &Session,
crate_type: CrateType,
linker: &Path,
) -> LinkSelfContainedComponents {
fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfContainedComponents {
// Turn the backwards compatible bool values for `self_contained` into fully inferred
// `LinkSelfContainedComponents`.
let self_contained =
Expand Down Expand Up @@ -1816,7 +1836,7 @@ fn self_contained_components(
LinkSelfContainedDefault::InferredForMingw => {
sess.host == sess.target
&& sess.target.vendor != "uwp"
&& detect_self_contained_mingw(sess, linker)
&& detect_self_contained_mingw(sess)
}
}
};
Expand Down
15 changes: 10 additions & 5 deletions compiler/rustc_target/src/spec/base/windows_gnullvm.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::borrow::Cow;

use crate::spec::crt_objects::pre_mingw_self_contained;
use crate::spec::{
BinaryFormat, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions, cvs,
BinaryFormat, Cc, DebuginfoKind, LinkSelfContainedDefault, LinkerFlavor, Lld, SplitDebuginfo,
TargetOptions, add_link_args, cvs,
};

pub(crate) fn opts() -> TargetOptions {
Expand All @@ -14,10 +16,11 @@ pub(crate) fn opts() -> TargetOptions {
&["-nolibc", "--unwindlib=none"],
);
// Order of `late_link_args*` does not matter with LLD.
let late_link_args = TargetOptions::link_args(
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
&["-lmingw32", "-lmingwex", "-lmsvcrt", "-lkernel32", "-luser32"],
);
let mingw_libs = &["-lmingw32", "-lmingwex", "-lmsvcrt", "-lkernel32", "-luser32"];

let mut late_link_args =
TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs);
add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs);

TargetOptions {
os: "windows".into(),
Expand All @@ -35,6 +38,8 @@ pub(crate) fn opts() -> TargetOptions {
binary_format: BinaryFormat::Coff,
allows_weak_linkage: false,
pre_link_args,
pre_link_objects_self_contained: pre_mingw_self_contained(),
link_self_contained: LinkSelfContainedDefault::InferredForMingw,
late_link_args,
abi_return_struct_as_int: true,
emit_debug_gdb_scripts: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub(crate) fn target() -> Target {
base.features = "+cx16,+sse3,+sahf".into();
base.plt_by_default = false;
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &["-m", "i386pep"]);
base.max_atomic_width = Some(128);
base.linker = Some("x86_64-w64-mingw32-clang".into());

Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ fn copy_self_contained_objects(
DependencyType::TargetSelfContained,
);
}
} else if target.is_windows_gnu() {
} else if target.is_windows_gnu() || target.is_windows_gnullvm() {
for obj in ["crt2.o", "dllcrt2.o"].iter() {
let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
let dst = libdir_self_contained.join(obj);
Expand Down
48 changes: 46 additions & 2 deletions src/bootstrap/src/core/build_steps/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,44 @@ fn runtime_dll_dist(rust_root: &Path, target: TargetSelection, builder: &Builder
}
}

fn make_win_llvm_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
if builder.config.dry_run() {
return;
}

let (_, lib_path) = get_cc_search_dirs(target, builder);

// Libraries necessary to link the windows-gnu toolchains.
// System libraries will be preferred if they are available (see #67429).
let target_libs = [
// MinGW libs
"libunwind.a",
"libunwind.dll.a",
"libmingw32.a",
"libmingwex.a",
"libmsvcrt.a",
// Windows import libs, remove them once std transitions to raw-dylib
"libkernel32.a",
"libuser32.a",
"libntdll.a",
"libuserenv.a",
"libws2_32.a",
"libdbghelp.a",
];

//Find mingw artifacts we want to bundle
let target_libs = find_files(&target_libs, &lib_path);

//Copy platform libs to platform-specific lib directory
let plat_target_lib_self_contained_dir =
plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
fs::create_dir_all(&plat_target_lib_self_contained_dir)
.expect("creating plat_target_lib_self_contained_dir failed");
for src in target_libs {
builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
}
}

fn get_cc_search_dirs(
target: TargetSelection,
builder: &Builder<'_>,
Expand Down Expand Up @@ -394,14 +432,20 @@ impl Step for Mingw {

fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
let target = self.target;
if !target.ends_with("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
if !target.contains("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to myself: check the manifest. Probably forgot about it again.

return None;
}

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

make_win_dist(tarball.image_dir(), target, builder);
if target.ends_with("pc-windows-gnu") {
make_win_dist(tarball.image_dir(), target, builder);
} else if target.ends_with("pc-windows-gnullvm") {
make_win_llvm_dist(tarball.image_dir(), target, builder);
} else {
unreachable!();
}

Some(tarball.generate())
}
Expand Down
2 changes: 2 additions & 0 deletions src/bootstrap/src/core/builder/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,8 @@ impl Builder<'_> {
if let Mode::Rustc | Mode::ToolRustcPrivate | Mode::ToolBootstrap | Mode::ToolTarget = mode
{
rustflags.arg("--cfg=windows_raw_dylib");
} else if mode == Mode::Std && target.ends_with("gnullvm") {
rustflags.arg("--cfg=windows_raw_dylib");
}

if use_new_symbol_mangling {
Expand Down
4 changes: 4 additions & 0 deletions src/bootstrap/src/core/config/target_selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ impl TargetSelection {
self.ends_with("windows-gnu")
}

pub fn is_windows_gnullvm(&self) -> bool {
self.ends_with("windows-gnullvm")
}

pub fn is_cygwin(&self) -> bool {
self.is_windows() &&
// ref. https://cygwin.com/pipermail/cygwin/2022-February/250802.html
Expand Down
Loading