diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2022-07-01 23:39:07 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-01 23:39:07 +0200 |
| commit | 01aa10c2ffd49238d0aef83253190c8df0d77c87 (patch) | |
| tree | a6b1e1e54a7f726afb79df01a37b89a51c7c9fb2 /src | |
| parent | 194764fdc070d95ce2200548a2e6267d701068bd (diff) | |
| parent | b6e28b59679e3e4ee47b20090035ef33889b3f3b (diff) | |
| download | rust-01aa10c2ffd49238d0aef83253190c8df0d77c87.tar.gz rust-01aa10c2ffd49238d0aef83253190c8df0d77c87.zip | |
Rollup merge of #98418 - topjohnwu:macos-dylib, r=jyn514
Allow macOS to build LLVM as shared library Inspired by how [homebrew](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/llvm.rb) builds and distributes llvm, here we manually create a symlink with a versioned dylib path to make `llvm-config` work properly. Note, the resulting `rustc` executable and `librustc_driver-<hash>.dylib` still links to the un-versioned `libLLVM.dylib` as expected when distributed in the final output. I have confirmed this by checking `otool -L` on both binaries. After the change, enabling `llvm.link-shared` and `llvm.thin-lto` will be possible on macOS.
Diffstat (limited to 'src')
| -rw-r--r-- | src/bootstrap/lib.rs | 16 | ||||
| -rw-r--r-- | src/bootstrap/native.rs | 41 |
2 files changed, 41 insertions, 16 deletions
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 859d35b7d7b..40ff0381c8b 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -107,15 +107,11 @@ use std::cell::{Cell, RefCell}; use std::collections::{HashMap, HashSet}; use std::env; use std::fs::{self, File}; +use std::io; use std::path::{Path, PathBuf}; use std::process::{self, Command}; use std::str; -#[cfg(unix)] -use std::os::unix::fs::symlink as symlink_file; -#[cfg(windows)] -use std::os::windows::fs::symlink_file; - use filetime::FileTime; use once_cell::sync::OnceCell; @@ -1460,7 +1456,7 @@ impl Build { src = t!(fs::canonicalize(src)); } else { let link = t!(fs::read_link(src)); - t!(symlink_file(link, dst)); + t!(self.symlink_file(link, dst)); return; } } @@ -1585,6 +1581,14 @@ impl Build { iter.map(|e| t!(e)).collect::<Vec<_>>().into_iter() } + fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(&self, src: P, link: Q) -> io::Result<()> { + #[cfg(unix)] + use std::os::unix::fs::symlink as symlink_file; + #[cfg(windows)] + use std::os::windows::fs::symlink_file; + if !self.config.dry_run { symlink_file(src.as_ref(), link.as_ref()) } else { Ok(()) } + } + fn remove(&self, f: &Path) { if self.config.dry_run { return; diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 9cd8b6d1455..8395be40f9b 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -251,9 +251,7 @@ impl Step for Llvm { }; builder.update_submodule(&Path::new("src").join("llvm-project")); - if builder.llvm_link_shared() - && (target.contains("windows") || target.contains("apple-darwin")) - { + if builder.llvm_link_shared() && target.contains("windows") { panic!("shared linking to LLVM is not currently supported on {}", target.triple); } @@ -359,7 +357,9 @@ impl Step for Llvm { // // If we're not linking rustc to a dynamic LLVM, though, then don't link // tools to it. - if builder.llvm_link_tools_dynamically(target) && builder.llvm_link_shared() { + let llvm_link_shared = + builder.llvm_link_tools_dynamically(target) && builder.llvm_link_shared(); + if llvm_link_shared { cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); } @@ -438,18 +438,18 @@ impl Step for Llvm { ); } - if let Some(ref suffix) = builder.config.llvm_version_suffix { + let llvm_version_suffix = if let Some(ref suffix) = builder.config.llvm_version_suffix { // Allow version-suffix="" to not define a version suffix at all. - if !suffix.is_empty() { - cfg.define("LLVM_VERSION_SUFFIX", suffix); - } + if !suffix.is_empty() { Some(suffix.to_string()) } else { None } } else if builder.config.channel == "dev" { // Changes to a version suffix require a complete rebuild of the LLVM. // To avoid rebuilds during a time of version bump, don't include rustc // release number on the dev channel. - cfg.define("LLVM_VERSION_SUFFIX", "-rust-dev"); + Some("-rust-dev".to_string()) } else { - let suffix = format!("-rust-{}-{}", builder.version, builder.config.channel); + Some(format!("-rust-{}-{}", builder.version, builder.config.channel)) + }; + if let Some(ref suffix) = llvm_version_suffix { cfg.define("LLVM_VERSION_SUFFIX", suffix); } @@ -478,6 +478,27 @@ impl Step for Llvm { cfg.build(); + // When building LLVM with LLVM_LINK_LLVM_DYLIB for macOS, an unversioned + // libLLVM.dylib will be built. However, llvm-config will still look + // for a versioned path like libLLVM-14.dylib. Manually create a symbolic + // link to make llvm-config happy. + if llvm_link_shared && target.contains("apple-darwin") { + let mut cmd = Command::new(&build_llvm_config); + let version = output(cmd.arg("--version")); + let major = version.split('.').next().unwrap(); + let lib_name = match llvm_version_suffix { + Some(s) => format!("lib/libLLVM-{}{}.dylib", major, s), + None => format!("lib/libLLVM-{}.dylib", major), + }; + + // The reason why we build the library path from llvm-config is because + // the output of llvm-config depends on its location in the file system. + // Make sure we create the symlink exactly where it's needed. + let llvm_base = build_llvm_config.parent().unwrap().parent().unwrap(); + let lib_llvm = llvm_base.join(lib_name); + t!(builder.symlink_file("libLLVM.dylib", &lib_llvm)); + } + t!(stamp.write()); build_llvm_config |
