2019-12-22 17:42:04 -05:00
|
|
|
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
|
2019-09-10 09:53:59 +03:00
|
|
|
use std::env;
|
|
|
|
|
use std::io;
|
|
|
|
|
use std::path::Path;
|
|
|
|
|
use std::process::Command;
|
2015-01-08 10:19:52 +02:00
|
|
|
|
2019-02-08 21:00:07 +09:00
|
|
|
use Arch::*;
|
2015-01-08 10:19:52 +02:00
|
|
|
#[allow(non_camel_case_types)]
|
2015-03-30 09:38:44 -04:00
|
|
|
#[derive(Copy, Clone)]
|
2015-01-08 10:19:52 +02:00
|
|
|
pub enum Arch {
|
|
|
|
|
Armv7,
|
|
|
|
|
Armv7s,
|
|
|
|
|
Arm64,
|
|
|
|
|
I386,
|
2019-08-11 20:31:01 +02:00
|
|
|
X86_64,
|
|
|
|
|
X86_64_macabi,
|
2015-01-08 10:19:52 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-14 16:05:45 -08:00
|
|
|
#[allow(non_camel_case_types)]
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
|
pub enum AppleOS {
|
|
|
|
|
tvOS,
|
|
|
|
|
iOS,
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-08 10:19:52 +02:00
|
|
|
impl Arch {
|
2018-08-09 15:42:43 +02:00
|
|
|
pub fn to_string(self) -> &'static str {
|
2015-01-08 10:19:52 +02:00
|
|
|
match self {
|
2018-08-09 15:42:43 +02:00
|
|
|
Armv7 => "armv7",
|
|
|
|
|
Armv7s => "armv7s",
|
|
|
|
|
Arm64 => "arm64",
|
|
|
|
|
I386 => "i386",
|
2019-08-11 20:31:01 +02:00
|
|
|
X86_64 => "x86_64",
|
2019-12-22 17:42:04 -05:00
|
|
|
X86_64_macabi => "x86_64",
|
2015-01-08 10:19:52 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-10 09:53:59 +03:00
|
|
|
pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
|
|
|
|
|
// Following what clang does
|
|
|
|
|
// (https://github.com/llvm/llvm-project/blob/
|
|
|
|
|
// 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
|
|
|
|
|
// to allow the SDK path to be set. (For clang, xcrun sets
|
|
|
|
|
// SDKROOT; for rustc, the user or build system can set it, or we
|
|
|
|
|
// can fall back to checking for xcrun on PATH.)
|
2020-03-21 12:50:22 +01:00
|
|
|
if let Ok(sdkroot) = env::var("SDKROOT") {
|
2019-09-12 15:23:59 +03:00
|
|
|
let p = Path::new(&sdkroot);
|
|
|
|
|
match sdk_name {
|
|
|
|
|
// Ignore `SDKROOT` if it's clearly set for the wrong platform.
|
2020-02-14 16:05:45 -08:00
|
|
|
"appletvos"
|
|
|
|
|
if sdkroot.contains("TVSimulator.platform")
|
2020-03-21 15:06:04 +01:00
|
|
|
|| sdkroot.contains("MacOSX.platform") => {}
|
2020-02-14 16:05:45 -08:00
|
|
|
"appletvsimulator"
|
2020-03-21 15:06:04 +01:00
|
|
|
if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => {}
|
2019-12-22 17:42:04 -05:00
|
|
|
"iphoneos"
|
|
|
|
|
if sdkroot.contains("iPhoneSimulator.platform")
|
2020-03-21 15:06:04 +01:00
|
|
|
|| sdkroot.contains("MacOSX.platform") => {}
|
2019-12-22 17:42:04 -05:00
|
|
|
"iphonesimulator"
|
2020-03-21 15:06:04 +01:00
|
|
|
if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => {
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
|
|
|
|
"macosx10.15"
|
|
|
|
|
if sdkroot.contains("iPhoneOS.platform")
|
2020-03-21 15:06:04 +01:00
|
|
|
|| sdkroot.contains("iPhoneSimulator.platform") => {}
|
2019-09-12 15:23:59 +03:00
|
|
|
// Ignore `SDKROOT` if it's not a valid path.
|
2020-03-21 15:06:04 +01:00
|
|
|
_ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
|
2019-09-12 15:23:59 +03:00
|
|
|
_ => return Ok(sdkroot),
|
2019-09-10 09:53:59 +03:00
|
|
|
}
|
|
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
let res =
|
|
|
|
|
Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
|
|
|
|
|
|output| {
|
|
|
|
|
if output.status.success() {
|
|
|
|
|
Ok(String::from_utf8(output.stdout).unwrap())
|
|
|
|
|
} else {
|
|
|
|
|
let error = String::from_utf8(output.stderr);
|
|
|
|
|
let error = format!("process exit with error: {}", error.unwrap());
|
|
|
|
|
Err(io::Error::new(io::ErrorKind::Other, &error[..]))
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
);
|
2019-09-10 09:53:59 +03:00
|
|
|
|
|
|
|
|
match res {
|
|
|
|
|
Ok(output) => Ok(output.trim().to_string()),
|
2019-12-22 17:42:04 -05:00
|
|
|
Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
|
2019-09-10 09:53:59 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-14 16:05:45 -08:00
|
|
|
fn build_pre_link_args(arch: Arch, os: AppleOS) -> Result<LinkArgs, String> {
|
|
|
|
|
let sdk_name = match (arch, os) {
|
2020-02-20 10:16:32 -08:00
|
|
|
(Arm64, AppleOS::tvOS) => "appletvos",
|
|
|
|
|
(X86_64, AppleOS::tvOS) => "appletvsimulator",
|
|
|
|
|
(Armv7, AppleOS::iOS) => "iphoneos",
|
|
|
|
|
(Armv7s, AppleOS::iOS) => "iphoneos",
|
|
|
|
|
(Arm64, AppleOS::iOS) => "iphoneos",
|
|
|
|
|
(I386, AppleOS::iOS) => "iphonesimulator",
|
|
|
|
|
(X86_64, AppleOS::iOS) => "iphonesimulator",
|
|
|
|
|
(X86_64_macabi, AppleOS::iOS) => "macosx10.15",
|
2020-02-14 16:05:45 -08:00
|
|
|
_ => unreachable!(),
|
2015-01-08 10:19:52 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let arch_name = arch.to_string();
|
|
|
|
|
|
2019-09-10 09:53:59 +03:00
|
|
|
let sdk_root = get_sdk_root(sdk_name)?;
|
|
|
|
|
|
-Z linker-flavor
This patch adds a `-Z linker-flavor` flag to rustc which can be used to invoke
the linker using a different interface.
For example, by default rustc assumes that all the Linux targets will be linked
using GCC. This makes it impossible to use LLD as a linker using just `-C
linker=ld.lld` because that will invoke LLD with invalid command line
arguments. (e.g. rustc will pass -Wl,--gc-sections to LLD but LLD doesn't
understand that; --gc-sections would be the right argument)
With this patch one can pass `-Z linker-flavor=ld` to rustc to invoke the linker
using a LD-like interface. This way, `rustc -C linker=ld.lld -Z
linker-flavor=ld` will invoke LLD with the right arguments.
`-Z linker-flavor` accepts 4 different arguments: `em` (emcc), `ld`,
`gcc`, `msvc` (link.exe). `em`, `gnu` and `msvc` cover all the existing linker
interfaces. `ld` is a new flavor for interfacing GNU's ld and LLD.
This patch also changes target specifications. `linker-flavor` is now a
mandatory field that specifies the *default* linker flavor that the target will
use. This change also makes the linker interface *explicit*; before, it used to
be derived from other fields like linker-is-gnu, is-like-msvc,
is-like-emscripten, etc.
Another change to target specifications is that the fields `pre-link-args`,
`post-link-args` and `late-link-args` now expect a map from flavor to linker
arguments.
``` diff
- "pre-link-args": ["-Wl,--as-needed", "-Wl,-z,-noexecstack"],
+ "pre-link-args": {
+ "gcc": ["-Wl,--as-needed", "-Wl,-z,-noexecstack"],
+ "ld": ["--as-needed", "-z,-noexecstack"],
+ },
```
[breaking-change] for users of custom targets specifications
2017-02-21 14:47:15 -05:00
|
|
|
let mut args = LinkArgs::new();
|
2019-12-22 17:42:04 -05:00
|
|
|
args.insert(
|
|
|
|
|
LinkerFlavor::Gcc,
|
|
|
|
|
vec![
|
|
|
|
|
"-arch".to_string(),
|
|
|
|
|
arch_name.to_string(),
|
|
|
|
|
"-isysroot".to_string(),
|
|
|
|
|
sdk_root.clone(),
|
|
|
|
|
"-Wl,-syslibroot".to_string(),
|
|
|
|
|
sdk_root,
|
|
|
|
|
],
|
|
|
|
|
);
|
-Z linker-flavor
This patch adds a `-Z linker-flavor` flag to rustc which can be used to invoke
the linker using a different interface.
For example, by default rustc assumes that all the Linux targets will be linked
using GCC. This makes it impossible to use LLD as a linker using just `-C
linker=ld.lld` because that will invoke LLD with invalid command line
arguments. (e.g. rustc will pass -Wl,--gc-sections to LLD but LLD doesn't
understand that; --gc-sections would be the right argument)
With this patch one can pass `-Z linker-flavor=ld` to rustc to invoke the linker
using a LD-like interface. This way, `rustc -C linker=ld.lld -Z
linker-flavor=ld` will invoke LLD with the right arguments.
`-Z linker-flavor` accepts 4 different arguments: `em` (emcc), `ld`,
`gcc`, `msvc` (link.exe). `em`, `gnu` and `msvc` cover all the existing linker
interfaces. `ld` is a new flavor for interfacing GNU's ld and LLD.
This patch also changes target specifications. `linker-flavor` is now a
mandatory field that specifies the *default* linker flavor that the target will
use. This change also makes the linker interface *explicit*; before, it used to
be derived from other fields like linker-is-gnu, is-like-msvc,
is-like-emscripten, etc.
Another change to target specifications is that the fields `pre-link-args`,
`post-link-args` and `late-link-args` now expect a map from flavor to linker
arguments.
``` diff
- "pre-link-args": ["-Wl,--as-needed", "-Wl,-z,-noexecstack"],
+ "pre-link-args": {
+ "gcc": ["-Wl,--as-needed", "-Wl,-z,-noexecstack"],
+ "ld": ["--as-needed", "-z,-noexecstack"],
+ },
```
[breaking-change] for users of custom targets specifications
2017-02-21 14:47:15 -05:00
|
|
|
|
|
|
|
|
Ok(args)
|
2015-01-08 10:19:52 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-11 12:11:44 +01:00
|
|
|
fn target_cpu(arch: Arch) -> String {
|
|
|
|
|
match arch {
|
2015-02-12 19:15:36 +02:00
|
|
|
Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
|
|
|
|
|
Armv7s => "cortex-a9",
|
2020-06-07 11:23:15 +04:00
|
|
|
Arm64 => "apple-a7",
|
2015-08-11 12:05:36 -07:00
|
|
|
I386 => "yonah",
|
|
|
|
|
X86_64 => "core2",
|
2019-08-11 20:31:01 +02:00
|
|
|
X86_64_macabi => "core2",
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
|
|
|
|
.to_string()
|
2015-01-11 12:11:44 +01:00
|
|
|
}
|
|
|
|
|
|
2019-09-12 15:23:59 +03:00
|
|
|
fn link_env_remove(arch: Arch) -> Vec<String> {
|
|
|
|
|
match arch {
|
|
|
|
|
Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()],
|
2020-02-20 10:16:32 -08:00
|
|
|
X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
|
2019-09-12 15:23:59 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-14 16:05:45 -08:00
|
|
|
pub fn opts(arch: Arch, os: AppleOS) -> Result<TargetOptions, String> {
|
|
|
|
|
let pre_link_args = build_pre_link_args(arch, os)?;
|
2016-07-24 11:47:39 -05:00
|
|
|
Ok(TargetOptions {
|
2015-01-11 12:11:44 +01:00
|
|
|
cpu: target_cpu(arch),
|
2015-01-08 10:19:52 +02:00
|
|
|
executables: true,
|
2017-08-06 22:54:09 -07:00
|
|
|
pre_link_args,
|
2019-09-12 15:23:59 +03:00
|
|
|
link_env_remove: link_env_remove(arch),
|
2015-12-10 12:21:55 -08:00
|
|
|
has_elf_tls: false,
|
2018-03-24 21:54:21 +02:00
|
|
|
eliminate_frame_pointer: false,
|
2019-12-22 17:42:04 -05:00
|
|
|
..super::apple_base::opts()
|
2016-07-24 11:47:39 -05:00
|
|
|
})
|
2015-01-08 10:19:52 +02:00
|
|
|
}
|