Skip to content

v0.45.0

@mgottscho mgottscho tagged this 01 May 18:56
# Problem

`xlsynth-sys` downloads managed `libxls` DSOs into its Cargo `OUT_DIR`
and emits native link directives pointing at that directory. This works
for linking, but it is not enough for all Cargo runtime cases.

In particular, downstream crates can use `xlsynth`/`xlsynth-sys` from
their own `build.rs`. Cargo successfully links those build-script
executables against the downloaded `libxls` DSO, but when Cargo later
runs the build script, the dynamic loader may not search the
`xlsynth-sys` `OUT_DIR`. The result is a runtime loader failure like:

```text
error while loading shared libraries: libxls-...so: cannot open shared object file: No such file or directory
```

This can happen even though the DSO was downloaded correctly and linking
succeeded, because the DSO is only present in the sys crate build output
directory, not in a loader-visible Cargo runtime directory.

## Minimal Repro

This issue can be reproduced with a tiny downstream crate whose
`build.rs` depends on `xlsynth`. The important part is that Cargo must
run a host build-script executable that links against the managed
`libxls` DSO downloaded by `xlsynth-sys`.

From a checkout of this repo:

```bash
XLSYNTH_REPO="$PWD"

rm -rf /tmp/xlsynth-buildrs-repro
mkdir -p /tmp/xlsynth-buildrs-repro/src

cat > /tmp/xlsynth-buildrs-repro/Cargo.toml <<EOF
[package]
name = "xlsynth-buildrs-repro"
version = "0.1.0"
edition = "2021"
build = "build.rs"

[build-dependencies]
xlsynth = { path = "$XLSYNTH_REPO/xlsynth" }
EOF

cat > /tmp/xlsynth-buildrs-repro/build.rs <<'EOF'
fn main() {
    let _ = xlsynth::xls_parse_typed_value("bits[8]:42").unwrap();
}
EOF

cat > /tmp/xlsynth-buildrs-repro/src/lib.rs <<'EOF'
pub fn marker() {}
EOF

cd /tmp/xlsynth-buildrs-repro
env -u LD_LIBRARY_PATH cargo clean
env -u LD_LIBRARY_PATH cargo check
```

Before this fix, the final command can fail when Cargo runs the
downstream build script:

```text
error while loading shared libraries: libxls-...so: cannot open shared object file: No such file or directory
```

The failure happens even though linking succeeded, because the managed
DSO lives in `xlsynth-sys`’s `OUT_DIR`, which is not reliably searched
by the dynamic loader when Cargo later starts a downstream build-script
executable.

After this fix, the same command succeeds with `LD_LIBRARY_PATH` unset.
That verifies the intended long-term behavior: managed DSOs are staged
into Cargo’s profile `deps` directory, which Cargo already makes
available when running host executables such as build scripts, without
requiring CI-specific or user-specific environment setup.

As an additional sanity check after the successful build, reviewers can
confirm that the managed DSO was staged where Cargo-run host executables
can find it:

```bash
find target/debug/deps -maxdepth 1 -name 'libxls-*' -print
```

# Solution

Stage managed `libxls` DSOs into Cargo’s profile `deps` directory in
addition to keeping them in `xlsynth-sys`’s `OUT_DIR`.

Cargo already includes `target/<profile>/deps` in the dynamic library
search path when it runs Cargo-built host executables such as build
scripts. Placing the managed DSO there makes downstream build-script
executables able to start without requiring users or CI to manually set
`LD_LIBRARY_PATH`.

The change applies to managed DSOs from both the default download flow
and the `DEV_XLS_DSO_WORKSPACE` flow. On Unix, the DSO is symlinked into
`deps`; on non-Unix platforms, it is copied. Stale staged files or
symlinks are replaced.

The README is also updated to clarify that default downloaded artifacts
are staged automatically, while manually supplied `XLS_DSO_PATH` /
`DSLX_STDLIB_PATH` artifacts may still require the caller to make the
DSO discoverable at build/test runtime.


Co-authored-by: Codex noreply@openai.com
Assets 2
Loading