From deea52e7c6539f2d97f8d25e115e9cbe219795dc Mon Sep 17 00:00:00 2001 From: Siddharth Bhat Date: Thu, 13 Jun 2024 19:01:03 +0100 Subject: [PATCH 1/3] chore: query xcrun on MacOS --- build.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/build.rs b/build.rs index 6422151..2f6fe81 100644 --- a/build.rs +++ b/build.rs @@ -31,7 +31,21 @@ fn main() { lean_dir.join("lib/lean") }; - if !cfg!(feature = "static") { + // To find libc++ on macOS, We must find the path to XCode, which apple enjoys + // changing each macOS release. + // Thus, we do this in a robust fashion by querying `xcrun`. + if cfg!(target_os = "macos") { + let xcrun_output = Command::new("xcrun") + .args(["--show-sdk-path"]) + .output() + .expect("failed to execute `xcrun --show-sdk-path`, which is used to find the location of MacOS platform libraries. Please ensure that XCode is installed."); + let libcpp_path = PathBuf::from(String::from_utf8(xcrun_output.stdout) + .expect("Path returned by `xcrun --show-sdk-path` is invalid UTF-8. This must never happen.").trim()) + .join("usr/lib"); + println!("cargo:rustc-link-search={}", libcpp_path.display()); + } + + if cfg!(feature = "static") { // Step 2: check libleanshared.so/libleanshared.dylib/libleanshared.dll is actually there, just for cleaner error messages let mut shared_lib = lib_dir.clone(); let exists = if cfg!(target_os = "windows") { From 9726034b12cc3f65eb6c2e5516495815a988865c Mon Sep 17 00:00:00 2001 From: Siddharth Bhat Date: Sat, 15 Jun 2024 01:28:59 +0100 Subject: [PATCH 2/3] chore: don't statically link against libc++ --- Cargo.toml | 3 +-- build.rs | 70 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6904278..0704f10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,8 +17,7 @@ links = "leanshared" [features] small_allocator = [] extern = [] -static = [] -default = ["small_allocator", "static"] +default = ["small_allocator"] [dependencies] libc = { version = "0.2", default-features = false } diff --git a/build.rs b/build.rs index 2f6fe81..6be6343 100644 --- a/build.rs +++ b/build.rs @@ -45,33 +45,35 @@ fn main() { println!("cargo:rustc-link-search={}", libcpp_path.display()); } - if cfg!(feature = "static") { - // Step 2: check libleanshared.so/libleanshared.dylib/libleanshared.dll is actually there, just for cleaner error messages - let mut shared_lib = lib_dir.clone(); - let exists = if cfg!(target_os = "windows") { - shared_lib.push("libleanshared.dll"); - shared_lib.exists() - } else if cfg!(target_os = "macos") { - shared_lib.push("libleanshared.dylib"); - shared_lib.exists() - } else if cfg!(unix) { - shared_lib.push("libleanshared.so"); - shared_lib.exists() - } else { - true - }; - if !exists { - panic!( - "{} was not found. We errored, as this would probably cause a linking failure later", - shared_lib.display() - ); - } - // Step 3: actually link with the library - println!("cargo:rustc-link-search={}", lib_dir.display()); - println!("cargo:rustc-link-lib=leanshared"); - println!("cargo:rustc-link-arg=-Wl,-rpath,{}", lib_dir.display()); - } else if cfg!(feature = "extern") { + // if cfg!(feature = "static") { + // // Step 2: check libleanshared.so/libleanshared.dylib/libleanshared.dll is actually there, just for cleaner error messages + // let mut shared_lib = lib_dir.clone(); + // let exists = if cfg!(target_os = "windows") { + // shared_lib.push("libleanshared.dll"); + // shared_lib.exists() + // } else if cfg!(target_os = "macos") { + // shared_lib.push("libleanshared.dylib"); + // shared_lib.exists() + // } else if cfg!(unix) { + // shared_lib.push("libleanshared.so"); + // shared_lib.exists() + // } else { + // true + // }; + // if !exists { + // panic!( + // "{} was not found. We errored, as this would probably cause a linking failure later", + // shared_lib.display() + // ); + // } + + // // Step 3: actually link with the library + // println!("cargo:rustc-link-search={}", lib_dir.display()); + // println!("cargo:rustc-link-lib=leanshared"); + // println!("cargo:rustc-link-arg=-Wl,-rpath,{}", lib_dir.display()); + // } else if cfg!(feature = "extern") { + if cfg!(feature = "extern") { println!("cargo:rustc-link-search={}/lib/lean", lean_dir.display()); println!("cargo:rustc-link-search={}/lib", lean_dir.display()); for lib in ["Lean", "Init", "leanrt", "leancpp", "gmp", "c++", "c++abi"] { @@ -87,8 +89,20 @@ fn main() { } println!("cargo:rustc-link-arg=-Wl,--end-group"); } - for lib in ["Lake", "c++", "c++abi"] { - println!("cargo:rustc-link-lib=static={lib}"); + + if cfg!(target_os = "macos") { + // Static linking against libc++(abi) on MacOS is a total shitshow, so just don't. + for lib in ["Lake"] { + println!("cargo:rustc-link-lib=static={lib}"); + } + for lib in ["c++", "c++abi"] { + println!("cargo:rustc-link-lib=dylib={lib}"); + } + + } else { + for lib in ["Lake", "c++", "c++abi"] { + println!("cargo:rustc-link-lib=static={lib}"); + } } for lib in ["m", "dl", "gmp"] { println!("cargo:rustc-link-lib=dylib={lib}"); From 3de29d86c064f65b01f2d62ec364970f4f7f83c9 Mon Sep 17 00:00:00 2001 From: Siddharth Bhat Date: Sat, 15 Jun 2024 01:47:27 +0100 Subject: [PATCH 3/3] chore: get linking working --- build.rs | 107 +++++++++++++++++++++++-------------------------------- 1 file changed, 45 insertions(+), 62 deletions(-) diff --git a/build.rs b/build.rs index 6be6343..4dd8a81 100644 --- a/build.rs +++ b/build.rs @@ -1,6 +1,47 @@ use std::path::PathBuf; use std::process::Command; +fn cargo_add_ld_options() { + // Run the command 'leanc --print-ldflags' + let output = Command::new("leanc") + .arg("--print-ldflags") + .output() + .expect("Failed to execute leanc command"); + + // Check if the command was successful + if output.status.success() { + // Convert the output to a string + let output_str = String::from_utf8(output.stdout).expect("Invalid UTF-8 in output"); + + // Split the output by '-L' and get the part after '-L' + let parts: Vec<&str> = output_str.split("-L").collect(); + if parts.len() < 2 { + eprintln!("Error: No ldflags found after -L"); + return; + } + let ld_search_path = parts[1].split_whitespace().next().unwrap_or_default(); + + // Pass search_path to Cargo as arguments + println!("cargo:rustc-link-search=native={}", ld_search_path); + + let lib_names : Vec<&str> = parts[1].split(" ").skip(2).map(|part| { + // drop the '-l' part. + part.split_whitespace().next().unwrap_or_default().strip_prefix("-l").unwrap_or_default() + + }).collect(); + + for lib_name in lib_names.iter() { + println!("cargo:rustc-link-lib={}", lib_name); + } + println!("cargo::warning=error: lib names: {:?}", lib_names); + + } else { + // Print an error message if the command failed + println!("cargo::warning='Error: leanc command failed with status {:?}", output.status); + } +} + + fn main() { if let Ok(docs_rs) = std::env::var("DOCS_RS") { // Detected build on `docs.rs`, so skip trying to link in Lean and just build docs @@ -45,67 +86,9 @@ fn main() { println!("cargo:rustc-link-search={}", libcpp_path.display()); } + println!("cargo:rustc-link-search={}/lib", lean_dir.display()); + println!("cargo:rustc-link-search={}/lib/lean", lean_dir.display()); - // if cfg!(feature = "static") { - // // Step 2: check libleanshared.so/libleanshared.dylib/libleanshared.dll is actually there, just for cleaner error messages - // let mut shared_lib = lib_dir.clone(); - // let exists = if cfg!(target_os = "windows") { - // shared_lib.push("libleanshared.dll"); - // shared_lib.exists() - // } else if cfg!(target_os = "macos") { - // shared_lib.push("libleanshared.dylib"); - // shared_lib.exists() - // } else if cfg!(unix) { - // shared_lib.push("libleanshared.so"); - // shared_lib.exists() - // } else { - // true - // }; - // if !exists { - // panic!( - // "{} was not found. We errored, as this would probably cause a linking failure later", - // shared_lib.display() - // ); - // } - - // // Step 3: actually link with the library - // println!("cargo:rustc-link-search={}", lib_dir.display()); - // println!("cargo:rustc-link-lib=leanshared"); - // println!("cargo:rustc-link-arg=-Wl,-rpath,{}", lib_dir.display()); - // } else if cfg!(feature = "extern") { - if cfg!(feature = "extern") { - println!("cargo:rustc-link-search={}/lib/lean", lean_dir.display()); - println!("cargo:rustc-link-search={}/lib", lean_dir.display()); - for lib in ["Lean", "Init", "leanrt", "leancpp", "gmp", "c++", "c++abi"] { - println!("cargo:rustc-link-lib=static={lib}"); - } - } else { - println!("cargo:rustc-link-search={}/lib", lean_dir.display()); - println!("cargo:rustc-link-search={}/lib/lean", lean_dir.display()); - for libs in [["Lean", "leancpp"], ["Init", "leanrt"]] { - println!("cargo:rustc-link-arg=-Wl,--start-group"); - for lib in libs { - println!("cargo:rustc-link-lib=static={lib}"); - } - println!("cargo:rustc-link-arg=-Wl,--end-group"); - } - - if cfg!(target_os = "macos") { - // Static linking against libc++(abi) on MacOS is a total shitshow, so just don't. - for lib in ["Lake"] { - println!("cargo:rustc-link-lib=static={lib}"); - } - for lib in ["c++", "c++abi"] { - println!("cargo:rustc-link-lib=dylib={lib}"); - } - - } else { - for lib in ["Lake", "c++", "c++abi"] { - println!("cargo:rustc-link-lib=static={lib}"); - } - } - for lib in ["m", "dl", "gmp"] { - println!("cargo:rustc-link-lib=dylib={lib}"); - } - } + cargo_add_ld_options(); + }