rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

implement Clone on Builder

Open jrandall opened this issue 2 years ago • 0 comments

I have a use case in which I would like to invoke rust-bindgen multiple times. Once with generate_comments(false) and once with generate_comments(true) -- the use case here is that the C header file has comments annotating the run-time version required for a particular struct field to have been added. This is for a sqlite extension that we want to build against a new version of sqlite headers (e.g. sqlite3ext.h but then have runtime detection of version in order to make it safe to load the loadable extension into an older version of sqlite.

I have this working (using some syn parsing of the AST that rust-bindgen generates to process the fields and their comments). However, I would very much like to be able to write code like this:

let mut bindings = bindgen::builder()
           .trust_clang_mangling(false)                                                                                |
            .header(header.clone())                                                                                     |
            .parse_callbacks(Box::new(SqliteTypeChooser))                                                               |
            .rustfmt_bindings(true);
            
 // lots of conditional code that updates `bindings` with different clang args, etc in different situtaions
 
 let bindings_with_comments = bindings.clone().generate_comments(true);

// actual invocations of `bindings.generate()` and `bindings_with_comments.generate()`

However, I find that the bindgen Builder does not implement Clone (it appears that it used to as of 0.19.1 but has not for some trime: https://docs.rs/bindgen/0.19.1/src/bindgen/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.19.1/src/lib.rs.html#42).

As a result of not being able to .clone(), I find that I am having to write something like this:

let mut bindings = bindgen::builder()
           .trust_clang_mangling(false)                                                                                |
            .header(header.clone())                                                                                     |
            .parse_callbacks(Box::new(SqliteTypeChooser))                                                               |
            .rustfmt_bindings(true);
let mut bindings_with_comments = bindgen::builder()
           .trust_clang_mangling(false)                                                                                |
            .header(header.clone())                                                                                     |
            .parse_callbacks(Box::new(SqliteTypeChooser))                                                               |
            .rustfmt_bindings(true);
            
 // lots of conditional code that follows every update to `bindings` with an identical update to `bindings_with_comments`
 
// actual invocations of `bindings.generate()` and `bindings_with_comments.generate()`

I've explored a bit if there are alternatives to this but struggle to find anything that doesn't involve essentially duplicating hundreds of lines of code.

It feels like the right solution is to implement Clone on bindgen Builder -- is there a good reason not to do this, or is it simply that no one has presented a use-case for it to date?

jrandall avatar Dec 09 '21 15:12 jrandall