Rust: Tracking issue for `link_args` stabilization

Created on 5 Nov 2015  路  26Comments  路  Source: rust-lang/rust

This issue tracks stabilization for the #[link_args] attribute.

A-linkage B-unstable C-tracking-issue P-medium T-compiler T-dev-tools T-lang

Most helpful comment

@petrochenkov cargo:rustc-flags specifically parses for -l and -L flags only and was deprecated in favor of the dedicated cargo:rustc-link-lib and cargo:rustc-link-search flags. cargo:rustc-cdylib-link-arg is great but only applies to cdylibs and there is no equivalent for regular binaries yet. Once cargo:rustc-link-arg and/or cargo:rustc-bin-link-arg exist however, then I would be in favor of getting rid of #[link_args] and never seeing it again.

All 26 comments

@alexcrichton (or anyone else), any ideas what the blockers are here?

From the reference:

The compiler's usage of the system linker is not guaranteed to continue in the future, and if the system linker is not used then specifying custom flags doesn't have much meaning.

Some thoughts of mine:

  • Right now we split arguments on spaces, so there's no way to specify an argument with a space in it
  • This is super non-cross-platform. Even within one platform there's no guarantee that we'll always call the same linker.
  • It's unclear what the "propagation semantics" of link args should be. For example if you build an rlib, should the arguments be passed to when that rlib is included in a linker invocation? Should it be passed upstream continuously after that is then later used in linker invocations?

Since we do not have a good solution for now, but as a system language, it is sometimes necessary to specify args like this (even only for specific platforms), put it behind a feature gate and only letting nightly branch to use it seems to be a compromise to make.

Got hit by this issue when trying out https://gist.github.com/jansegre/043f5ab7f53e23890eed.

As LuaJIT requires, I need to link the binary with flags -pagezero_size 10000 -image_base 100000000, which seems only achievable via #[link_args = "..."].

Could this be done _without_ using Rust nightly? Obviously link_args is not available as of Rust 1.6.0:

src/main.rs:1:1: 1:23 error: #[feature] may not be used on the stable release channel
src/main.rs:1 #![feature(link_args)]

You can use the command line flag -Clink-args="-pagezero_size 10000 -image_base 100000000" which does work fine (or cargo rustc -- -Clink-args="blah")

It seems strange to allow -C link-args on the command line without -Z unstable-options, yet keep the source code equivalent unstable.

I'd rather we fix the issue with being unable to have spaces in the linker arguments before stabilizing either of them. Unfortunately -Clink-args being stable makes that difficult.

So uh, is it intentional that this became accidentally stable?

#![link_args = "-l bunny"]
fn main() {}
rustc 1.18.0 (03fc9d622 2017-06-06)
warning: unused attribute
 --> <anon>:2:1
  |
2 | #![link_args = "-l bunny"]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(unused_attributes)] on by default

error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib" "./out.0.o" "-o" "./out" "-Wl,--gc-sections" "-pie" "-nodefaultlibs" "-L" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-f4594d3e53dcb114.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/librand-1efbcfd8938372b6.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcollections-532a3dbf317eff86.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_unicode-cfbd6648f7db2ee5.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-a0157c0ca919c364.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-488b4ab4bd53a138.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-ca07b617414dd0fa.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_jemalloc-492d8ea7fa3384ff.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-88c194c15fdb6521.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-687e6a964d22cbb4.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-987729be881d4d32.rlib" "-Wl,-Bdynamic" "-l" "dl" "-l" "rt" "-l" "pthread" "-l" "gcc_s" "-l" "pthread" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util" "-l" "bunny"
  = note: /usr/bin/ld: cannot find -lbunny
          collect2: error: ld returned 1 exit status


error: aborting due to previous error

Also it warns that the attribute is unused despite having a very obvious effect. Also we still don't have a superior #![link_arg] yet which is capable of handling arguments with spaces in them.

@retep998 I guess its a mistake, yes. There is a working feature gate, together with a gate test, but it seems to be only active on the foreign module declaration, so extern { .. } or extern C { .. }.

But there's no reason to even tie a link_args to an extern block. At least with link you can use the kind to infer whether to apply dllimport to those extern symbols, but for arbitrary linker arguments there's nothing you can do.

@retep998 I guess its simply a mistake. The bug in the feature gate is probably that way since the initial implementation e338a4154b134fc1d4628496d4ccf85b7af7c443 (no idea what ast::item_foreign_mod meant back then but it means probably exactly what extern { .. } means now).

IMO we should do one of these two things:

  • Emit warnings and fix the feature gate after a few cycles, or
  • Stabilize the feature right away, or with some previous thinking.

cc @rust-lang/compiler, it appears that there was an unintended stabilization here; decision needed.

Unless there's a sign of usage in the wild, I think the right answer here is to fix the broken feature gate and keep this unstable.

triage: P-high

We decided to try and fix this. @pnkfelix will either prep a PR or write-up some mentoring instructions.

Feature gate was fixed by #43109. Lowering priority.

triage: P-medium

It seems that link_args attributes always get reported as unused. This was also mentioned above. Am I missing something?

@vext01 I'm guessing that just isn't high enough priority to get addressed (yet)...

This would be very useful for embedded applications, which currently all have to create a custom .cargo/config that passes the linker script to the linker.

What happens with #[link_args] in an rlib? Will those args be passed to the final linker invocation in the binary? (if not, that's fine, we can work around that, but it should probably be a conscious choice)

ping \ (how to ping it?) @jamesmunns @japaric @therealprof

I'd like to remove this attribute (preferably?) or bring it to some reasonable state.

Given the already listed issues

  • whitespace treatment
  • non-portability (even between e.g. gcc and the underlying ld)
  • non-propagation of link_args from dependencies

and other issues

  • the relative order between #[link] and #[link_args] attributes is not respected, all the link_args are passed together after all the libraries

what are the current use cases for this feature?

Is it possible to comfortably replace it with command line options from cargo configs or build scripts?

Passing arbitrary linker flags from build.rs would also work, I believe. Not for all the nice feature I had in mind, but at least it would allow removing .cargo/config from embedded projects.

I have submitted an RFC about some more fine-grained control over linking - https://github.com/rust-lang/rfcs/pull/2951.

The "Future possibilities" section contains a paragraph about a potential order-preserving, propagating and single-argument alternative to #[link_args].

Ping works. ;)

I don't recall ever having seen #[link_args] in the wild. It certainly would be nice to have more control about the linking process and linker configuration from the application without requiring a build.rs and sans custom config in .cargo/config but we have been able to do without for a long time...

If I could specify linker arguments from build scripts then I wouldn't care for this attribute at all, but I currently have neither so...

If I could specify linker arguments from build scripts

cargo:rustc-flags=-Clink-arg=-my-link-arg

?

(There's also cargo:rustc-cdylib-link-arg=FLAG which seems a pretty random recent addition and a part of some potential larger feature.)

@petrochenkov cargo:rustc-flags specifically parses for -l and -L flags only and was deprecated in favor of the dedicated cargo:rustc-link-lib and cargo:rustc-link-search flags. cargo:rustc-cdylib-link-arg is great but only applies to cdylibs and there is no equivalent for regular binaries yet. Once cargo:rustc-link-arg and/or cargo:rustc-bin-link-arg exist however, then I would be in favor of getting rid of #[link_args] and never seeing it again.

Was this page helpful?
0 / 5 - 0 ratings