Trying to link static FFmpeg. Linker refuses to find Libsvtav1

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!

I'm having the exact same issue, did you find out what's going on?

when debugging linking issues, first check the actual linker invocation using the --print link-args rustc flag, e.g.:

$ RUSTFLAGS='--print link-args' cargo build

Yes actually.
I don't know why it's happening, but for some reason static Libsvtav1 built with GCC / LD has symbols that LLD doesn't recognize. Build everything with Clang/ LLD (especially Libsvtav1) and it will link.