-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Better support for linking against alternate libraries #6519
Comments
Another wrinkle to this is that in the case of I'm, uh, not sure if I can override I'm really trying to avoid having to hack up the |
I've started to go down the rabbit holes at rust-lang/rust#27438 and rust-lang/rust#37403 and suspect this issue has been discussed there. Although I have yet to excavate the holes deeply enough to see if someone has mentioned exactly my use case. I'm starting to think I should have filed this issue under rust-lang/lang instead of cargo... |
OK. So it seems Rust wants to add If you use I found rust-lang/rust#37403 and the Unfortunately |
Thanks for the report here, and the detail! I'll admit though that after reading this over I'm a bit lost still, but I'm glad to hear that |
Yeah, the issue is kind of a rambling train wreck. Sorry about that. I'm not exactly sure what I'm trying to ask for either! But with a few days detached from me filing this, I think the following would definitely help:
|
That all makes sense to me! I definitely agree that we basically always need more documentation about linking and how things work in Rust, we've mostly just relied on how things tend to "mostly work" today and the edge cases seem to be few and far between! (but as you've seen are pretty awful once you hit them). Want to poke at the static-nobundle tracking issue and see if someone would like to FCP it for stabilization? It may also be good to open issues on rust-lang/rust to document the various behaviors here? |
I have a wonky use case that requires doing dirty things with linking. I'm not exactly sure what I want Cargo to do yet - only what I want it to enable me to do. This issue could be interpreted as asking for help. But I think exposing the problem to Cargo's maintainers would be useful, as it may help influence future features.
My problem statement can be summarized as: I want to force a dependency crate using
#[link]
to obtain symbols from the current crate instead of the library specified by#[link]
. But that may not capture the full detail of the problem.My use case is with the https://github.com/indygreg/PyOxidizer project. I have a crate that depends on the
python3-sys
crate (https://github.com/dgrunwald/rust-cpython). In addition to itsbuild.rs
emitting tons of lines (which I can override easily enough), thepython3-sys
crate heavily uses#[cfg_attr(windows, link(name="pythonXY"))] extern "C" { ... }
. Itsbuild.rs
emits acargo:rustc-link-lib=pythonXY:python{}{}
line remappingpythonXY
to what it finds when running. This is all pretty standard for *-sys crates.Here's where things get wonky.
I have a crate (
pyembed
) in PyOxidizer whosebuild.rs
effectively builds a static library containing a custom Python distribution using thecc
crate. Thecc
crate and pyembed'sbuild.rs
emitcargo:rustc-link-lib=static=
andcargo:rustc-link-search=native=
lines so this static library is linked. This is also fairly straightforward I think.What makes this use case special is that the static library I'm building provides the symbols that the dependency
python3-sys
crate wants - and has declared as available in thepythonXY
library. This kinda/sorta creates a circular dependency. But because symbols aren't resolved until link time, I don't run into problems building the dependencypython3-sys
crate - even though itsexternal
symbols and#[link]
library aren't available/built yet.I have a few solutions to this problem available to me today. But they feel less than optimal.
If my
build.rs
produces a static library whose name matches the#[link]
in the dependent crate exactly (in my casepythonXY
), that library satisfies thepythonXY.lib
requirement that Cargo automatically adds to thelink.exe
invocation. The linker can find the.lib
file and all is good. Furthermore, I don't think it matters if the symbols are actually in that.lib
or not, as the linker doesn't care what.lib
provides the symbols. All that matters is that the symbols can be found. So, mybuild.rs
could produce apythonXY.lib
actually containing the Python symbols. Or it could produce an emptypythonXY.lib
to satisfy the#[link]
requirement in the dependency.Producing
.lib
files to satisfy#[link]
requirements feels like the best option available to me today.Something else I tried was to use the
cargo:rustc-link-library=ALIAS:TARGET
syntax to remappythonXY
to something else.Originally, the
build.rs
produced static library containing Python's symbols was namedpyembedded
. I tried adding acargo:rustc-link-library=pythonXY:pyembedded
line to tell Cargo to linkpyembedded.lib
instead ofpythonXY.lib
. From a linker perspective, this should just work.pyembedded.lib
might be present multiple times tolink.exe
's invocation, but that's OK. However, Cargo rejected this witherror: renaming of the library `pythonXY` was specified, however this crate contains no #[link(...)] attributes referencing this library.
. I suppose I could add a#[link]
attribute topyembed
. But it feels weird telling it to link againstpythonXY
since that is exactly the thing I'm trying to prevent!I also tried adding a
cargo:rustc-link-library=pythonXY:pyembed
(pyembed
is the name of the crate). My thinking was I would just refer the crate to itself and things might just work (in theory I think they would from a linker perspective). But Cargo also rejected this due topythonXY
not being declared. This makes sense.I also thought maybe I can remap
pythonXY
to an empty string to make the link requirement go away. I attempted to add acargo:rustc-link-lib=pythonXY:
line. But this was rejected witherror: an empty renaming target was specified for library `pythonXY
anderror: empty library name given via `-l`
.It's worth noting that the
rustc-link-lib=ALIAS:NAME
renaming syntax doesn't appear to be documented athttps://doc.rust-lang.org/cargo/reference/build-scripts.html
. This scares me a little, as I'm not sure if the feature is stable. Is this feature documented anywhere?While I think I have a workaround in the form of producing
.lib
files matching the#[link]
requirements of dependent crates, it feels a bit hacky. In my use case, I explicitly do not want the dependent crates to attempt linking against defined#[link]
entries, since I'm providing those symbols as part of my crate.From my perspective, I think the simplest feature that would do the trick is the ability to remove / cancel out the
#[link]
attributes of dependent crates. Thecargo:rustc-link-library:NAME:
syntax /might/ be a clever way to implement this.Of course, removing a
#[link]
requirement is a subset of a larger, more general feature, which is to have full control over linking behavior, overriding or replacing behavior automatically derived from dependent crates. This seems like a complex, hard-to-design-and-implement feature and I'm not requesting it. (But it would be nice.)I hope the Cargo maintainers find this report useful. Since I think there is a sufficient existing workaround and my use case is a bit special, I wouldn't consider this a high priority to address.
The text was updated successfully, but these errors were encountered: