JuliaInterop / Clang.jl

C binding generator and Julia interface to libclang
https://juliainterop.github.io/Clang.jl/
MIT License
219 stars 68 forks source link

Not emitting definition for INT8_MAX (from stdint) #446

Closed Octogonapus closed 11 months ago

Octogonapus commented 11 months ago

I'm wrapping the AWS CRT packages and I have encountered some weird behavior. This C code:

// stdint.h is included indirectly through a number of headers which are also passed to Clang.jl
#define AWS_EVENT_STREAM_HEADER_NAME_LEN_MAX (INT8_MAX)

causes this wrapper to be generated:

const AWS_EVENT_STREAM_HEADER_NAME_LEN_MAX = INT8_MAX

There's no definition for INT8_MAX in the generated code. It would be great if Clang.jl could emit:

const AWS_EVENT_STREAM_HEADER_NAME_LEN_MAX = 127

or at least:

const INT8_MAX = 127
const AWS_EVENT_STREAM_HEADER_NAME_LEN_MAX = INT8_MAX

Is Clang.jl expected to fail in this case, or did I misconfigure something?

Clang.jl v0.17.6 Julia v1.9.3

Gnimuc commented 11 months ago

Yes. It's technically impossible to do this because macro expanding is handled by the preprocessor, before the AST is created, and we can only extract info from the AST.[^1] The identifier INT8_MAX could be anything, it's legal to undef it and define it again. So, unless we implement a full-featured C preprocessor in Julia, it's hard to do it without any mistakes.

However, the best practice is much simpler. We can add const INT8_MAX = typemax(Int8) to the prologue file and do it once for all.

I know the ultimate solution is something like Rust's https://github.com/rust-lang/libc. But in practice, as Julia is niche at the moment, we really don't have that manpower. ;)

[^1]: to elaborate a bit more, the info is lost after the macro is "expanded" by the preprocessor. the compiler can only see 127, not INT8_MAX. The reason why Clang.jl can handle #define AWS_EVENT_STREAM_HEADER_NAME_LEN_MAX (INT8_MAX) is that it uses a heuristic way to parse the C code.)

Octogonapus commented 11 months ago

Fair enough