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

[Feature Request] Have cbindgen set a conditional compilation attribute when generating #1014

Open
bavalpey opened this issue Oct 21, 2024 · 2 comments

Comments

@bavalpey
Copy link

bavalpey commented Oct 21, 2024

Right now, there's no way to hide (or specifically include) code that only cbindgen needs to know about when parsing a file.
There should be a conditional compilation attribute, or some other way of specifying code that only cbindgen needs to see. This should work just like the #[cfg(rust_analyzer)] attribute, or #[cfg(doc)] attribute.

There are a few use cases for this, but one of them is to selectively generate documentation, or to omit certain code. There are cases where cbindgen:ignore is not sufficient.

For instance, I don't want the cbindgen annotations cluttering up the public documentation for my code, so I use this odd macro cfg like so:

#[cfg_attr(not(any(doc, rust_analyzer)), doc = "cbindgen:[annotation]"

Another use case is to get cbindgen to output the correct structure or type of something that it isn't doing properly otherwise.
For example, I have an issue where a renamed type does not play nicely with how cbindgen unravels *const T.
Specifically, I have a type, FfiStr, that is a wrapper for *const c_char. I am currently using renaming to have cbindgen treat this as a const char* (which is correct). But cbindgen doesn't play nicely with this when I need to pass around arrays of these. Typing *const FfiStr results in const const char *.

I can't use a type alias, which cbidngen will just translate to using _ as ... when it sees it. For other reasons, I also can't use a type wrapper in Rust. However, if I were provided an annotation, then I could conditionally define a type annotation that cbindgen never sees.

The feature flag option in cbindgen.toml isn't sufficient for this. For one, this can cause undesirable behavior when invoking other tools that want--features=all or similar. It also doesn't really convey the intent very well: that this code snippet is only meant to be seen by cbindgen.

@emilio
Copy link
Collaborator

emilio commented Oct 27, 2024

I can't use a type alias, which cbidngen will just translate to using _ as ... when it sees it. For other reasons, I also can't use a type wrapper in Rust. However, if I were provided an annotation, then I could conditionally define a type annotation that cbindgen never sees.

Can you write a concrete example of how would you use this? In any case I think random cfg's are not allowed by the compiler (or were). The ideal for the /// cbindgen: annotations would be #[cbindgen(...)] or so, the doc syntax was pretty much a stop-gap :/

@bavalpey
Copy link
Author

bavalpey commented Oct 29, 2024

Can you write a concrete example of how would you use this?

So, I would use this like so:

#[cfg(not(cbindgen)]
type FfiStrArray = *const FfiStr

#[cfg(cbindgen])
struct FfiStrArray {}

#[unsafe(no_mangle)]
pub extern "C" fn some_ffi_str_method(a: FfiStrArray) {
    // Use FfiStrArray here., and have FfiStrArray renamed in cbindgen.toml
}

I also would use it for doc comments. Right now what I am doing is wrapping every /// cbindgen: ... directive in #[cfg_attr(not(any(doc, rust_analyzer)), doc = "cbindgen: ...")].

With a cfg macro added, one could do:
#[cfg_attr(cbindgen), doc = "cbindgen: ..."]

In any case I think random cfg's are not allowed by the compiler

I'm not sure when it was added, but rustc supports --cfg [var] and --cfg var=value to configure arbitrary cfgs when invoked. This is how rust_analyzer has its own cfg. Although, to make linters happy, one has to add the following to cargo.toml:

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(cbindgen)'] }

Essentially, wherever cbindgen is invoking rustc, you just have to add an additional --cfg cbindgen argument.

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