rust-lang / libz-sys

Rust crate package to link to a system libz (zlib)
Apache License 2.0
117 stars 77 forks source link

Dynamically link zlib-ng #158

Open hack3ric opened 1 year ago

hack3ric commented 1 year ago

Linux distros prefer shared libraries over vendor it whenever possible, and zlib-ng is (at least) available on Arch Linux. I am wondering if we can support dynamic linking in libz-ng-sys?

I would like to help and create a PR, but we may need to discuss how to expose this feature first, if it is acceptable.

Byron commented 1 year ago

Even though I don't know enough yet to help with figuring out implementation details, I can say that any implementation of this feature would need to be backwards compatible, i.e. non-breaking.

With this said, such a feature will also help to one day make it possible to let people opt-in to using system libraries, static or dynamic, via flate2 as well.

NobodyXu commented 1 year ago

Maybe it could use a CARGO environment for this instead of a feature?

I've seen other *-sys crates (e.g. openssl) doing this, with a vendored feature to override environment settings.

chenrui333 commented 4 months ago

might be just do ZLIB_NO_VENDOR like openssl and libgit2 crates?

folkertdev commented 3 months ago

For zlib-rs we want to test against locally-built versions of zlib a lot, so I hacked up a script that takes the libz-sys source, but transforms all of the extern functions into a function that dynamically loads from a dylib.

https://github.com/memorysafety/zlib-rs/blob/main/dynamic-libz-sys/src/generated.rs

e.g.

extern "C" {
    fn deflateReset(strm: z_streamp) -> c_int;
}

becomes

pub unsafe fn deflateReset(strm: z_streamp) -> c_int {
    type Func = unsafe extern "C" fn(strm: z_streamp) -> c_int;
    let f: libloading::Symbol<Func> = dynamic_library()
        .get(if_zng!({ concat!("zng_", "deflateReset") }, "deflateReset").as_bytes())
        .unwrap();
    f(strm)
}

The reason this approach is useful for us is that we can load two versions of zlib into the same binary without name conflicts. There is a performance penalty I guess but we only need this for debugging anyway so that's not an issue. Maybe this is useful for someone while this crate does not implement picking a custom dylib to link.