From 405226dd710a02a68d8a2b1cccf7495a4ceb60ef Mon Sep 17 00:00:00 2001 From: Jonas Vanderhaegen <7755555+jonasvanderhaegen@users.noreply.github.com> Date: Sun, 24 May 2026 01:55:19 +0200 Subject: [PATCH] build: link bundled-dep archives shipped with prebuilt liblbug.a The prebuilt liblbug.a has unresolved external references to yyjson, simsimd and several other third-party libraries. These archives are shipped alongside liblbug.a in the prebuilt cache directory, but the build script never told the linker about them. Add link_prebuilt_bundled_deps() which emits cargo:rustc-link-lib directives for every *.a found in the prebuilt lib dir, and call it from use_prebuilt_lbug(). The function is existence-gated so it is a no-op when a fully fused archive is used. Fixes "Undefined symbols: _yyjson_val_mut_copy, _yyjson_write_opts ..." link errors on macOS and equivalent failures on Linux when the crate is consumed via [patch.crates-io] or crates.io download. --- build.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/build.rs b/build.rs index 8bd4f53..101085c 100644 --- a/build.rs +++ b/build.rs @@ -72,6 +72,43 @@ fn link_libraries(link_bundled_deps: bool) { } } +/// Emit `cargo:rustc-link-lib` directives for every bundled-dep static archive +/// that was shipped alongside the prebuilt `liblbug.a`. The prebuilt archive +/// contains object files that reference symbols from these libraries (yyjson, +/// simsimd, etc.) but does not fold them in, so the linker must be told to +/// pull them in explicitly. The directives are only emitted for files that +/// actually exist so this is a no-op when the prebuilt ships a fused archive. +fn link_prebuilt_bundled_deps(lib_dir: &Path) { + for lib in [ + "utf8proc", + "antlr4_cypher", + "antlr4_runtime", + "re2", + "fastpfor", + "parquet", + "thrift", + "snappy", + "zstd", + "miniz", + "mbedtls", + "brotlidec", + "brotlicommon", + "lz4", + "roaring_bitmap", + "simsimd", + "yyjson", + ] { + let lib_path = lib_dir.join(format!("lib{lib}.a")); + if lib_path.exists() { + if rustversion::cfg!(since(1.82)) { + println!("cargo:rustc-link-lib=static:+whole-archive={lib}"); + } else { + println!("cargo:rustc-link-lib=static={lib}"); + } + } + } +} + fn manifest_dir() -> PathBuf { PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()) } @@ -198,6 +235,11 @@ fn use_prebuilt_lbug(manifest_dir: &Path) -> Option> { println!("cargo:rustc-link-search=native={}", lib_dir.display()); println!("cargo:rerun-if-changed={}", lib_dir.display()); emit_lbug_metadata(&prebuilt_source_desc(), &lib_dir); + // Link any bundled-dep archives that were shipped alongside liblbug.a. + // The prebuilt archive has unresolved references to yyjson, simsimd, etc.; + // without these directives the final link step fails with + // "Undefined symbols: _yyjson_val_mut_copy, ..." on macOS/Linux. + link_prebuilt_bundled_deps(&lib_dir); Some(vec![lib_dir]) }