Skip to content

Commit

Permalink
Replace libLLVM symlink with linker script
Browse files Browse the repository at this point in the history
It turns out that the libLLVM-N.so -> libLLVM.so.N.1 symlink is
also needed when projects like miri link against librustc_driver.so.
As such, we have to distribute it in real rustup components like
rustc-dev, rather than only for download-ci-llvm.

To avoid actually distributing symlinks (which are not supported
or not fully supported by the rustup infrastructure) replace it
with a linker script that does the same thing instead.
  • Loading branch information
nikic committed Mar 4, 2024
1 parent f7cb53e commit 3501f4a
Showing 1 changed file with 15 additions and 23 deletions.
38 changes: 15 additions & 23 deletions src/bootstrap/src/core/build_steps/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2021,12 +2021,7 @@ fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
}
}

fn install_llvm_file(
builder: &Builder<'_>,
source: &Path,
destination: &Path,
install_symlink: bool,
) {
fn install_llvm_file(builder: &Builder<'_>, source: &Path, destination: &Path) {
if builder.config.dry_run() {
return;
}
Expand All @@ -2035,11 +2030,15 @@ fn install_llvm_file(
// If we have a symlink like libLLVM-18.so -> libLLVM.so.18.1, install the target of the
// symlink, which is what will actually get loaded at runtime.
builder.install(&t!(fs::canonicalize(source)), destination, 0o644);
if install_symlink {
// If requested, also install the symlink. This is used by download-ci-llvm.
let full_dest = destination.join(source.file_name().unwrap());
builder.copy(&source, &full_dest);
}

// Replace the symlink itself with an equivalent linker script. This is used by
// download-ci-llvm and projects linking against librustc_driver.so. We don't use a
// symlink, as these are not allowed inside rustup components.
let link = t!(fs::read_link(source));
t!(std::fs::write(
destination.join(source.file_name().unwrap()),
format!("INPUT({})", link.display())
));
} else {
builder.install(&source, destination, 0o644);
}
Expand All @@ -2048,12 +2047,7 @@ fn install_llvm_file(
/// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking.
///
/// Returns whether the files were actually copied.
fn maybe_install_llvm(
builder: &Builder<'_>,
target: TargetSelection,
dst_libdir: &Path,
install_symlink: bool,
) -> bool {
fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) -> bool {
// If the LLVM was externally provided, then we don't currently copy
// artifacts into the sysroot. This is not necessarily the right
// choice (in particular, it will require the LLVM dylib to be in
Expand Down Expand Up @@ -2102,7 +2096,7 @@ fn maybe_install_llvm(
} else {
PathBuf::from(file)
};
install_llvm_file(builder, &file, dst_libdir, install_symlink);
install_llvm_file(builder, &file, dst_libdir);
}
!builder.config.dry_run()
} else {
Expand All @@ -2117,7 +2111,7 @@ pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection,
// dynamically linked; it is already included into librustc_llvm
// statically.
if builder.llvm_link_shared() {
maybe_install_llvm(builder, target, &dst_libdir, false);
maybe_install_llvm(builder, target, &dst_libdir);
}
}

Expand All @@ -2129,7 +2123,7 @@ pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection
// dynamically linked; it is already included into librustc_llvm
// statically.
if builder.llvm_link_shared() {
maybe_install_llvm(builder, target, &dst_libdir, false);
maybe_install_llvm(builder, target, &dst_libdir);
}
}

Expand Down Expand Up @@ -2224,8 +2218,6 @@ impl Step for RustDev {

let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
tarball.set_overlay(OverlayKind::LLVM);
// LLVM requires a shared object symlink to exist on some platforms.
tarball.permit_symlinks(true);

builder.ensure(crate::core::build_steps::llvm::Llvm { target });

Expand Down Expand Up @@ -2266,7 +2258,7 @@ impl Step for RustDev {
// of `rustc-dev` to support the inherited `-lLLVM` when using the
// compiler libraries.
let dst_libdir = tarball.image_dir().join("lib");
maybe_install_llvm(builder, target, &dst_libdir, true);
maybe_install_llvm(builder, target, &dst_libdir);
let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);

Expand Down

0 comments on commit 3501f4a

Please sign in to comment.