Skip to content

Bindgen-generated types conflict with other -sys crates #99

Open
@bavshin-f5

Description

@bavshin-f5

Our bindgen configuration does not filter the types and as a result we pollute nginx_sys with all the symbols from libc, pcre2 and OpenSSL.

At the very least, we should limit output to the nginx symbols and required dependencies:

    let bindings = bindgen::Builder::default()
        .allowlist_function("ngx_.*")
        .allowlist_type("ngx_.*")
        .allowlist_var("(NGX|NGINX|ngx|nginx)_.*")

but here's another annoying problem: nginx_sys::SSL is not the same type as openssl_sys::SSL and cannot be used interchangeably. Even though it's generated from the same header with the same layout, Rust compiler does not use structural typing and cannot infer the equivalence.
In practice that results in an extra noise and unsafety when using a high-level OpenSSL bindings. Whenever we need to call openssl::something, we'll have to cast nginx_sys:: types to openssl_sys:: and vice versa.

The same issue applies to pcre2, libc and likely windows-sys.
This could be solved by telling bindgen to skip the types and add imports from the correct crate:

        .blocklist_type("SSL|SSL_CTX|SESSION")
        .raw_line("use openssl_sys::{SSL,SSL_CTX,SSL_SESSION};")

The last remaining issue is that we lose all the automagically derived traits, as bindgen is no longer able to verify that the blocklisted struct field type implements Copy, Clone or Debug. This requires more advanced workarounds, such as providing our ParseCallbacks implementation:

use bindgen::callbacks::{DeriveTrait, ImplementsTrait};

struct NgxExternalTypes;

impl bindgen::callbacks::ParseCallbacks for NgxExternalTypes {
    fn blocklisted_type_implements_trait(&self, name: &str, derive_trait: DeriveTrait) -> Option<ImplementsTrait> {
        // name is not preprocessed and could be `struct x`, `const x`, `const struct x` etc.
        match name.split_ascii_whitespace().last()? {
            "in_addr" => Some(match derive_trait {
                DeriveTrait::Copy => ImplementsTrait::Yes,
                DeriveTrait::Debug => ImplementsTrait::Yes,
                DeriveTrait::Hash => ImplementsTrait::Yes,
                DeriveTrait::PartialEqOrPartialOrd => ImplementsTrait::Yes,
                _ => ImplementsTrait::No,
            }),
            "in6_addr" => Some(match derive_trait {
                DeriveTrait::Copy => ImplementsTrait::Yes,
                DeriveTrait::Hash => ImplementsTrait::Yes,
                DeriveTrait::PartialEqOrPartialOrd => ImplementsTrait::Yes,
                _ => ImplementsTrait::No,
            }),
            _ => None,
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions