Cfg! expression to enable if some version number greater than X


#1

Use case: for the FFmpeg mapping rust-ffmpeg-sys, I want to ensure it stays compatible with many FFmpeg versions. Some struct fields’ existence can only be decided by version number. I can easily retrieve those numbers via build.rs (compile a C program that outputs the definition).

But then how can I conditionally add struct fields in Rust code if that found version number is greater than some constant X?

Here’s an already working example based on FFmpeg feature definitions:

#[repr(C)]
pub struct AVCodecContext {
    // [...]
    #[cfg(any(feature="ff_api_codec_name", not(feature="ff_api_codec_name_is_defined")))]
    pub codec_name: [c_char; 32],

I’d like to have something like that for version numbers, pseudocode:

#[repr(C)]
pub struct AVCodecContext {
    // [...]
    // Decide struct field size based on FFmpeg version number
    #[cfg(version_greater_than("some_variable_set_by_build_rs", "some version number constant to compare against"))]
    pub bit_rate: int64_t,
    #[cfg(not(version_greater_than("some_variable_set_by_build_rs", "some version number constant to compare against")))]
    pub bit_rate: c_int,

How can I easily make this work? I am hoping this could be a feature of cfg! but didn’t find anything similar. Another idea was to auto-generate a Rust source file with the FFmpeg version like let ffmpeg_version_major : int = ... and then somehow use it in cfg!. Is a greater-than comparison possible in any way?


#2

Sounds like you want a build script to enable/disable feature flags based on availability within ffmpeg – this way you are also safe against unknown versions or misleading version numbers.


#3

That’s what the project is doing already, as stated in my example. I mentioned that some FFmpeg changes cannot be detect by feature #defines because none were added in certain commits.

My problem right now is the case from my example, where AVCodecContext::bit_rate changed to 64-bit, see relevant commit. Actually that commit didn’t even change the version numbers at all, so I’d have to fall back to something else, but I am asking for a general solution in case this is ever needed. Using actual released version numbers instead of hacky workarounds is probably a better solution.

P.S. in the stated commit, a new (and totally unrelated) #define was introduced, which I will use as trick.


#4

Forget about that last reply… I opened the wrong commit.

This one is for AVCodecContext::bit_rate, and it only changes the minor version number. So I would need some solution using version numbers. My build script could of course export lots of “ffmpeg_version_greater_than_X_Y” and then cfg!(feature="ffmpeg_version_greater_than_57_1") but that’s quite messy, isn’t it?