/// need out of the shared crate context before we get rid of it.
use rustc_session::{filesearch, Session};
use rustc_span::symbol::Symbol;
-use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
+use rustc_target::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelroLevel};
use super::archive::ArchiveBuilder;
use super::command::Command;
// To comply with the Windows App Certification Kit,
// MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
let t = &sess.target.target;
- if flavor == LinkerFlavor::Msvc && t.target_vendor == "uwp" {
+ if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
+ && t.target_vendor == "uwp"
+ {
if let Some(ref tool) = msvc_tool {
let original_path = tool.path();
if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::windows_msvc_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);
- // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
- // space available to x86 Windows binaries on x86_64.
- base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push("/LARGEADDRESSAWARE".to_string());
-
- // Ensure the linker will only produce an image if it can also produce a table of
- // the image's safe exception handlers.
- // https://docs.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers
- base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push("/SAFESEH".to_string());
+ let pre_link_args_msvc = vec![
+ // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
+ // space available to x86 Windows binaries on x86_64.
+ "/LARGEADDRESSAWARE".to_string(),
+ // Ensure the linker will only produce an image if it can also produce a table of
+ // the image's safe exception handlers.
+ // https://docs.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers
+ "/SAFESEH".to_string(),
+ ];
+ base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone());
+ base.pre_link_args
+ .get_mut(&LinkerFlavor::Lld(LldFlavor::Link))
+ .unwrap()
+ .extend(pre_link_args_msvc);
Ok(Target {
llvm_target: "i686-pc-windows-msvc".to_string(),
// Target on this testing platform (i.e., checking the iOS targets
// only on a Mac test platform).
let _ = $module::target().map(|original| {
+ original.check_consistency();
let as_json = original.to_json();
let parsed = Target::from_json(as_json).unwrap();
assert_eq!(original, parsed);
pub arch: String,
/// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
pub data_layout: String,
- /// Linker flavor
+ /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
+ /// on the command line.
pub linker_flavor: LinkerFlavor,
/// Optional settings with defaults.
pub options: TargetOptions,
/// Linker to invoke
pub linker: Option<String>,
- /// LLD flavor
+ /// LLD flavor used if `lld` (or `rust-lld`) is specified as a linker
+ /// without clarifying its flavor in any way.
pub lld_flavor: LldFlavor,
/// Linker arguments that are passed *before* any user-defined libraries.
}
}
}
+
+ #[cfg(test)]
+ fn check_consistency(&self) {
+ // Check that LLD with the given flavor is treated identically to the linker it emulates.
+ // If you target really needs to deviate from the rules below, whitelist it
+ // and document the reasons.
+ assert_eq!(
+ self.linker_flavor == LinkerFlavor::Msvc
+ || self.linker_flavor == LinkerFlavor::Lld(LldFlavor::Link),
+ self.options.lld_flavor == LldFlavor::Link,
+ );
+ for args in &[
+ &self.options.pre_link_args,
+ &self.options.pre_link_args_crt,
+ &self.options.late_link_args,
+ &self.options.late_link_args_dynamic,
+ &self.options.late_link_args_static,
+ &self.options.post_link_args,
+ ] {
+ assert_eq!(
+ args.get(&LinkerFlavor::Msvc),
+ args.get(&LinkerFlavor::Lld(LldFlavor::Link)),
+ );
+ if args.contains_key(&LinkerFlavor::Msvc) {
+ assert_eq!(self.options.lld_flavor, LldFlavor::Link);
+ }
+ }
+ }
}
impl ToJson for Target {
-use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::windows_msvc_base::opts();
// should be smart enough to insert branch islands only
// where necessary, but this is not the observed behavior.
// Disabling the LBR optimization works around the issue.
- base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push("/OPT:NOLBR".to_string());
+ let pre_link_args_msvc = "/OPT:NOLBR".to_string();
+ base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push(pre_link_args_msvc.clone());
+ base.pre_link_args
+ .get_mut(&LinkerFlavor::Lld(LldFlavor::Link))
+ .unwrap()
+ .push(pre_link_args_msvc);
// FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
// implemented for windows/arm in LLVM
use std::default::Default;
pub fn opts() -> TargetOptions {
+ let pre_link_args_msvc = vec![
+ // Suppress the verbose logo and authorship debugging output, which would needlessly
+ // clog any log files.
+ "/NOLOGO".to_string(),
+ // UEFI is fully compatible to non-executable data pages. Tell the compiler that
+ // non-code sections can be marked as non-executable, including stack pages. In fact,
+ // firmware might enforce this, so we better let the linker know about this, so it
+ // will fail if the compiler ever tries placing code on the stack (e.g., trampoline
+ // constructs and alike).
+ "/NXCOMPAT".to_string(),
+ // There is no runtime for UEFI targets, prevent them from being linked. UEFI targets
+ // must be freestanding.
+ "/nodefaultlib".to_string(),
+ // Non-standard subsystems have no default entry-point in PE+ files. We have to define
+ // one. "efi_main" seems to be a common choice amongst other implementations and the
+ // spec.
+ "/entry:efi_main".to_string(),
+ // COFF images have a "Subsystem" field in their header, which defines what kind of
+ // program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION,
+ // EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION,
+ // which is very likely the most common option. Individual projects can override this
+ // with custom linker flags.
+ // The subsystem-type only has minor effects on the application. It defines the memory
+ // regions the application is loaded into (runtime-drivers need to be put into
+ // reserved areas), as well as whether a return from the entry-point is treated as
+ // exit (default for applications).
+ "/subsystem:efi_application".to_string(),
+ ];
let mut pre_link_args = LinkArgs::new();
-
- pre_link_args.insert(
- LinkerFlavor::Lld(LldFlavor::Link),
- vec![
- // Suppress the verbose logo and authorship debugging output, which would needlessly
- // clog any log files.
- "/NOLOGO".to_string(),
- // UEFI is fully compatible to non-executable data pages. Tell the compiler that
- // non-code sections can be marked as non-executable, including stack pages. In fact,
- // firmware might enforce this, so we better let the linker know about this, so it
- // will fail if the compiler ever tries placing code on the stack (e.g., trampoline
- // constructs and alike).
- "/NXCOMPAT".to_string(),
- // There is no runtime for UEFI targets, prevent them from being linked. UEFI targets
- // must be freestanding.
- "/nodefaultlib".to_string(),
- // Non-standard subsystems have no default entry-point in PE+ files. We have to define
- // one. "efi_main" seems to be a common choice amongst other implementations and the
- // spec.
- "/entry:efi_main".to_string(),
- // COFF images have a "Subsystem" field in their header, which defines what kind of
- // program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION,
- // EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION,
- // which is very likely the most common option. Individual projects can override this
- // with custom linker flags.
- // The subsystem-type only has minor effects on the application. It defines the memory
- // regions the application is loaded into (runtime-drivers need to be put into
- // reserved areas), as well as whether a return from the entry-point is treated as
- // exit (default for applications).
- "/subsystem:efi_application".to_string(),
- ],
- );
+ pre_link_args.insert(LinkerFlavor::Msvc, pre_link_args_msvc.clone());
+ pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Link), pre_link_args_msvc);
TargetOptions {
dynamic_linking: false,
use std::default::Default;
pub fn opts() -> TargetOptions {
- let pre_args = vec!["/NOLOGO".to_string(), "/NXCOMPAT".to_string()];
- let mut args = LinkArgs::new();
- args.insert(LinkerFlavor::Msvc, pre_args.clone());
- args.insert(LinkerFlavor::Lld(LldFlavor::Link), pre_args);
+ let pre_link_args_msvc = vec!["/NOLOGO".to_string(), "/NXCOMPAT".to_string()];
+ let mut pre_link_args = LinkArgs::new();
+ pre_link_args.insert(LinkerFlavor::Msvc, pre_link_args_msvc.clone());
+ pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Link), pre_link_args_msvc);
TargetOptions {
function_sections: true,
// messages if a link error occurred.
link_env: vec![("VSLANG".to_string(), "1033".to_string())],
lld_flavor: LldFlavor::Link,
- pre_link_args: args,
+ pre_link_args,
crt_static_allows_dylibs: true,
crt_static_respected: true,
abi_return_struct_as_int: true,
-use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
+use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, TargetOptions};
use std::default::Default;
pub fn opts() -> TargetOptions {
- let mut args = LinkArgs::new();
- args.insert(
- LinkerFlavor::Msvc,
- vec![
- "/NOLOGO".to_string(),
- "/NXCOMPAT".to_string(),
- "/APPCONTAINER".to_string(),
- "mincore.lib".to_string(),
- ],
- );
+ let pre_link_args_msvc = vec![
+ "/NOLOGO".to_string(),
+ "/NXCOMPAT".to_string(),
+ "/APPCONTAINER".to_string(),
+ "mincore.lib".to_string(),
+ ];
+ let mut pre_link_args = LinkArgs::new();
+ pre_link_args.insert(LinkerFlavor::Msvc, pre_link_args_msvc.clone());
+ pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Link), pre_link_args_msvc);
TargetOptions {
function_sections: true,
target_family: Some("windows".to_string()),
is_like_windows: true,
is_like_msvc: true,
- pre_link_args: args,
+ pre_link_args,
crt_static_allows_dylibs: true,
crt_static_respected: true,
abi_return_struct_as_int: true,
emit_debug_gdb_scripts: false,
requires_uwtable: true,
+ lld_flavor: LldFlavor::Link,
..Default::default()
}