Last active
May 16, 2026 15:34
-
-
Save jonasvanderhaegen/d7790c7d41d2faaed3cc2a4497803446 to your computer and use it in GitHub Desktop.
Fix lbug 0.15.2 build.rs: replace cfg!() host checks with CARGO_CFG_* env vars for correct cross-compile target detection (macOS→Windows)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use std::env; | |
| use std::path::{Path, PathBuf}; | |
| fn link_mode() -> &'static str { | |
| if env::var("LBUG_SHARED").is_ok() { | |
| "dylib" | |
| } else { | |
| "static" | |
| } | |
| } | |
| fn get_target() -> String { | |
| env::var("PROFILE").unwrap() | |
| } | |
| fn link_libraries() { | |
| let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); | |
| // This also needs to be set by any crates using it if they want to use extensions | |
| if env::var("CARGO_CFG_WINDOWS").is_err() && link_mode() == "static" { | |
| println!("cargo:rustc-link-arg=-rdynamic"); | |
| } | |
| if env::var("CARGO_CFG_WINDOWS").is_ok() && link_mode() == "dylib" { | |
| println!("cargo:rustc-link-lib=dylib=lbug_shared"); | |
| } else if link_mode() == "dylib" { | |
| println!("cargo:rustc-link-lib={}=lbug", link_mode()); | |
| } else if rustversion::cfg!(since(1.82)) && target_os != "linux" { | |
| // Zig's linker (used for Linux cross-compile from macOS) doesn't support | |
| // absolute .a file paths with --whole-archive; skip +whole-archive for Linux. | |
| println!("cargo:rustc-link-lib=static:+whole-archive=lbug"); | |
| } else { | |
| println!("cargo:rustc-link-lib=static=lbug"); | |
| } | |
| if link_mode() == "static" { | |
| if env::var("CARGO_CFG_WINDOWS").is_ok() { | |
| println!("cargo:rustc-link-lib=dylib=msvcrt"); | |
| println!("cargo:rustc-link-lib=dylib=shell32"); | |
| println!("cargo:rustc-link-lib=dylib=ole32"); | |
| } else if target_os == "macos" { | |
| println!("cargo:rustc-link-lib=dylib=c++"); | |
| } else { | |
| println!("cargo:rustc-link-lib=dylib=stdc++"); | |
| } | |
| for lib in [ | |
| "utf8proc", | |
| "antlr4_cypher", | |
| "antlr4_runtime", | |
| "re2", | |
| "fastpfor", | |
| "parquet", | |
| "thrift", | |
| "snappy", | |
| "zstd", | |
| "miniz", | |
| "mbedtls", | |
| "brotlidec", | |
| "brotlicommon", | |
| "lz4", | |
| "roaring_bitmap", | |
| "simsimd", | |
| "yyjson", | |
| ] { | |
| if rustversion::cfg!(since(1.82)) && target_os != "linux" { | |
| println!("cargo:rustc-link-lib=static:+whole-archive={lib}"); | |
| } else { | |
| println!("cargo:rustc-link-lib=static={lib}"); | |
| } | |
| } | |
| } | |
| } | |
| fn get_lbug_root() -> PathBuf { | |
| let manifest_dir_str = std::env::var("CARGO_MANIFEST_DIR").unwrap(); | |
| let manifest_dir = Path::new(&manifest_dir_str); | |
| let root = manifest_dir.join("lbug-src"); | |
| if root.is_symlink() || root.is_dir() { | |
| return root; | |
| } | |
| if env::var("CARGO_CFG_WINDOWS").is_ok() { | |
| return manifest_dir.join("../.."); | |
| } | |
| let lbug_dir = manifest_dir.join("lbug-src"); | |
| if !lbug_dir.exists() { | |
| let version = std::env::var("LBUG_VERSION").unwrap_or_else(|_| "main".to_string()); | |
| println!("Downloading ladybug source version {version}..."); | |
| let url = if version.starts_with('v') { | |
| format!( | |
| "https://github.com/LadybugDB/ladybug/archive/refs/tags/{}.tar.gz", | |
| version | |
| ) | |
| } else if version == "main" { | |
| "https://github.com/LadybugDB/ladybug/archive/refs/heads/main.tar.gz".to_string() | |
| } else { | |
| format!( | |
| "https://github.com/LadybugDB/ladybug/archive/refs/tags/v{}.tar.gz", | |
| version | |
| ) | |
| }; | |
| let output = std::process::Command::new("curl") | |
| .args(["-sL", &url]) | |
| .arg("-o") | |
| .arg("ladybug.tar.gz") | |
| .current_dir(manifest_dir) | |
| .output() | |
| .expect("Failed to download ladybug source"); | |
| if !output.status.success() { | |
| panic!("Failed to download ladybug source from {}", url); | |
| } | |
| std::fs::create_dir_all(&lbug_dir).expect("Failed to create lbug-src directory"); | |
| std::process::Command::new("tar") | |
| .args([ | |
| "-xzf", | |
| "ladybug.tar.gz", | |
| "--strip-components=1", | |
| "-C", | |
| "lbug-src", | |
| ]) | |
| .current_dir(manifest_dir) | |
| .status() | |
| .expect("Failed to extract ladybug source"); | |
| std::fs::remove_file(manifest_dir.join("ladybug.tar.gz")).ok(); | |
| } | |
| lbug_dir | |
| } | |
| fn build_bundled_cmake() -> Vec<PathBuf> { | |
| let lbug_root = get_lbug_root(); | |
| let mut build = cmake::Config::new(&lbug_root); | |
| build | |
| .no_build_target(true) | |
| .define("BUILD_SHELL", "OFF") | |
| .define("BUILD_SINGLE_FILE_HEADER", "OFF") | |
| .define("AUTO_UPDATE_GRAMMAR", "OFF"); | |
| if env::var("CARGO_CFG_WINDOWS").is_ok() { | |
| build.generator("Ninja"); | |
| build.cxxflag("/EHsc"); | |
| build.cxxflag("/std:c++20"); | |
| build.define("CMAKE_MSVC_RUNTIME_LIBRARY", "MultiThreadedDLL"); | |
| build.define("CMAKE_POLICY_DEFAULT_CMP0091", "NEW"); | |
| } | |
| if let Ok(jobs) = std::env::var("NUM_JOBS") { | |
| std::env::set_var("CMAKE_BUILD_PARALLEL_LEVEL", jobs); | |
| } | |
| let build_dir = build.build(); | |
| let lbug_lib_path = build_dir.join("build").join("src"); | |
| println!("cargo:rustc-link-search=native={}", lbug_lib_path.display()); | |
| for dir in [ | |
| "utf8proc", | |
| "antlr4_cypher", | |
| "antlr4_runtime", | |
| "re2", | |
| "brotli", | |
| "alp", | |
| "fastpfor", | |
| "parquet", | |
| "thrift", | |
| "snappy", | |
| "zstd", | |
| "miniz", | |
| "mbedtls", | |
| "lz4", | |
| "roaring_bitmap", | |
| "simsimd", | |
| "yyjson", | |
| ] { | |
| let lib_path = build_dir | |
| .join("build") | |
| .join("third_party") | |
| .join(dir) | |
| .canonicalize() | |
| .unwrap_or_else(|_| { | |
| panic!( | |
| "Could not find {}/build/third_party/{}", | |
| build_dir.display(), | |
| dir | |
| ) | |
| }); | |
| println!("cargo:rustc-link-search=native={}", lib_path.display()); | |
| } | |
| vec![ | |
| lbug_root.join("src/include"), | |
| build_dir.join("build/src"), | |
| build_dir.join("build/src/include"), | |
| lbug_root.join("third_party/nlohmann_json"), | |
| lbug_root.join("third_party/fastpfor"), | |
| lbug_root.join("third_party/alp/include"), | |
| ] | |
| } | |
| fn build_ffi( | |
| bridge_file: &str, | |
| out_name: &str, | |
| source_file: &str, | |
| bundled: bool, | |
| include_paths: &Vec<PathBuf>, | |
| ) { | |
| let mut build = cxx_build::bridge(bridge_file); | |
| build.file(source_file); | |
| if bundled { | |
| build.define("LBUG_BUNDLED", None); | |
| } | |
| if get_target() == "debug" || get_target() == "relwithdebinfo" { | |
| build.define("ENABLE_RUNTIME_CHECKS", "1"); | |
| } | |
| if link_mode() == "static" { | |
| build.define("LBUG_STATIC_DEFINE", None); | |
| } | |
| build.includes(include_paths); | |
| println!("cargo:rerun-if-env-changed=LBUG_SHARED"); | |
| println!("cargo:rerun-if-changed=include/lbug_rs.h"); | |
| println!("cargo:rerun-if-changed=src/lbug_rs.cpp"); | |
| // Note that this should match the lbug-src/* entries in the package.include list in Cargo.toml | |
| // Unfortunately they appear to need to be specified individually since the symlink is | |
| // considered to be changed each time. | |
| println!("cargo:rerun-if-changed=lbug-src/src"); | |
| println!("cargo:rerun-if-changed=lbug-src/cmake"); | |
| println!("cargo:rerun-if-changed=lbug-src/third_party"); | |
| println!("cargo:rerun-if-changed=lbug-src/CMakeLists.txt"); | |
| println!("cargo:rerun-if-changed=lbug-src/tools/CMakeLists.txt"); | |
| if env::var("CARGO_CFG_WINDOWS").is_ok() { | |
| build.flag("/std:c++20"); | |
| build.flag("/MD"); | |
| } else { | |
| build.flag("-std=c++2a"); | |
| } | |
| build.compile(out_name); | |
| } | |
| fn main() { | |
| if env::var("DOCS_RS").is_ok() { | |
| // Do nothing; we're just building docs and don't need the C++ library | |
| return; | |
| } | |
| let mut bundled = false; | |
| let mut include_paths = | |
| vec![Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()).join("include")]; | |
| if let (Ok(lbug_lib_dir), Ok(lbug_include)) = | |
| (env::var("LBUG_LIBRARY_DIR"), env::var("LBUG_INCLUDE_DIR")) | |
| { | |
| println!("cargo:rustc-link-search=native={lbug_lib_dir}"); | |
| println!("cargo:rustc-link-arg=-Wl,-rpath,{lbug_lib_dir}"); | |
| include_paths.push(Path::new(&lbug_include).to_path_buf()); | |
| } else { | |
| include_paths.extend(build_bundled_cmake()); | |
| bundled = true; | |
| } | |
| if link_mode() == "static" { | |
| link_libraries(); | |
| } | |
| build_ffi( | |
| "src/ffi.rs", | |
| "lbug_rs", | |
| "src/lbug_rs.cpp", | |
| bundled, | |
| &include_paths, | |
| ); | |
| if cfg!(feature = "arrow") { | |
| build_ffi( | |
| "src/ffi/arrow.rs", | |
| "lbug_arrow_rs", | |
| "src/lbug_arrow.cpp", | |
| bundled, | |
| &include_paths, | |
| ); | |
| } | |
| if link_mode() == "dylib" { | |
| link_libraries(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment