diff options
| author | bors <bors@rust-lang.org> | 2024-09-27 17:28:47 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-09-27 17:28:47 +0000 |
| commit | fa724e5d8cbbdfbd1e53c4c656121af01b694406 (patch) | |
| tree | cb03957ec3e5050d456cb76445a55c146af42ce6 /compiler/rustc_codegen_ssa | |
| parent | a3f76a26e045a760bb1163b7eab36872985242d5 (diff) | |
| parent | 966a0b76bc21ba65071b4d50dfb0536e0581604f (diff) | |
| download | rust-fa724e5d8cbbdfbd1e53c4c656121af01b694406.tar.gz rust-fa724e5d8cbbdfbd1e53c4c656121af01b694406.zip | |
Auto merge of #130934 - matthiaskrgr:rollup-4puticr, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #129087 (Stabilize `option_get_or_insert_default`) - #130435 (Move Apple linker args from `rustc_target` to `rustc_codegen_ssa`) - #130459 (delete sub build directory "debug" to not delete the change-id file) - #130873 (rustc_target: Add powerpc64 atomic-related features) - #130916 (Use `&raw` in the compiler) - #130917 (Fix error span if arg to `asm!()` is a macro call) - #130927 (update outdated comments) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_codegen_ssa')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/link.rs | 133 |
1 files changed, 132 insertions, 1 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 69693230ce0..80e8111516e 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -40,7 +40,7 @@ use rustc_target::spec::crt_objects::CrtObjects; use rustc_target::spec::{ Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault, LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, - SplitDebuginfo, + SplitDebuginfo, current_apple_deployment_target, }; use tempfile::Builder as TempFileBuilder; use tracing::{debug, info, warn}; @@ -2405,6 +2405,8 @@ fn add_order_independent_options( // Take care of the flavors and CLI options requesting the `lld` linker. add_lld_args(cmd, sess, flavor, self_contained_components); + add_apple_link_args(cmd, sess, flavor); + let apple_sdk_root = add_apple_sdk(cmd, sess, flavor); add_link_script(cmd, sess, tmpdir, crate_type); @@ -2957,6 +2959,135 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool } } +/// We need to communicate four things to the linker on Apple/Darwin targets: +/// - The architecture. +/// - The operating system (and that it's an Apple platform). +/// - The deployment target. +/// - The environment / ABI. +fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { + if !sess.target.is_like_osx { + return; + } + let LinkerFlavor::Darwin(cc, _) = flavor else { + return; + }; + + // `sess.target.arch` (`target_arch`) is not detailed enough. + let llvm_arch = sess.target.llvm_target.split_once('-').expect("LLVM target must have arch").0; + let target_os = &*sess.target.os; + let target_abi = &*sess.target.abi; + + // The architecture name to forward to the linker. + // + // Supported architecture names can be found in the source: + // https://github.com/apple-oss-distributions/ld64/blob/ld64-951.9/src/abstraction/MachOFileAbstraction.hpp#L578-L648 + // + // Intentially verbose to ensure that the list always matches correctly + // with the list in the source above. + let ld64_arch = match llvm_arch { + "armv7k" => "armv7k", + "armv7s" => "armv7s", + "arm64" => "arm64", + "arm64e" => "arm64e", + "arm64_32" => "arm64_32", + // ld64 doesn't understand i686, so fall back to i386 instead. + // + // Same story when linking with cc, since that ends up invoking ld64. + "i386" | "i686" => "i386", + "x86_64" => "x86_64", + "x86_64h" => "x86_64h", + _ => bug!("unsupported architecture in Apple target: {}", sess.target.llvm_target), + }; + + if cc == Cc::No { + // From the man page for ld64 (`man ld`): + // > The linker accepts universal (multiple-architecture) input files, + // > but always creates a "thin" (single-architecture), standard + // > Mach-O output file. The architecture for the output file is + // > specified using the -arch option. + // + // The linker has heuristics to determine the desired architecture, + // but to be safe, and to avoid a warning, we set the architecture + // explicitly. + cmd.link_args(&["-arch", ld64_arch]); + + // Man page says that ld64 supports the following platform names: + // > - macos + // > - ios + // > - tvos + // > - watchos + // > - bridgeos + // > - visionos + // > - xros + // > - mac-catalyst + // > - ios-simulator + // > - tvos-simulator + // > - watchos-simulator + // > - visionos-simulator + // > - xros-simulator + // > - driverkit + let platform_name = match (target_os, target_abi) { + (os, "") => os, + ("ios", "macabi") => "mac-catalyst", + ("ios", "sim") => "ios-simulator", + ("tvos", "sim") => "tvos-simulator", + ("watchos", "sim") => "watchos-simulator", + ("visionos", "sim") => "visionos-simulator", + _ => bug!("invalid OS/ABI combination for Apple target: {target_os}, {target_abi}"), + }; + + let (major, minor, patch) = current_apple_deployment_target(&sess.target); + let min_version = format!("{major}.{minor}.{patch}"); + + // Lie about the SDK version, we don't know it here + let sdk_version = &*min_version; + + // From the man page for ld64 (`man ld`): + // > This is set to indicate the platform, oldest supported version of + // > that platform that output is to be used on, and the SDK that the + // > output was built against. + // + // Like with `-arch`, the linker can figure out the platform versions + // itself from the binaries being linked, but to be safe, we specify + // the desired versions here explicitly. + cmd.link_args(&["-platform_version", platform_name, &*min_version, sdk_version]); + } else { + // cc == Cc::Yes + // We'd _like_ to use `-target` everywhere, since that can uniquely + // communicate all the required details, but that doesn't work on GCC, + // and since we don't know whether the `cc` compiler is Clang, GCC, or + // something else, we fall back to other options that also work on GCC + // when compiling for macOS. + // + // Targets other than macOS are ill-supported by GCC (it doesn't even + // support e.g. `-miphoneos-version-min`), so in those cases we can + // fairly safely use `-target`. See also the following, where it is + // made explicit that the recommendation by LLVM developers is to use + // `-target`: <https://github.com/llvm/llvm-project/issues/88271> + if target_os == "macos" { + // `-arch` communicates the architecture. + // + // CC forwards the `-arch` to the linker, so we use the same value + // here intentionally. + cmd.cc_args(&["-arch", ld64_arch]); + + // The presence of `-mmacosx-version-min` makes CC default to + // macOS, and it sets the deployment target. + let (major, minor, patch) = current_apple_deployment_target(&sess.target); + // Intentionally pass this as a single argument, Clang doesn't + // seem to like it otherwise. + cmd.cc_arg(&format!("-mmacosx-version-min={major}.{minor}.{patch}")); + + // macOS has no environment, so with these two, we've told CC the + // four desired parameters. + // + // We avoid `-m32`/`-m64`, as this is already encoded by `-arch`. + } else { + cmd.cc_args(&["-target", &sess.target.llvm_target]); + } + } +} + fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option<PathBuf> { let arch = &sess.target.arch; let os = &sess.target.os; |
