fix: Prefer GNU linux builds in install scripts for duckdb support, and gate duckdb support on linux hosts that are MUSL until MUSL support is added

This commit is contained in:
2026-08-28 20:06:39 -06:00
parent 50d2a74e80
commit 18c2cfeb41
4 changed files with 56 additions and 2 deletions
+23
View File
@@ -68,9 +68,32 @@ fn normalize_version(requested: Option<String>) -> Option<String> {
}
}
fn host_has_glibc() -> bool {
if process::Command::new("getconf")
.arg("GNU_LIBC_VERSION")
.output()
.is_ok_and(|out| out.status.success())
{
return true;
}
process::Command::new("ldd")
.arg("--version")
.output()
.is_ok_and(|out| {
let combined = format!(
"{}{}",
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
);
combined.to_lowercase().contains("glibc")
})
}
fn preferred_update_target() -> Option<&'static str> {
match (env::consts::OS, env::consts::ARCH) {
("linux", "x86_64") if host_has_glibc() => Some("x86_64-unknown-linux-gnu"),
("linux", "x86_64") => Some("x86_64-unknown-linux-musl"),
// No aarch64 gnu asset is published; musl is the only option.
("linux", "aarch64") => Some("aarch64-unknown-linux-musl"),
_ => None,
}
+6
View File
@@ -1869,6 +1869,12 @@ fn select_embedding_model(models: &[&Model]) -> Result<String> {
}
pub(crate) fn select_rag_driver() -> Result<String> {
// Statically linked musl builds cannot dlopen DuckDB extensions, so duckdb is not offered there.
#[cfg(target_env = "musl")]
let options = vec![
"yaml — portable, in-memory HNSW; usable from several Coyote processes at once (default)",
];
#[cfg(not(target_env = "musl"))]
let options = vec![
"yaml — portable, in-memory HNSW; usable from several Coyote processes at once (default)",
"duckdb — persistent on-disk store; vectors and content survive restarts; HNSW approximate search.",
+20 -1
View File
@@ -85,6 +85,21 @@ pub struct DuckDbProvider {
}
impl DuckDbProvider {
/// Fail fast on musl builds, before any filesystem or DuckDB work. Coyote's musl
/// builds are statically linked, and a statically linked binary cannot dlopen the
/// `vss`/`fts` extension shared objects, so this driver can never work there.
fn reject_musl() -> Result<()> {
#[cfg(target_env = "musl")]
bail!(
"The duckdb RAG driver is unavailable in this build of coyote: musl builds \
are statically linked, and a statically linked binary cannot load DuckDB \
extensions like `vss`/`fts` (dlopen is unsupported). Use the `qdrant` RAG \
driver instead, or a gnu-libc build of coyote."
);
#[cfg(not(target_env = "musl"))]
Ok(())
}
/// Open (or create) the DuckDB file. `dim` is the embedding vector dimension,
/// supplied by the caller who knows the model.
///
@@ -95,6 +110,7 @@ impl DuckDbProvider {
/// created or initialized here, or lazily through `ensure_writable` on the rebuild
/// path.
pub fn open(db_path: &Path, dim: usize) -> Result<Self> {
Self::reject_musl()?;
let (conn, writable) = Self::open_for_workload(db_path, dim)?;
// A reopened file may already carry a live FTS index from a previous session,
// in which case keyword search works immediately.
@@ -173,6 +189,7 @@ impl DuckDbProvider {
}
pub fn introspect_dim(db_path: &Path) -> Result<Option<usize>> {
Self::reject_musl()?;
if !db_path.exists() {
return Ok(None);
}
@@ -819,7 +836,9 @@ impl RagProvider for DuckDbProvider {
}
}
#[cfg(test)]
// Not compiled for musl: `open` bails there (statically linked binaries cannot dlopen
// the extension shared objects), so every test in this module would fail at setup.
#[cfg(all(test, not(target_env = "musl")))]
mod tests {
use super::*;
use crate::rag::provider::RagProvider;