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 6422151..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 @@ -31,53 +72,23 @@ fn main() { lean_dir.join("lib/lean") }; - 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") { - 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"); - } - 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}"); - } + // 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()); } + + println!("cargo:rustc-link-search={}/lib", lean_dir.display()); + println!("cargo:rustc-link-search={}/lib/lean", lean_dir.display()); + + cargo_add_ld_options(); + }