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

Missing constants on macOS vs Linux

Open virtualritz opened this issue 4 years ago • 2 comments
trafficstars

I get some #define constants from a C header missing in the generated bindings when building on Linux vs. macOS.

The constants in question, all starting with the TA_INTEGER prefix, are not behind any conditionals #if in the header but use other constants. See C Header section below.

Namely they use INT_MIN/INT_MAX which come from limits.h. The C lib I am wrapping builds fine and its code uses TA_INTEGER_MIN/TA_INTEGER_MAX/TA_INTEGER_DEFAULT; i.e. the constants from limits.h are 'seen' and used – on both platforms.

I am using Rust nighly and latest bindgen. Of note: clang is @ 5.0.1 on the Linux (CentOS) vs 12.0 on macOS.

Grepping on the bindings on macOS:

~/c/c/ta-lib-rs/tar/d/b/ta-lib-sys-9975acf6d6f5a59e
❯ rg TA_INTEGER_DEFAULT
out/bindings.rs
7:pub const TA_INTEGER_DEFAULT: i32 = -2147483648;

out/include/ta-lib/ta_defs.h
213:#define TA_INTEGER_DEFAULT (INT_MIN)

But on Linux:

~/c/c/ta-lib-rs/tar/d/b/ta-lib-sys-26bcdc06d91e3e82
❯ rg TA_INTEGER
out/include/ta-lib/ta_defs.h
213:#define TA_INTEGER_DEFAULT (INT_MIN)

If I run the above, grepping for TA_REAL instead, I get the same output on both platforms. I.e. constants starting with TA_REAL are there, constants starting with TA_INTEGER are missing on Linux.

It looks as if some stuff incoming from limits.h is just not recognized/omitted by bindgen which then leads to the TA_INTEGER prefixed constants missing in the generated binding. Just a guess ofc.

C Header

wrapper.h.

The actual offending header is this one, ta_defs.h, line 213 – #define TA_INTEGER_DEFAULT (INT_MIN).

/* min/max value for a TA_Integer */
#define TA_INTEGER_MIN (INT_MIN+1)
#define TA_INTEGER_MAX (INT_MAX)

/* min/max value for a TA_Real 
 *
 * Use fix value making sense in the
 * context of TA-Lib (avoid to use DBL_MIN
 * and DBL_MAX standard macro because they
 * are troublesome with some compiler).
 */
#define TA_REAL_MIN (-3e+37)
#define TA_REAL_MAX (3e+37)

/* A value outside of the min/max range 
 * indicates an undefined or default value.
 */
#define TA_INTEGER_DEFAULT (INT_MIN)
#define TA_REAL_DEFAULT    (-4e+37)

Bindgen Invocation

let bindings = bindgen::Builder::default()
         .header("wrapper.h")
         .clang_arg(format!("-I{}", out_path.join("include").display()))
         .allowlist_function("TA_.*")
         .allowlist_type("TA_.*")
         .allowlist_var("TA_.*")
         .generate()

This then leads to a bunch of:

error[E0425]: cannot find value `TA_INTEGER_DEFAULT` in crate `ta`
   --> ta-lib/src/macros.rs:170:29
    |
170 |                           ta::TA_INTEGER_DEFAULT
    |                               ^^^^^^^^^^^^^^^^^^ help: a constant with a similar name exists: `TA_REAL_DEFAULT`

virtualritz avatar Oct 25 '21 13:10 virtualritz

I guess this is really an issue with whether INT_MIN is seen by bindgen on macOS, but maybe we can special-case and define them based on the target integer size.

emilio avatar Oct 27 '21 17:10 emilio

Just to clarify: INT_MIN is seen on macOS but not seen on Linux/CentOS.

I worked around this for now in my wrapper crate but it's probably worth following up the root cause of this.

virtualritz avatar Oct 29 '21 14:10 virtualritz

I have this problem on Linux as well. My clang version is Ubuntu clang version 14.0.0-1ubuntu1 and bindgen version is 0.63.0.

HKalbasi avatar Dec 27 '22 15:12 HKalbasi