Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,22 @@ jobs:
run: cargo run --example basic
shell: bash

- name: Downstream rpath smoke (self-contained binary)
# Build a downstream binary that wires zvec-rust-build from its build.rs,
# then execute it directly with every dylib search-path variable
# cleared. This fails unless the emitted rpath (@executable_path /
# $ORIGIN) plus the staged shared library make the executable
# self-contained — the case plain `cargo run` cannot prove, because
# Cargo injects the library directory into its own child's environment.
run: |
cargo build -p zvec-rpath-smoke
BIN="target/debug/zvec-rpath-smoke"
if [ "${{ runner.os }}" = "Windows" ]; then
BIN="target/debug/zvec-rpath-smoke.exe"
fi
env -u DYLD_LIBRARY_PATH -u DYLD_FALLBACK_LIBRARY_PATH -u LD_LIBRARY_PATH "$BIN"
shell: bash

audit:
name: Security Audit
needs: check-and-test
Expand Down
16 changes: 15 additions & 1 deletion .github/workflows/publish-crates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,31 @@ jobs:

SYS_VERSION=$(extract_version zvec-sys/Cargo.toml)
SDK_VERSION=$(extract_version zvec/Cargo.toml)
BUILD_VERSION=$(extract_version zvec-build/Cargo.toml)

if [ "$SYS_VERSION" != "$VERSION" ] || [ "$SDK_VERSION" != "$VERSION" ]; then
if [ "$SYS_VERSION" != "$VERSION" ] || [ "$SDK_VERSION" != "$VERSION" ] || [ "$BUILD_VERSION" != "$VERSION" ]; then
echo "Version mismatch!"
echo " Tag: $VERSION"
echo " zvec-rust-sys: $SYS_VERSION"
echo " zvec-rust: $SDK_VERSION"
echo " zvec-rust-build: $BUILD_VERSION"
exit 1
fi
echo "All versions match: $VERSION"
shell: bash

- name: Dry-run publish zvec-rust-build
# Pure build-script helper with no dependencies and no link to the C
# library, so it can be published first and independently.
run: cargo publish -p zvec-rust-build --dry-run
shell: bash

- name: Publish zvec-rust-build to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish -p zvec-rust-build
shell: bash

- name: Dry-run publish zvec-rust-sys
run: cargo publish -p zvec-rust-sys --dry-run
shell: bash
Expand Down
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["zvec-sys", "zvec"]
members = ["zvec-sys", "zvec", "zvec-build", "zvec-rpath-smoke"]
exclude = ["fuzz"]
resolver = "2"

Expand Down
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,39 @@ The Rust SDK depends on the zvec C library (`libzvec_c_api`). Choose one of the

### Option 1: Bundled Prebuilt Library (Zero Setup)

Add `zvec-rust` to your `Cargo.toml`. The default `bundled` feature automatically downloads the prebuilt `libzvec_c_api` for your platform from [GitHub Releases](https://github.com/zvec-ai/zvec-rust/releases) and sets up the library path via `rpath`:
Add `zvec-rust` to your `Cargo.toml`. The default `bundled` feature automatically downloads the prebuilt `libzvec_c_api` for your platform from [GitHub Releases](https://github.com/zvec-ai/zvec-rust/releases):

```toml
[dependencies]
zvec-rust = "0.7.1"
```

`cargo run` / `cargo test` work out of the box because Cargo passes the
resolved library directory to the linker for you. A **directly executed** or
**deployed** binary, however, needs a runtime search path (`rpath`) pointing at
the shared library — Cargo does not add one automatically. Use the
[`zvec-rust-build`](https://crates.io/crates/zvec-rust-build) build-script
helper from your binary crate to emit the `rpath` and stage the library beside
the executable:

```toml
[dependencies]
zvec-rust = "0.7.1"

[build-dependencies]
zvec-rust-build = "0.7.1"
```

```rust
// build.rs
fn main() {
zvec_rust_build::configure();
}
```

Without the helper you must instead set `DYLD_LIBRARY_PATH` (macOS) /
`LD_LIBRARY_PATH` (Linux) at runtime.

### Option 2: Custom Build

If you want to build the zvec C library yourself (e.g., for a custom configuration or unsupported platform), set the `ZVEC_LIB_DIR` environment variable:
Expand Down
25 changes: 24 additions & 1 deletion README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,36 @@ Rust SDK 依赖 zvec C 库(`libzvec_c_api`)。可通过以下任一方式提

### 方案一: bundled 预编译库(零配置)

在 `Cargo.toml` 中添加 `zvec-rust`。默认启用的 `bundled` feature 会自动从 [GitHub Releases](https://github.com/zvec-ai/zvec-rust/releases) 下载适合你平台的预编译 `libzvec_c_api`,并通过 `rpath` 设置库路径
在 `Cargo.toml` 中添加 `zvec-rust`。默认启用的 `bundled` feature 会自动从 [GitHub Releases](https://github.com/zvec-ai/zvec-rust/releases) 下载适合你平台的预编译 `libzvec_c_api`:

```toml
[dependencies]
zvec-rust = "0.7.1"
```

`cargo run` / `cargo test` 可开箱即用,因为 Cargo 会把解析出的库目录传给链接器。
但**直接执行**或**部署后**的二进制需要一条指向共享库的运行时搜索路径(`rpath`),
而 Cargo 不会自动添加。请在你的二进制 crate 中使用
[`zvec-rust-build`](https://crates.io/crates/zvec-rust-build) 构建脚本助手,
它会生成 `rpath` 并把共享库暂存到可执行文件旁边:

```toml
[dependencies]
zvec-rust = "0.7.1"

[build-dependencies]
zvec-rust-build = "0.7.1"
```

```rust
// build.rs
fn main() {
zvec_rust_build::configure();
}
```

若不使用该助手,则需在运行时设置 `DYLD_LIBRARY_PATH`(macOS)/ `LD_LIBRARY_PATH`(Linux)。

### 方案二:自行编译

如果你需要自行编译 zvec C 库(例如自定义配置或不支持的平台),设置 `ZVEC_LIB_DIR` 环境变量:
Expand Down
11 changes: 11 additions & 0 deletions zvec-build/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "zvec-rust-build"
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
description = "Build-script helper for downstream binaries linking against zvec-rust: emits the runtime rpath and stages the shared library."
readme = "README.md"
keywords = ["build-dependencies", "rpath", "zvec", "ffi", "bindings"]
categories = ["development-tools::build-utils"]
42 changes: 42 additions & 0 deletions zvec-build/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# zvec-rust-build

Build-script helper for downstream **binary** crates that link against
[`zvec-rust`](https://crates.io/crates/zvec-rust).

`zvec-rust` loads the `libzvec_c_api` shared library at runtime. Cargo does not
configure a runtime search path (`rpath`) on the final executable by itself, so
without help the binary can only find the library through `DYLD_LIBRARY_PATH`
(macOS) or `LD_LIBRARY_PATH` (Linux).

Add this crate as a build dependency and call it from your `build.rs`:

```toml
[build-dependencies]
zvec-rust-build = "0.7"
```

```rust
// build.rs
fn main() {
zvec_rust_build::configure();
}
```

`configure()`:

- Emits `rpath` linker arguments so the executable finds the shared library
both next to itself (development: `target/<profile>/`) and in a sibling
`../lib` directory (deployment layout `bin/<exe>` + `lib/<shared library>`).
- Stages the shared library beside the executable in `target/<profile>/`, so
`./target/<profile>/<exe>` runs with no environment variables set.

On Windows there is no `rpath`; the loader searches the executable's directory,
so staging the DLL beside the executable is what makes development runs work,
and packaging must ship `zvec_c_api.dll` in the same directory as the
executable.

## Packaging helpers

`lib_dir()` returns the resolved library directory and
`copy_runtime_libs_to(dst)` stages the runtime shared library into an arbitrary
directory — useful for assembling a distribution tree.
Loading
Loading