Trying to link static FFmpeg. Linker refuses to find Libsvtav1
⚓ Rust 📅 2026-02-19 👤 surdeus 👁️ 1Hi,
I'm new to Rust having come from C++ and many others. Jack of several trades but master of none, if you will.
I read the book cover-to-cover, now trying to get on my feet and running into a baffling issue. Before I get into it I would like to disclose that I'm totally blind. Please forgive me if there are formatting issues as a result.
I want to use FFmpeg's underlying libraries (Libavcodec and friends). I built a static FFmpeg myself, used bindgen to generate bindings just to AVFormatContext so far, and linked it with the help of the pkg-config crate. This is after having tried both the rusty_ffmpeg and ffmpeg-next crates with the same results as described below.
Long story short: all of the libraries seem to link fine except for Libsvt-av1, despite it being present and accounted for according to pkg-config. At this point I'd be more than happy to PayPal someone a few bucks for some troubleshooting as I simply can't fathom what makes Libsvtav1 special as compared to numerous other FFmpeg dependencies.
This is my current cargo.toml:
[package]
name = "cvc_encoder"
version = "0.1.0"
edition = "2024"
[dependencies]
[build-dependencies]
bindgen = "0.72.1"
pkg-config = "0.3.32"
build.rs:
use std::env;
use std::path::PathBuf;
fn main() {
let mut pkg_config = pkg_config::Config::new();
pkg_config.atleast_version("1.8.1");//Ubuntu 24.04.4.
pkg_config.statik(true);
pkg_config.probe("libavformat")
.unwrap();
let bindings = bindgen::Builder::default()
.header("wrapper.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.allowlist_item("AVFormatContext")
.allowlist_item("avformat_open_input")
.allowlist_item("av_strerror")
.generate()
.expect("Unable to generate bindings.");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}
Finally, src/ffmpeg/output.rs has the attempted call to avformat_open_input:
use crate::ffmpeg::sys;
pub struct Output {
//todo.
}
impl Output {
pub fn open(url: &str) -> Output {
let mut format_context: *mut sys::AVFormatContext = std::ptr::null_mut();
let c_url = std::ffi::CString::new(url).unwrap();
unsafe {
let result = sys::avformat_open_input(&raw mut format_context, c_url.as_ptr(), std::ptr::null(), std::ptr::null_mut());//Linker finds everything this needs except Libsvtav1.
//Prevent unused variable warning with a println for now.
println!("The result is... {result}!");
}
Output {}
}
}
Attempting to build this, I get undefined references to Libsvtav1:
= note: rust-lld: error: undefined symbol: svt_metadata_array_free
>>> referenced by libsvtav1.c:419 (libavcodec/libsvtav1.c:419)
>>> libsvtav1.o:(eb_receive_packet) in archive /home/caturria/cvc_encoder/target/debug/deps/libcvc_encoder-8be554e9bd5758bb.rlib
>>> referenced by libsvtav1.c:680 (libavcodec/libsvtav1.c:680)
>>> libsvtav1.o:(eb_enc_close) in archive /home/caturria/cvc_encoder/target/debug/deps/libcvc_encoder-8be554e9bd5758bb.rlib
rust-lld: error: undefined symbol: svt_add_metadata
>>> referenced by libsvtav1.c:545 (libavcodec/libsvtav1.c:545)
>>> libsvtav1.o:(eb_receive_packet) in archive /home/caturria/cvc_encoder/target/debug/deps/libcvc_encoder-8be554e9bd5758bb.rlib
rust-lld: error: undefined symbol: svt_av1_enc_get_packet
>>> referenced by libsvtav1.c:610 (libavcodec/libsvtav1.c:610)
>>> libsvtav1.o:(eb_receive_packet) in archive /home/caturria/cvc_encoder/target/debug/deps/libcvc_encoder-8be554e9bd5758bb.rlib
My PKG_CONFIG_PATH environment variable correctly points to my local FFmpeg build:
caturria@LAPTOP-P14K8RUP:~/cvc_encoder$ echo $PKG_CONFIG_PATH
/home/caturria/ffmpeg_build/output/lib/pkgconfig
Svtav1Enc is correctly registered as a dependency:
caturria@LAPTOP-P14K8RUP:~/cvc_encoder$ pkg-config --static --libs libavformat
-L/home/caturria/ffmpeg_build/output/lib -lavformat -lavcodec -L/home/caturria/ffmpeg_build/output/lib/x86_64-linux-gnu -ldav1d -ldl -lmp3lame -lopus -lSvtAv1Enc
-lvorbisenc -lvorbis -logg -lx264 -lpthread -lz -lswresample -lavutil -lm -lssl -lcrypto -ldl -latomic -pthread
SvtAv1Enc itself is present and accounted for:
caturria@LAPTOP-P14K8RUP:~/cvc_encoder$ pkg-config --static --libs SvtAv1Enc
-L/home/caturria/ffmpeg_build/output/lib -lSvtAv1Enc -lpthread -lm
I performed the exact same test in C and it links just fine:
#include <libavformat/avformat.h>
int main(int, const char *[]) {
avformat_open_input(NULL, NULL, NULL, NULL);//Obviously a bad call, but good enough to prove that link dependencies are present and accounted for.
}
Simple makefile:
all:
cc `pkg-config --cflags libavformat` test.c -o test `pkg-config --libs libavformat`
This links perfectly fine and results in a 41MB binary as expected.
Finally, I tried linking SvtAv1Enc explicitly after Libavformat and its dependencies, but this too yielded the same result:
pkg_config.probe("SvtAv1Enc")
.unwrap();
Any help is greatly appreciated, and I'm more than happy to offer some compensation. I can usually figure things out given enough elbow grease, but this one's got me beat. Libsvtav1 doesn't seem like it should be special in any way that would explain why I can link it just fine when building with gcc and the exact same flags, but not Rust/ Cargo on the same machine with the same linker.
Thanks in advance!
1 post - 1 participant
🏷️ Rust_feed