Skip to content

Load libva at runtime via dlopen instead of linking#1

Merged
kixelated merged 1 commit into
mainfrom
claude/vaapi-dlopen-libva
Jul 23, 2026
Merged

Load libva at runtime via dlopen instead of linking#1
kixelated merged 1 commit into
mainfrom
claude/vaapi-dlopen-libva

Conversation

@kixelated

Copy link
Copy Markdown
Contributor

What

Switch the bindgen bindings from link-time extern "C" declarations to bindgen's dynamic-loading mode, so libva is dlopen'd at runtime rather than linked at build time.

  • bindgen_gen.rs: .dynamic_library_name("Va").dynamic_link_require_all(false) — bindgen emits a Va struct of libloading-resolved function pointers (77 va* wrappers) with zero extern "C" link blocks. require_all(false) lets a system libva older than the vendored headers still load (a missing symbol only errors if actually called).
  • build.rs: delete the pkg_config::probe("libva"/"libva-drm") block. No link step; the build needs only libclang + the vendored headers.
  • src/bindings.rs: a OnceLock-cached load()/va() accessor over libloading. It dlopens libva-drm.so.2, whose NEEDED libva.so.2 exposes the core va* symbols via dlsym's dependency search, so one load covers both vaGetDisplayDRM and the rest.
  • display.rs: Display::open_drm_display calls load() up front and returns a new OpenDrmDisplayError::LibvaUnavailable on failure, so a libva-less host falls back gracefully (Display::open()None) instead of aborting at process load.
  • The 40 bindings::vaFoo( call sites now go through bindings::va().vaFoo(.
  • Cargo.toml: add libloading, drop the pkg-config build-dep.

Why

build.rs probed libva/libva-drm via pkg-config whenever the target OS was Linux, which (a) required libva-dev at build time and (b) made the binary hard-link libva.so.2, so a libva-less host failed to load rather than falling back. It also broke the docs.rs build (docs.rs builds on Linux with no libva-dev), which is what surfaced this. This is the fix tracked in moq #1837, and the flake.nix comment already described this intended behavior ("libva is dlopen'd at runtime, not linked at build") — the code now matches it.

Testing

Verified on an aarch64 Linux host with no libva installed (rust + clang only):

  • Builds clean with no libva-dev / pkg-config (the docs.rs condition).
  • The probe binary has no NEEDED libva (ldd) — dlopen, not link.
  • libva absent → open_drm_display returns Err(LibvaUnavailable("libva-drm.so.2: cannot open shared object file")), Display::open()None, exit 0, no panic.
  • After installing the libva runtime libs (libva2/libva-drm2, no -dev), the probe clears load() and fails later at device open — confirming the dlopen resolves — and still falls back cleanly.

Not tested: a real VAAPI hardware encode. That needs an x86 host with a working Intel/AMD driver; the test host is ARM with no GPU. Worth a smoke encode before publishing 0.0.3.

Follow-up (not in this PR)

Publish as moq-vaapi 0.0.3, then in the moq monorepo bump moq-vaapi = "0.0.3", correct the stale "hard-links libva" comments in rs/moq-video/Cargo.toml, and drop the temporary [package.metadata.docs.rs] stopgap so docs.rs documents the vaapi feature again.

🤖 Generated with Claude Code

(written by Opus 4.8)

Switch the bindgen bindings to dynamic-loading mode so libva is dlopen'd
at runtime instead of linked at build time. The build no longer depends
on libva at all (only libclang plus the vendored headers), and the
resulting binary carries no NEEDED libva, so it loads on a libva-less
host and the caller can fall back to another encoder.

Previously build.rs probed libva/libva-drm via pkg-config whenever the
target OS was Linux, which required libva-dev at build time and made the
binary hard-link libva.so.2. It also broke the docs.rs build, since
docs.rs builds on Linux with no libva-dev installed.

- bindgen_gen.rs: dynamic_library_name("Va") + dynamic_link_require_all(false)
- build.rs: drop the pkg-config link step
- src/bindings.rs: OnceLock-cached load()/va() over libloading. Load
  libva-drm.so.2, whose NEEDED libva.so.2 exposes the core va* symbols
  through dlsym's dependency search.
- Display::open_drm_display loads libva up front and returns a new
  LibvaUnavailable error, so a libva-less host falls back gracefully
  instead of aborting at process load.
- rewrite the 40 va* call sites through the loaded accessor
- Cargo.toml: add libloading, drop the pkg-config build-dep

Tested on an aarch64 Linux host with no libva installed: the crate
builds with rust + clang only, the probe binary has no NEEDED libva, and
Display::open() returns None gracefully. Installing the libva runtime
libs advances past load() (dlopen resolves) and still falls back cleanly.
Real VAAPI hardware encode is unverified (needs an x86 box with a driver).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @kixelated, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@kixelated, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 54 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c0833ce2-3785-4660-8c8c-ed896aac7d41

📥 Commits

Reviewing files that changed from the base of the PR and between f6ee901 and 8bdc664.

📒 Files selected for processing (12)
  • Cargo.toml
  • bindgen_gen.rs
  • build.rs
  • src/bindings.rs
  • src/buffer.rs
  • src/config.rs
  • src/context.rs
  • src/display.rs
  • src/image.rs
  • src/lib.rs
  • src/picture.rs
  • src/surface.rs
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/vaapi-dlopen-libva

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

1 similar comment
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@kixelated, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 54 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c0833ce2-3785-4660-8c8c-ed896aac7d41

📥 Commits

Reviewing files that changed from the base of the PR and between f6ee901 and 8bdc664.

📒 Files selected for processing (12)
  • Cargo.toml
  • bindgen_gen.rs
  • build.rs
  • src/bindings.rs
  • src/buffer.rs
  • src/config.rs
  • src/context.rs
  • src/display.rs
  • src/image.rs
  • src/lib.rs
  • src/picture.rs
  • src/surface.rs
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/vaapi-dlopen-libva

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kixelated
kixelated merged commit f005e8d into main Jul 23, 2026
2 checks passed
@kixelated
kixelated deleted the claude/vaapi-dlopen-libva branch July 23, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant