-
Notifications
You must be signed in to change notification settings - Fork 79
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
Including system library paths makes it difficult to overide library versions #11
Comments
Currently system library paths are required to allow the compiler to find static versions of libraries, but I can see where this would cause problems with multiple libs on the system... |
Could the compiler not add the system default paths, independently of pkg-config, at the end of the arguments list (so they have the lowest priority)? |
Perhaps, but the compiler has no knowledge of the default paths for a system (like the linker does) |
What would the process be, to move towards a solution for this? |
I can't really think of a great solution for this, so it would probably involve coming up with one first :) |
I'm not familiar with all the tooling rust uses to compile. Is there some place I can read up on the linkers used on different platforms? Could the compiler query the linker for the default paths? |
We generally just shell out to |
So in our project we ended up on exactly the same issue, and no easy solution. Of course the root cause is the awful setup of libssl on MacOS X but we need to find a way around this... I still don't properly get why we need the system paths for the static libs to be found. Isn't it something that |
If we really need it, here is a dumb idea: call
Diff the 2 outputs. Then we'd know which libs are the system libs. |
The compiler needs to load the actual
Perhaps! |
I just re-read the manual page for pkg-config. Actually the list of paths that pkg-config considers as "system" seems to be hard-coded:
So maybe it's good enough to just special-case these paths ? |
I'd be game! |
So now, how do we special case them ? Do you think rustc could actually automatically always add them (and then we can remove them from pkg-config output)? Or would it be too fragile and we should instead add them as a new special build.rs output that cargo would understand ? |
It's pretty rare to pick up a staticlib from there, so if we're linking a dylib we just shouldn't print out those two |
In that case the patch would be as simple as not adding the env variable |
See sfackler/rust-openssl#447 (comment) I think there's a way to make this specific to certain libraries (or, at least, I did for openssl):
My fork: https://github.com/imazen/rust-openssl |
@nathanaeljones I don't think that syntax is recognized by the compiler. It will attempt to interpret |
What about #11 (comment) ? This is a pretty painful bug. Since |
For reference, this is how I'm using [replace]. Cargo pretends it doesn't exist.
|
|
@nathanaeljones hm the |
No, they both were not. But due to the non-deterministic order of link paths in cargo, it is very hard to construct tests. Failures can range from 5% of builds to 95% of builds, so isolating variables is near-impossible. (I'm not blaming pkg-config - there are larger questions) FrictionThis is by far the worst whack-a-mole situation I've experienced in the Rust ecosystem. Since September, I've averaged 16 hours per month in fighting recurrences on Travis and AppVeyor (along with various dev environments). I forked pkg-config, but any new crates I use could pull in a standard version, causing the issue to ... eventually, even weeks later ... reoccur. It's not easy to diagnose, even the (n)th time, because sometimes it is just OpenSSL breaking its ABI again, or an actual build environment issue, and it's just infrequent enough to be extremely painful. I should be shipping a production beta of Imageflow this month, but for now I've had to disable TLS support across all crates and purge usage of HTTPS. For the server component, I'm planning an nginx proxy to substitute, but I don't yet have an answer for making HTTPS requests, and that's kind a key feature for an image proxy. Right now I'm holding my breath and hoping that this PR goes somewhere fast. If it doesn't, I'll need to fork Hyper and most of the Iron ecosystem rather quickly. Unfortunately, this isn't limited to OpenSSL - I've run into it with libpng, libjpeg, and various other packages. Larger questionMy understanding is that there are several issues at play:
Hear me out. You've got a great solution to the OpenSSL nightmare in the works, but the problem with C dependencies (in general) persists. Cross-plat is much harder when wrangling compatibility with a range of versions for each dependency. With diamond dependencies (like openssl) this is sometimes impossible without forking the world. What if we made it easier for developers to use specific versions of C/C++ dependencies? I realize this feature (discovered as I write this) tries to make that easier, and I suspect I could .gitignore .cargo/config and generate it from Conan. However, if I miss a target, or a library, I risk silently linking against the wrong binaries and risking future heap or stack corruption. What if - rather than preventing various build.rs scripts from executing - I was able to specify a 'filter' - an executable receiving the concatenated build script output via STDIN (along with all env vars like the target triple), and producing modified results to STDOUT? This method would permit:
Anticipated challenges:
|
@nathanaeljones if you already forked to remove https://github.com/alexcrichton/pkg-config-rs/blob/e9297b2e16e40026ec546324b657b780d2c305b3/src/lib.rs#L363 in your fork, maybe you can propose a PR ? |
@nathanaeljones sorry you've been having so much trouble lately! It sounds like there's definitely some improvement we could make somewhere. That being said though this perhaps isn't the place to discuss these issues? I'm more than willing to help out with any particular issue, but general changes to Cargo should probably be discussed on internals.rust-lang.org, rather than the pkg-config-rs issue tracker. |
@julienw #35 Would have done so earlier, but I didn't get confirmation that the change was acceptable. @alexcrichton I wasn't sure, but figured you could suggest the best forum. Thanks! I'll post there. |
In light of the refactoring of SSL in Hyper, I upgraded all crates and gave this another try. It would appear that this is still broken by default - at least, compiling openssl-sys on Ubuntu 14.04 brings in the world ( |
What if we could somehow pass paths to the compiler only? Is there anything we can do to make this correct? |
We have lost bunch of developer time due to this surprising default 7 years since the ticket was opened... At least we were able to locate the library leaking in the system directory by grepping for it in If there's nothing that's going to happen here, close as WONTFIX? |
In its default configuration, pkg-config adds system-wide library directories to the linker search path (rust-lang/pkg-config-rs#11). This causes these directories to be searched before other paths added by later crates or by `-Clink-arg` in rustflags. If a library is present in the system-wide directory and a later build step wants to specifically link against a different version of that library in another path, the linker will choose the library from the first search directory it finds. If the linker doesn't find a library in any of the specified search directories, it falls back on system-wide paths, so we don't need to print the path we found lubcurl in if it is in one of those system paths. rust-lang/libz-sys#50
In its default configuration, pkg-config adds system-wide library directories to the linker search path (rust-lang/pkg-config-rs#11). This causes these directories to be searched before other paths added by later crates or by `-Clink-arg` in rustflags. If a library is present in the system-wide directory and a later build step wants to specifically link against a different version of that library in another path, the linker will choose the library from the first search directory it finds. If the linker doesn't find a library in any of the specified search directories, it falls back on system-wide paths, so we don't need to print the path we found lubcurl in if it is in one of those system paths. See rust-lang/libz-sys#50 for the same fix to libz that landed a while back.
In its default configuration, pkg-config adds system-wide library directories to the linker search path (rust-lang/pkg-config-rs#11). This causes these directories to be searched before other paths added by later crates or by -Clink-arg in rustflags. If a library is present in the system-wide directory and a later build step wants to specifically link against a different version of that library in another path, the linker will choose the library from the first search directory it finds. If the linker doesn't find a library in any of the specified search directories, it falls back on system-wide paths, so we don't need to print the path we found libssh2 in if it is in one of those system paths. See rust-lang/libz-sys#50 for the same fix to libz that landed a while back. See also alexcrichton/curl-rust#441 for the same fix to libcurl-sys.
In its default configuration, pkg-config adds system-wide library directories to the linker search path (rust-lang/pkg-config-rs#11). This causes these directories to be searched before other paths added by later crates or by -Clink-arg in rustflags. If a library is present in the system-wide directory and a later build step wants to specifically link against a different version of that library in another path, the linker will choose the library from the first search directory it finds. If the linker doesn't find a library in any of the specified search directories, it falls back on system-wide paths, so we don't need to print the path we found libssh2 in if it is in one of those system paths. See rust-lang/libz-sys#50 for the same fix to libz that landed a while back. See also alexcrichton/curl-rust#441 for the same fix to libcurl-sys.
At present,
Config::find
returns system library paths. This can make it difficult to override library versions.The motiviating example is using rust-openssl with ssh2-rs on OS X. On Mac, openssl requires a non-system version of openssl for TLS support, which can successfuly be provided by homebrew, for example. ssh2-rs depends on libz-rs, which pkg-config finds as
-L /usr/lib
. This library path gets added before the openssl library path, resulting in the system (older) openssl libraries being used, and the linker failing.The text was updated successfully, but these errors were encountered: