Tracking Issue for linker arguments respecting their relative order with `-l` library options
petrochenkov opened this issue · 10 comments
This is a tracking issue for link arguments respecting their relative order with -l
library options, which is a part of RFC "Linking modifiers for native libraries" (#81490, rust-lang/rfcs#2951), https://github.com/rust-lang/rfcs/blob/master/text/2951-native-link-modifiers.md#relative-order-of--l-and--clink-args-options specifically.
There's no feature gate for the issue.
About tracking issues
Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
Steps
- Implement the RFC - #99467
- Adjust documentation (see instructions on rustc-dev-guide)
- Stabilization PR (see instructions on rustc-dev-guide)
Unresolved Questions
The feature is unlikely to be implementable in the form that is specified in the RFC, i.e. by preserving relative order of -l
and -Clink-arg(s)
options.
-C link-arg
was usable for overriding options previously passed by the compiler for long time, so is pretty much guaranteed to be passed at the end of command line at this point.
The suggested solution (see #81490 and below) is to reuse the -l
option for such arguments and introduce -l link-arg=arbitrary-link-argument
, which is exactly like -C link-arg=arbitrary-link-argument
, except that its relative order to other -l
options is respected.
Implementation history
Implemented in #99467.
There's one possible improvement to -l link-arg
making it more portable between linkers and useful - befriending it with the verbatim
modifier (#99425).
-l link-arg:-verbatim=-foo
would add -Wl,-foo
(or equivalent) when C compiler is used as a linker, and just -foo
when bare linker is used.
-l link-arg:+verbatim=-bar
on the other hand would always pass just -bar
.
Not sure about the default here, I suspect that -verbatim
would be preferable, but it's different from -C link-arg
.
This would help to make link-arg
usable in #[link]
attributes and e.g. wrap libc and libgcc into a group (*) in the libc crate like
#[link(kind = "link-arg", name = "--start-group")]
#[link(kind = "static", name = "c")]
#[link(kind = "static", name = "gcc")]
#[link(kind = "link-arg", name = "--end-group")]
(*) to address cyclic dependencies between them
This is an analogue of CMake's LINKER:
prefix (https://cmake.org/cmake/help/git-stage/command/target_link_options.html#handling-compiler-driver-differences), and was discussed as a possible future extension in the link modifier RFC (https://github.com/rust-lang/rfcs/blob/master/text/2951-native-link-modifiers.md#support-linkarg--string-in-addition-to-the-modifiers).
cc @krasimirgg
I think -l link-arg
may have an unintended side effect: when build scripts run println!("cargo:rustc-link-lib={some_value}")
to get cargo to call rustc with -l
, cargo transitively passes the -l some_value
down to the crates' reverse dependencies. By contrast, using the recently stabilized cargo:rustc-link-arg
, which passes -C link-arg
to rustc, cargo does not pass the linker argument down to reverse dependencies. I think this would be useful, but is this desired?
@Be-ing
It's better to ask the cargo questions on the cargo repo, but in case of rustc -l link-arg
s are supposed to be passed from rlibs to the final linking step in the same way as other -l
options, to address the use case from #99427 (comment), for example (libc crate adds --(start,end)-group
, but they are actually passed to the linker later when libc crate is used as a dependency of an executable or dynamic library).
What is needed to move this forward? I have run into another situation in which -l link-arg
is needed. When linking Qt6Quick statically, some .cpp.o
files (compiled from a file generated by Qt's rcc tool) need to be linked too, but there's no stable interface to tell rustc and cargo to link those. I have tried using
println!("cargo:rustc-link-lib=static:+verbatim=/home/be/qt6-installed/lib/objects-Release/Quick_resources_2/.rcc/qrc_scenegraph_shaders.cpp.o");
but that fails with file too small to be an archive
, an error that comes from LLVM. When implementing support for linking file paths in the pkg-config crate, I could hack around the lack of -l link-arg
by splitting the path into the parent directory and file name then passing those with -L
and -l
, but that doesn't work for .o
files because of this file too small to be an archive
error.
Update: #118202 implemented the new behavior for -l link-arg
(#99427 (comment)), now it adds -Wl,
to the passed linker flags automatically if the linker is a C/C++ compiler.
This may be a breaking change for the current users of -l link-arg
.
If some flag needs to be passed specifically to the C/C++ compiler, and not to the underlying linker, then the +verbatim
modifier can be used - -l link-arg:+verbatim=-nostartfiles
.
Is this intended to also be used to weakly link frameworks on Apple platforms? As in, the equivalent of -weak_framework CoreFoundation
would be to do the following:
#![feature(link_arg_attribute)]
#[link(name = "-weak_framework", kind = "link-arg", modifiers = "+verbatim")]
#[link(name = "CoreFoundation", kind = "link-arg", modifiers = "+verbatim")]
extern "C" {}
Or must this be implemented separately as #[link(name = "CoreFoundation", kind = "weak_framework")]
?
@madsmtm
link-arg
is supposed to cover any cases that are not natively supported by existing link kinds at the moment (https://github.com/rust-lang/rfcs/blob/master/text/2951-native-link-modifiers.md#support-linkarg--string-in-addition-to-the-modifiers).
The -weak_framework
seems to fit that description, although I'm not personally familiar with it.
Cool, thanks, I've submitted a test for this in #118644.
(I actually think it works exactly like "framework"
(rustc_session::utils::NativeLibKind::Framework
), which seems to suggest it may need to be +verbatim
to be completely correct; I've updated my previous post).
Also tagging @grovesNL, you asked about this functionality a while ago on this internals thread.