diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 954a601480935..73f4a9ce02e0f 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -402,6 +402,26 @@ codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio codegen_ssa_xcrun_command_line_tools_insufficient = when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode +codegen_ssa_xcrun_cross_about = + the SDK is needed by the linker to know where to find symbols in system libraries and for embedding the SDK version in the final object file + +codegen_ssa_xcrun_cross_download_sdk = + the SDK can be downloaded and extracted from https://developer.apple.com/download/all/?q=xcode (requires an Apple ID). + + The full Xcode bundle should contain the SDK in Xcode.app/Contents/Developer/Platforms/{$sdk_name}.platform/Developer/SDKs/{$sdk_name}.sdk{ $sdk_name -> + [MacOSX] , but downloading just the "Command Line Tools for Xcode" should also be sufficient to obtain the macOS SDK. + *[other] . + } + +codegen_ssa_xcrun_cross_env_var = + pass the path to the SDK using the SDKROOT environment variable + +codegen_ssa_xcrun_cross_ill_supported_target = + cross-compiling on iOS, tvOS, visionOS or watchOS (in particular the linking step) is ill supported on non-macOS hosts + +codegen_ssa_xcrun_cross_linker_not_explicitly_set = + you will also need to use a linker capable of linking Mach-O files, consider using the bundled `lld` with `-Clinker=rust-lld` + codegen_ssa_xcrun_failed_invoking = invoking `{$command_formatted}` to find {$sdk_name}.sdk failed: {$error} codegen_ssa_xcrun_found_developer_dir = found active developer directory at "{$developer_dir}" diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 2c8b0ec418dd8..e53854ed16a2b 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -290,22 +290,50 @@ pub(super) fn get_sdk_root(sess: &Session) -> Option { Some(path) } Err(err) => { - let mut diag = sess.dcx().create_err(err); - - // Recognize common error cases, and give more Rust-specific error messages for those. - if let Some(developer_dir) = xcode_select_developer_dir() { - diag.arg("developer_dir", &developer_dir); - diag.note(fluent::codegen_ssa_xcrun_found_developer_dir); - if developer_dir.as_os_str().to_string_lossy().contains("CommandLineTools") { - if sdk_name != "MacOSX" { - diag.help(fluent::codegen_ssa_xcrun_command_line_tools_insufficient); + if sess.host.os == "macos" { + // On host macOS, we require the SDK to be available, either via the `SDKROOT` env + // var, or from the invocation of `xcrun`. + let mut diag = sess.dcx().create_err(err); + + // Recognize common error cases, and give more Rust-specific error messages for those. + if let Some(developer_dir) = xcode_select_developer_dir() { + diag.arg("developer_dir", &developer_dir); + diag.note(fluent::codegen_ssa_xcrun_found_developer_dir); + if developer_dir.as_os_str().to_string_lossy().contains("CommandLineTools") { + if sdk_name != "MacOSX" { + diag.help(fluent::codegen_ssa_xcrun_command_line_tools_insufficient); + } } + } else { + diag.help(fluent::codegen_ssa_xcrun_no_developer_dir); } + + diag.emit(); } else { - diag.help(fluent::codegen_ssa_xcrun_no_developer_dir); + // When cross-compiling from e.g. Linux, while the `xcrun` binary _may_ sometimes be + // provided as a shim by a cross-compilation helper tool, it usually isn't. + // + // In that case, we treat failing to find and/or invoke the `xcrun` binary as a + // warning, allow the SDK to be missing, and assume that the compiler driver + // / linker is properly configured to be able to link with an internal SDK (like in + // `zig cc`). + let mut diag = sess.dcx().create_warn(err); + + diag.note(fluent::codegen_ssa_xcrun_cross_about); + diag.help(fluent::codegen_ssa_xcrun_cross_env_var); + diag.help(fluent::codegen_ssa_xcrun_cross_download_sdk); + + if sess.opts.cg.linker.is_none() { + diag.warn(fluent::codegen_ssa_xcrun_cross_linker_not_explicitly_set); + } + + if sess.target.os != "macos" { + diag.warn(fluent::codegen_ssa_xcrun_cross_ill_supported_target); + } + + diag.emit(); } - diag.emit(); None } } @@ -330,6 +358,8 @@ fn xcrun_show_sdk_path( sdk_name: &'static str, verbose: bool, ) -> Result<(PathBuf, String), XcrunError> { + // Intentionally invoke the `xcrun` in PATH (e.g. nixpkgs provides an `xcrun` shim, so we don't + // want to require `/usr/bin/xcrun`). let mut cmd = Command::new("xcrun"); if verbose { cmd.arg("--verbose"); @@ -401,7 +431,7 @@ fn stdout_to_path(mut stdout: Vec) -> PathBuf { } #[cfg(unix)] let path = ::from_vec(stdout); - #[cfg(not(unix))] // Unimportant, this is only used on macOS - let path = OsString::from(String::from_utf8(stdout).unwrap()); + #[cfg(not(unix))] // Not so important, this is mostly used on macOS + let path = OsString::from(String::from_utf8(stdout).expect("stdout must be UTF-8")); PathBuf::from(path) }