mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
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.
This commit is contained in:
commit
01aa10c2ff
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user