Trying to link static FFmpeg. Linker refuses to find Libsvtav1

⚓ Rust    📅 2026-02-19    👤 surdeus    👁️ 1      

surdeus

Hi,

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

Read full topic

🏷️ Rust_feed