Skip to content

Commit

Permalink
fix: build on macos with asan (tlspuffin#302)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelmera authored Mar 6, 2024
1 parent 37c71e1 commit c98e986
Showing 1 changed file with 64 additions and 7 deletions.
71 changes: 64 additions & 7 deletions tlspuffin/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ use std::process::Command;

fn main() {
if cfg!(feature = "asan") {
let output = Command::new("clang")
.args(["--print-resource-dir"])
.output()
.expect("failed to clang to get resource dir");
let clang: &str = std::str::from_utf8(&output.stdout).unwrap().trim();

println!("cargo:rustc-link-arg=-Wl,-rpath={}/lib/linux/", clang);
// NOTE adding compiler-rt to rpath for libasan is not straightforward
//
// Unfortunately, passing `-frtlib-add-rpath` to clang doesn't add
// the correct rpath on linux platforms. Instead, we find the folder
// containing the compiler-rt runtime and add it to rpath ourselves.
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", runtime_dir());
println!("cargo:rustc-link-arg=-fsanitize=address");
println!("cargo:rustc-link-arg=-shared-libasan");
}
Expand All @@ -23,3 +22,61 @@ fn main() {
println!("cargo:rustc-link-arg=-fcoverage-mapping");
}
}

fn runtime_dir() -> String {
// NOTE the current process for finding the runtime-dir might be incomplete
//
// We try the following in order:
// - `clang --print-runtime-dir` (clang >= 13)
// - `clang --print-resource-dir`/lib/<os>
// - panic
//
// Note that extracting the directory path directly from the result of
// `--print-file-name=libclang_rt.asan-<arch>.<dylib_suffix>` would be
// an alternative solution but it was broken for a long time on Apple
// clang.
//
// - see https://github.com/llvm/llvm-project/commit/aafc3f7be804d117a632365489a18c3e484a3931
let output = Command::new("clang")
.args(["--print-runtime-dir"])
.output()
.expect("failed to get runtime dir from `clang --print-runtime-dir`. Is clang in PATH?");

let clang_runtime_dir = output
.status
.success()
.then(|| std::str::from_utf8(&output.stdout).unwrap().trim())
.unwrap_or("");

if clang_runtime_dir.is_empty() {
return runtime_dir_fallback();
}

clang_runtime_dir.to_string()
}

fn runtime_dir_fallback() -> String {
let output = Command::new("clang")
.args(["--print-resource-dir"])
.output()
.expect("failed to get resource dir from `clang --print-resource-dir`. Is clang in PATH?");

let clang_resource_dir = output
.status
.success()
.then(|| std::str::from_utf8(&output.stdout).unwrap().trim())
.expect("failed to get resource dir from `clang --print-resource-dir`");

let clang_sysname = match std::env::consts::OS {
"macos" => "darwin",
"linux" => "linux",
_ => panic!("cannot get compiler runtime dir: unsupported os"),
};

let runtime_dir = format!("{}/lib/{}/", clang_resource_dir, clang_sysname);
if !std::path::Path::new(&runtime_dir).exists() {
panic!("failed to find clang runtime dir");
}

runtime_dir
}

0 comments on commit c98e986

Please sign in to comment.