Linking against ffmpeg libs on Rust gives `vdp_device_create_x11` (libvdpau-dev missing?)

I'm trying to link against ffmpeg libraries, in rust, and getting as the only error:

undefined reference to `vdp_device_create_x11'

Here's the libs linked:

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rustc-link-lib=static=z");
    println!("cargo:rustc-link-lib=dylib=dl");
    println!("cargo:rustc-link-lib=static=X11");
    println!("cargo:rustc-link-lib=dylib=vdpau");
    println!("cargo:rustc-link-lib=dylib=va");
    println!("cargo:rustc-link-lib=dylib=va-drm");
    println!("cargo:rustc-link-lib=dylib=va-x11");
    println!("cargo:rustc-link-lib=dylib=xcb");
}

On C++ I used to link with all these libs above + some for GTK and it worked. Don't know why it wont work now.

On https://stackoverflow.com/questions/38850260/errors-when-compiling-c-code-with-ffmpeg-library it says that I should link against -lvdpau - libvdpau-dev

I tried adding

    println!("cargo:rustc-link-lib=dylib=vdpau-dev");

but I get

  = note: /usr/bin/ld: cannot find -lvdpau-dev

Even though I installed libvdpau-dev. Indeed,

ldconfig -p | grep vdpau
        libvdpau.so.1 (libc6,x86-64) => /lib/x86_64-linux-gnu/libvdpau.so.1
        libvdpau.so (libc6,x86-64) => /lib/x86_64-linux-gnu/libvdpau.so

Why libdpau-dev is missing? I'm on ubuntu 20, apt-get install -y libdpau-dev. Finny thing is that C++ compiles perfectly in this same docker container without any modifications and without libdpau-dev

nm -D /lib/x86_64-linux-gnu/libvdpau.so | grep x11
0000000000001d50 T vdp_device_create_x11

On Debian-based systems (including Ubuntu), every C library package has a separate dev package for headers and other development files. For example:

  • libvdpau1 contains files needed at run time by programs that use VDPAU.
  • libvdpau-dev contains files needed at build time when compiling programs that use VDPAU.

The correct linker argument is -lvdpau, and your build script that uses dylib=vdpau is correct.

I was not able to reproduce your link error, on Ubuntu 20.04. Can you provide a reproducible test case? I copied your build script into a new Cargo project, and installed the required packages:

sudo apt install libvdpau-dev libva-dev libx11-dev zlib1g-dev

Then I put the following code into main.rs:

extern {
    fn vdp_device_create_x11(
        display: *const u8,
        screen: i32,
        device: *const u8,
        get_proc_address: *const u8,
    )-> i32;
}

fn main() {
    unsafe {
        vdp_device_create_x11(0 as _, 0, 0 as _, 0 as _);
    }
}

The program builds successfully:

$ cargo build
   Compiling ff v0.1.0 (/home/mbrubeck/src/test/ff)
    Finished dev [unoptimized + debuginfo] target(s) in 0.47s

Also, note that the order of the linker arguments is important. You might need to move the vdpau line below some other library that depends on it.

I'll try to provide a minimal reproducible example. Meanwhile, here's a more detailed error:

note: /usr/bin/ld: /home/dev/orwell/liborwell_rust/target/debug/deps/libffmpeg_sys_next-109176c9182219d2.rlib(hwcontext_vdpau.o): in function `vdpau_device_create':
          hwcontext_vdpau.c:(.text+0x686): undefined reference to `vdp_device_create_x11'

The file hwcontext_vdpau.o is from ffmpeg: https://ffmpeg.org/doxygen/trunk/hwcontext__vdpau_8c_source.html

My theory of why it worked for your case but not mine is that in your case you link these libraries after the code that uses vdp_device_create_x11. In my case, I think it links my code against the libs I provided + ffmpeg libs. So maybe ffmpeg libs come after or before the libs I provided.

Well, since I'm linking against the project that links with ffmpeg, I think this is what's happening:

my_code is being linked against ffmpeg-sys-next crate + libs I provided. Where ffmpeg-sys-next crate contains the ffmpeg libs. I just don't know if the order is

ffmpeg-sys-next crate + libs I provided

or

libs I provided + ffmpeg-sys-next crate.

If ffmpeg needs vdp_device_create_x11, then vdp_device_create_x11 should come before ffmpeg or after?

Is it possible to control if the crate dependencies are linked after or before the libs I provided?

This might be possible by making your build script output its own link arguments for the FFMPEG libraries. I haven't found a way to test this yet.

Alternately, perhaps the ffmeg-sys-next crate could add an optional feature to link to libvdpau.

no, actually the situation is like this:

MyRustLib + RustStaticLib{rust code + ffmpeg libs} + libvdpau + other system libs

I was talking about the linking order of these things. I think it's cargo that manages the linking of 2 rust crates or rust packages and it uses the linking arguments from lib.rs to link libvdpau + other system libs

Running `rustc --crate-name liborwell_rust --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -Cembed-bitcode=no -C debuginfo=2 -C metadata=a40686dab33e6453 -C extra-filename=-a40686dab33e6453 --out-dir /home/dev/orwell/liborwell_rust/target/debug/deps -C incremental=/home/dev/orwell/liborwell_rust/target/debug/incremental -L dependency=/home/dev/orwell/liborwell_rust/target/debug/deps --extern ffmpeg_next=/home/dev/orwell/liborwell_rust/target/debug/deps/libffmpeg_next-c150275f8ec2ece5.rlib --extern liborwellprofile_protobuf_rust=/home/dev/orwell/liborwell_rust/target/debug/deps/libliborwellprofile_protobuf_rust-85a803bf8441d976.rlib --extern phf=/home/dev/orwell/liborwell_rust/target/debug/deps/libphf-0282e4d662343769.rlib --extern protobuf=/home/dev/orwell/liborwell_rust/target/debug/deps/libprotobuf-525fd12c456cb486.rlib -l static=z -l dylib=dl -l dylib=vdpau -l static=X11 -l dylib=va -l dylib=va-drm -l dylib=va-x11 -l dylib=xcb -L native=/home/dev/orwell/deps/ffmpeg/build/linux/x86_64/lib`

Looks like the ffmpeg libraries are the last thing passed to the compiler/linker: -L native=/home/dev/orwell/deps/ffmpeg/build/linux/x86_64/lib

rustc passed -L native=/home/dev/orwell/deps/ffmpeg/build/linux/x86_64/lib as its last flag. It comes after all the libs, including vdpau. Don't know, however, if it actually tries to link vdpau first then the ffmpeg libs.