Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pass cflags to gcc #43

Open
scottlamb opened this issue Jul 19, 2017 · 1 comment
Open

pass cflags to gcc #43

scottlamb opened this issue Jul 19, 2017 · 1 comment

Comments

@scottlamb
Copy link

In my Rust program, I want to use a C library (ffmpeg) with an API that's not Rust-friendly in a couple ways:

  1. The API is partially defined in terms of macros such as this one, and I'd rather not have to duplicate their definitions (and hope they never change):

    #define AVERROR_EOF                FFERRTAG( 'E','O','F',' ')
  2. The caller is expected to directly access struct fields rather than use accessor functions, and the struct layout changes from version to version (hopefully paired with the appropriate .so major version increments, or even C callers are screwed when the library gets upgraded) and/or based on ifdefs, so duplicating the struct layouts in Rust is brittle. Here's an example (minus comments and such):

    typedef struct AVPacket {
        AVBufferRef *buf;
        int64_t pts;
        int64_t dts;
        uint8_t *data;
        int   size;
        int   stream_index;
        int   flags;
        AVPacketSideData *side_data;
        int side_data_elems;
        int   duration;
    #if FF_API_DESTRUCT_PACKET
        void  (*destruct)(struct AVPacket *);
        void  *priv;
    #endif
        int64_t pos;
        int64_t convergence_duration;
    } AVPacket;

(There's an existing Rust wrapper, but it took the duplication approach, and so there are problems if you compile against a different version than expected. I'd like to try another way.)

I want to make a tiny C library that simply provides a more Rust-friendly API surface: provides C functions to wrap the macros and access struct fields. So my Rust program will be using ffmpeg directly (for the parts that seem sensible/stable) and via my wrapper (for the rest).

I tried doing this via this simple build.rs:

extern crate gcc;
extern crate pkg_config;

fn main() {
    pkg_config::Config::new().atleast_version("54.1").probe("libavutil").unwrap();
    pkg_config::Config::new().atleast_version("56.0").probe("libavcodec").unwrap();
    pkg_config::Config::new().atleast_version("56.0").probe("libavformat").unwrap();
    gcc::Config::new()
        .file("wrapper.c")
        .compile("libwrapper.a");
}

but it looks like the cflags don't get passed to the gcc-built stuff; my #include <libavcodec/codec.h> doesn't work. Looking at pkg-config's source, I think I'd have to look at the pkg_config::Library, take the things that it carefully unpacked via parse_libs_cflags, and repack them into the cflags representation. That seems silly; I want a more direct way to pass them from pkg-config to gcc, as well as use them in my Rust program itself.

@ebassi
Copy link

ebassi commented Aug 29, 2017

Currently, I have something like this:

    let lib = pkg_config::Config::new().atleast_version("1.2").probe("some-dep").unwrap();
    let mut builder = gcc::Config::new();

    for i in &lib.include_paths {
        builder.include(i);
    }

    builder.include("src");
    builder.file("foo/foo.c");
    builder.compile("libfoo.a");

But I agree, it's less than stellar. It would be nice to have something like:

    let lib = pkg_config::Config::new().atleast_version(...).probe(...).unwrap();
    gcc::Config::new().include_paths(&lib.include_paths).file(...).compile(...);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants