In the world of GObject API there are XML files describing the API and so you create two crates one with the FFI stuff and one with the Rust-facing stuff. Clearly all very sensible as that is the way to tools lead you.
For other C APIs I am assuming bindgen is the de facto standard tool for generating the FFI. The question is should this be a standalone crate with any Rust-facing additions in a separate crate. Alternatively, should the FFI bits and the Rust-facing bit all be in the same crate?
One issue I am stumbling on at the minute: the C API I am binding/wrapping has a "function" that is a macro. Bindgen appears not to generate anything for this. This implies manually providing an implementation of the function. I am guessing the *-sys crate is the right place for it, rather than the * (rust-y) companion crate. Is there an example of doing this sort of thing that I can take a look at?
Is there a way of getting Bindgen to output a file with newlines, having the entire output as a single line file is difficult for finding things out about the generated file?
Apparently I have rustfmt installed via rustup but the bindgen generated file isn't using it.
Does this imply not running bindgen as part of a build but instead generating and committing the result of bindgen to a file in the repository of the *-sys package?
If the C library has a stable ABI (i.e. there's generally one version of it and it doesn't change often in incompatible ways), I recommend committing the generated file in your sys crate. That saves users from having to run bindgen, which is quite a heavy dependency.
Now to find out how to organise things so that the bindgen is a manual thing not a run every time thing. Also committing the generated source further pushes me towards finding out why rustup is installing a rustfmt but not one that actually works.
So not the Cargo.toml/build.rs driven system as for the bzip2 example and real crates. I'll have to see how stable the API is and take a view. I'll hunt out the libjpeg example. Thanks for the feedback, very much appreciated.
I found out why the bindgen wasn't being formatted, rustfmt wasn't installed properly – I have no idea how or why. Now reinstalled properly and working as you predicted. Life is a lot easier now.
@kornel As a supplementary question: bindgen does nothing with C macros that have parameters. If some of then should be offered as (potentially inline) functions should they be in the lib-sys crate or in the lib crate?
It's fine to put macro replacements in the sys crate. There isn't a hard rule about this, since macros don't affect linking or ABI in general.
Keep in mind that often C uses macros only because it's bad at inlining functions or lacks generics, so a replacement for a C macro isn't always a macro. It might be a (generic) Rust function.
@kornel Of course now is the decision what to do about the ioctl calls. The nix crate allows for creating Rust-facing ioctl functions whereas the C just has the ioctl number macros. The nix generated ioctl functions should perhaps should be in a lib crate, but I think I might do a doublethink and put them in the lib-sys crate since there is unlikely to be a lib crate for this FFI binding.