提交 b6e28b59 编写于 作者: T topjohnwu

Allow dynamically linking against libLLVM on macOS

Create symlinks to workaround file missing error in llvm-config
上级 fdca237d
...@@ -107,15 +107,11 @@ ...@@ -107,15 +107,11 @@
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::env; use std::env;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::{self, Command}; use std::process::{self, Command};
use std::str; 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 filetime::FileTime;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
...@@ -1446,7 +1442,7 @@ fn copy_internal(&self, src: &Path, dst: &Path, dereference_symlinks: bool) { ...@@ -1446,7 +1442,7 @@ fn copy_internal(&self, src: &Path, dst: &Path, dereference_symlinks: bool) {
src = t!(fs::canonicalize(src)); src = t!(fs::canonicalize(src));
} else { } else {
let link = t!(fs::read_link(src)); let link = t!(fs::read_link(src));
t!(symlink_file(link, dst)); t!(self.symlink_file(link, dst));
return; return;
} }
} }
...@@ -1571,6 +1567,14 @@ fn read_dir(&self, dir: &Path) -> impl Iterator<Item = fs::DirEntry> { ...@@ -1571,6 +1567,14 @@ fn read_dir(&self, dir: &Path) -> impl Iterator<Item = fs::DirEntry> {
iter.map(|e| t!(e)).collect::<Vec<_>>().into_iter() 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) { fn remove(&self, f: &Path) {
if self.config.dry_run { if self.config.dry_run {
return; return;
......
...@@ -238,9 +238,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { ...@@ -238,9 +238,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
}; };
builder.update_submodule(&Path::new("src").join("llvm-project")); builder.update_submodule(&Path::new("src").join("llvm-project"));
if builder.llvm_link_shared() if builder.llvm_link_shared() && target.contains("windows") {
&& (target.contains("windows") || target.contains("apple-darwin"))
{
panic!("shared linking to LLVM is not currently supported on {}", target.triple); panic!("shared linking to LLVM is not currently supported on {}", target.triple);
} }
...@@ -346,7 +344,9 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { ...@@ -346,7 +344,9 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
// //
// If we're not linking rustc to a dynamic LLVM, though, then don't link // If we're not linking rustc to a dynamic LLVM, though, then don't link
// tools to it. // 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"); cfg.define("LLVM_LINK_LLVM_DYLIB", "ON");
} }
...@@ -425,18 +425,18 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { ...@@ -425,18 +425,18 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
); );
} }
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. // Allow version-suffix="" to not define a version suffix at all.
if !suffix.is_empty() { if !suffix.is_empty() { Some(suffix.to_string()) } else { None }
cfg.define("LLVM_VERSION_SUFFIX", suffix);
}
} else if builder.config.channel == "dev" { } else if builder.config.channel == "dev" {
// Changes to a version suffix require a complete rebuild of the LLVM. // 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 // To avoid rebuilds during a time of version bump, don't include rustc
// release number on the dev channel. // release number on the dev channel.
cfg.define("LLVM_VERSION_SUFFIX", "-rust-dev"); Some("-rust-dev".to_string())
} else { } 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); cfg.define("LLVM_VERSION_SUFFIX", suffix);
} }
...@@ -465,6 +465,27 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { ...@@ -465,6 +465,27 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
cfg.build(); 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()); t!(stamp.write());
build_llvm_config build_llvm_config
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册