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
6 changes: 3 additions & 3 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ codecov:
require_ci_to_pass: false

ignore:
- **benches/*
- **examples/*
- **tests/*
- benches/*
- examples/*
- tests/*

coverage:
status:
Expand Down
85 changes: 52 additions & 33 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ jobs:
- name: Install cargo-hack
run: cargo install cargo-hack
- name: Apply clippy lints
run: cargo hack clippy --each-feature --exclude-no-default-features
# Skip the opt-in EP features (`cuda`, `tensorrt`, `directml`,
# `rocm`, `coreml`) — those activate `ort/<ep>`, which requires
# the corresponding vendor SDK at build time. Standard CI runners
# don't have CUDA / TensorRT / ROCm installed, and `directml` /
# `coreml` are platform-restricted.
run: cargo hack clippy --each-feature --exclude-no-default-features --exclude-features cuda,tensorrt,directml,rocm,coreml

# Run tests on some extra platforms
cross:
Expand Down Expand Up @@ -94,9 +99,19 @@ jobs:
- name: Install Rust
run: rustup update stable && rustup default stable
- name: cargo build --target ${{ matrix.target }}
# The cross matrix verifies the no-inference subset (the
# `Embedding`, `Options`, `Error` types) compiles on every
# listed target, including wasm32-* and tier-2/3 native
# platforms where ort prebuilds aren't available. The default
# `inference` feature pulls `ort` + `tokenizers`, neither of
# which targets wasm or most non-tier-1 native targets, so
# passing default features here would only re-fail the build
# in their C/FFI prereqs. The native inference path is
# exercised by the `build` / `test` jobs below on
# ubuntu-latest / macos-latest / windows-latest.
run: |
rustup target add ${{ matrix.target }}
cargo build --target ${{ matrix.target }}
cargo build --target ${{ matrix.target }} --no-default-features
Comment on lines 112 to +114

build:
name: build
Expand Down Expand Up @@ -125,7 +140,8 @@ jobs:
- name: Install cargo-hack
run: cargo install cargo-hack
- name: Run build
run: cargo hack build --feature-powerset --exclude-no-default-features
# See the clippy job for why the EP features are excluded.
run: cargo hack build --feature-powerset --exclude-no-default-features --exclude-features cuda,tensorrt,directml,rocm,coreml

test:
name: test
Expand Down Expand Up @@ -153,8 +169,33 @@ jobs:
run: rustup update stable --no-self-update && rustup default stable
- name: Install cargo-hack
run: cargo install cargo-hack
- name: Run test
run: cargo hack test --feature-powerset --exclude-no-default-features --exclude-features loom
# Linux / macOS: full feature-powerset minus the EP features (see
# the clippy job for that exclusion). `--exclude-no-default-features`
# is intentionally NOT set so the powerset also runs the
# `--no-default-features` and `--no-default-features --features serde`
# combos — those exercise the cfg-gated `serde` derive paths in
# `src/options.rs` that the default-features build can't reach.
- name: Run test (Linux/macOS)
if: runner.os != 'Windows'
run: cargo hack test --feature-powerset --exclude-features cuda,tensorrt,directml,rocm,coreml
# Windows: also exclude `inference` and `default`. ORT's prebuilt
# binary on `x86_64-pc-windows-msvc` is linked against the dynamic
# CRT (`/MD`), but the C/C++ build scripts in `tokenizers` deps
# (`onig_sys`, `esaxx-rs`) link the static CRT (`/MT`). When both
# end up in the same test executable — and `cargo test` compiles
# examples like `embed_text.rs` that link ort + tokenizers — MSVC
# emits `LNK2038` ("RuntimeLibrary mismatch") and the link aborts.
# `default` is excluded because it implies `inference`.
#
# This is an upstream dependency mismatch, not something this crate
# can resolve in its own code. The `build` and `clippy` Windows
# jobs above still compile the crate end-to-end (no final link),
# so lib-level regressions a Windows test binary would catch are
# still caught. The `inference` path is exercised on the Linux and
# macOS runners.
- name: Run test (Windows — skip inference due to MSVC CRT conflict)
if: runner.os == 'Windows'
run: cargo hack test --feature-powerset --exclude-features cuda,tensorrt,directml,rocm,coreml,inference,default

sanitizer:
name: sanitizer
Expand Down Expand Up @@ -250,32 +291,6 @@ jobs:
run: |
bash ci/miri_sb.sh "${{ matrix.target }}"

loom:
name: loom
strategy:
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- name: Cache cargo build and registry
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-loom-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-loom-
- name: Install Rust
run: rustup update nightly --no-self-update && rustup default nightly
- name: Loom tests
run: cargo test --tests --features loom

# valgrind:
# name: valgrind
# runs-on: ubuntu-latest
Expand Down Expand Up @@ -315,7 +330,6 @@ jobs:
- cross
- test
- sanitizer
- loom
steps:
- uses: actions/checkout@v6
- name: Install Rust
Expand All @@ -335,7 +349,12 @@ jobs:
- name: Run tarpaulin
env:
RUSTFLAGS: "--cfg tarpaulin"
run: cargo tarpaulin --all-features --run-types tests --run-types doctests --workspace --out xml
# `--all-features` would activate `cuda` / `tensorrt` / `rocm`
# / `directml` / `coreml`, which require the corresponding
# vendor SDKs to compile — see the clippy job. Cover only the
# features that actually compile on a stock ubuntu-latest
# runner.
run: cargo tarpaulin --features inference,serde --run-types tests --run-types doctests --workspace --out xml
- name: Upload to codecov.io
uses: codecov/codecov-action@v6
with:
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@

/target
Cargo.lock

**.claude/
docs/

10 changes: 6 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# UNRELEASED
# Changelog

# 0.1.2 (January 6th, 2022)

FEATURES
All notable changes to `egemma` will be documented in this file. The
format is loosely based on [Keep a Changelog](https://keepachangelog.com/),
and the project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

Initial release. See `Cargo.toml` for the public surface.
151 changes: 115 additions & 36 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,48 +1,127 @@
[package]
name = "template-rs"
version = "0.0.0"
edition = "2021"
repository = "https://github.com/al8n/template-rs"
homepage = "https://github.com/al8n/template-rs"
documentation = "https://docs.rs/template-rs"
description = "A template for creating Rust open-source repo on GitHub"
license = "MIT OR Apache-2.0"
rust-version = "1.73"

[[bench]]
path = "benches/foo.rs"
name = "foo"
harness = false

[features]
default = ["std"]
alloc = []
std = []
name = "egemma"
version = "0.1.0"
edition = "2024"
rust-version = "1.95"
description = "Rust ONNX inference library for Google's EmbeddingGemma (text embeddings)"
license = "MIT OR Apache-2.0"
repository = "https://github.com/Findit-AI/egemma"
keywords = ["embedding-gemma", "gemma", "embedding", "onnx", "ml"]
categories = ["science"]
include = [
"src/**/*.rs",
"examples/**/*.rs",
"Cargo.toml",
"README.md",
"CHANGELOG.md",
Comment on lines +15 to +16
"LICENSE-*",
]

[dependencies]
# `ort` and `tokenizers` are gated on the `inference` feature so the
# crate compiles for wasm32 (where neither builds today — `ort` needs
# native ONNX Runtime FFI and `tokenizers` pulls `onig_sys` /
# `esaxx-rs` which lack wasm targets). Without `inference` the crate
# exposes the `Embedding` type, the `Options` surface, and the error
# enum — useful in environments where inference happens elsewhere.
ort = { version = "2.0.0-rc.12", optional = true }
tokenizers = { version = "0.23", optional = true }
thiserror = "2"
# `serde` is opt-in: most consumers use `egemma` purely as an inference
# library and don't need to (de)serialize `Options`. Pulling serde
# unconditionally adds compile time and binary size for no benefit on
# the common path. Mirrors the `silero` pattern — gate the dependency,
# the `derive(Serialize, Deserialize)` calls, and every field-level
# `#[serde(...)]` attribute on `feature = "serde"`.
serde = { version = "1", features = ["derive"], optional = true }

[dev-dependencies]
criterion = "0.8"
tempfile = "3"
serde_json = "1"

# =====================================================================
# Target / feature contract.
#
# Default features include `inference`, which pulls `ort` + `tokenizers`.
# Both require native build scripts (`ort` needs ONNX Runtime FFI;
# `tokenizers` pulls `onig_sys` / `esaxx-rs`, which fail on wasm32
# because their C deps don't have wasm targets).
#
# **Wasm builds must use `--no-default-features`.** Building wasm with
# default features fails inside `getrandom` / `onig_sys` long before
# this crate's code is ever touched, with a confusing C-toolchain
# error. The `--no-default-features` build compiles the `Embedding`,
# `Options`, and `Error` subset — useful when inference happens
# elsewhere (a server, a different runtime). This mirrors the
# `siglip2` pattern: native = inference by default; wasm = explicit
# opt-out, no-inference subset.
#
# CI / build-matrix consumers: gate the wasm job on
# `--no-default-features`, e.g.
# `cargo check --target wasm32-unknown-unknown --no-default-features`.
# =====================================================================
[features]
default = ["inference"]
# Activates the ONNX-backed inference path (`TextEncoder`). Native
# targets only — see the target / feature contract block above for the
# wasm escape hatch.
inference = ["dep:ort", "dep:tokenizers"]
# Pulls the `serde` dependency and activates `Serialize` / `Deserialize`
# on `Options`, `BatchOptions`, and `ThreadOptions`. `Embedding`
# deliberately does NOT carry these derives — round-trip via the inner
# slice (see `Embedding` docs) so the dim and L2-norm invariants that
# `TryFrom<Vec<f32>>` exists to enforce can't be bypassed.
serde = ["dep:serde"]

# ----- Opt-in execution providers --------------------------------------
#
# Feature names mirror ort's own EP feature flags so a downstream
# consumer can reason about both crates with the same vocabulary
# (`egemma/cuda` ↔ `ort/cuda`, etc.). Each feature activates the
# corresponding ort sub-feature so the prebuilt ONNX Runtime that
# gets linked includes that EP, and `session::build_session`
# cfg-registers the EP at session-build time. None are enabled by
# default — see `siglip2/Cargo.toml` for the measurement methodology.
cuda = ["inference", "ort/cuda"]
tensorrt = ["inference", "ort/tensorrt"]
directml = ["inference", "ort/directml"]
rocm = ["inference", "ort/rocm"]
coreml = ["inference", "ort/coreml"]

[[test]]
name = "integration"
path = "tests/integration.rs"
required-features = ["inference"]

[[example]]
name = "embed_text"
path = "examples/embed_text.rs"
required-features = ["inference"]

[profile.bench]
opt-level = 3
debug = false
codegen-units = 1
lto = 'thin'
incremental = false
debug-assertions = false
overflow-checks = false
rpath = false
opt-level = 3
debug = false
codegen-units = 1
lto = 'thin'
incremental = false
debug-assertions = false
overflow-checks = false
rpath = false

[package.metadata.docs.rs]
all-features = true
# `all-features = true` would activate the opt-in execution-provider
# features (`cuda`, `tensorrt`, `directml`, `rocm`, `coreml`), each of
# which requires the corresponding vendor SDK at build time. docs.rs's
# Linux builder doesn't have any of them, so `all-features` would fail
# the docs build even when the actual code on docs.rs is fine. List
# the features that compile on a stock Linux runner; EP-specific docs
# coverage would need a separately provisioned builder.
features = ["inference", "serde"]
rustdoc-args = ["--cfg", "docsrs"]

[lints.rust]
rust_2018_idioms = "warn"
[lints]
workspace = true

[workspace.lints.rust]
rust_2018_idioms = "warn"
single_use_lifetimes = "warn"
unexpected_cfgs = { level = "warn", check-cfg = [
'cfg(all_tests)',
'cfg(tarpaulin)',
] }
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(all_tests)', 'cfg(tarpaulin)', 'cfg(docsrs)'] }
Loading
Loading