Summary

Provide an extensible mechanism

仕組み、機構
for tweaking linking behavior
ふるまい
of native libraries both in #[link] attributes (#[link(modifiers = "+foo,-bar")]) and on command line (-l static:+foo,-bar=mylib).

Motivation

Occasionally some tweaks to linking behavior

ふるまい
of native libraries are necessary, and currently there's no way to apply
適用する
them.

For example, some static

静的な
libraries may need to be linked as a whole archive without throwing any object files away because some symbols in them appear
現れる
to be unused while actually having some effect.
This RFC introduces modifier whole-archive to address this.

In other cases we need to link to a library located at some specific

特定の
path or not matching
一致する、マッチさせる
the default naming conventions.
This RFC introduces modifier verbatim to pass such libraries to the linker.

This RFC also reformulates the static-nobundle linking kind as a modifier bundle thus

それゆえに、従って、
providing
与える
an opportunity to change the static
静的な
linking default to non-bundling on some future edition boundary, and hopefully unblocking its stabilization.

The generic syntax

文法
provides
与える
a way to add more such modifiers in the future without introducing new linking kinds.

Guide-level explanation

This is an advanced feature not expected to be used commonly, see the reference-level explanation if you know that you need some of these modifiers.

Reference-level explanation

Existing syntax
文法
of linking attributes and options

  • Attributes: #[link(name = "string", kind = "string", cfg(predicate))] (some components
    構成要素
    are optional.)
  • Command line options: -l kind=name:rename (some components
    構成要素
    are optional).

Proposed extensions to the syntax
文法

  • Attributes: #[link(/* same */, modifiers = "+foo,-bar")].
  • Command line options: -l kind:+foo,-bar=name:rename.

The modifiers are boolean

真偽の
and applied
適用する
only to the single
単一の
library specified
特定する、指定する、規定する
with name.
+ means enable, - means disable, multiple
複数の
options can be separated
分割する
by commas, the last boolean
真偽の
value specified
特定する、指定する、規定する
for the given
与えられた
modifier wins.
The notation
記法
is borrowed from target features in general
一般
and should have the same semantics.

If the :rename component

構成要素
is specified
特定する、指定する、規定する
on the command line, then in addition
追加
to the name and linking kind the modifiers will be updated as well (using concatenation).

Specific
特定の
modifiers

bundle

Only compatible with the static

静的な
linking kind.

+bundle means objects from the static

静的な
library are bundled into the produced
産出、産出する
crate (a rlib, for example) and are used from this crate later during linking of the final binary.
2進数

-bundle means the static

静的な
library is included into the produced
産出、産出する
rlib "by name" and object files from it are included only during linking of the final binary,
2進数
the file search by that name is also performed during final linking.

This modifier is supposed to supersede the static-nobundle linking kind defined

定義する
by RFC 1717.

The default for this modifier is currently +bundle, but it could be changed later on some future edition boundary.

verbatim

+verbatim means that rustc itself won't add any target-specified library prefixes

接頭辞
or suffixes (like lib or .a) to the library name, and will try its best to ask for the same thing from the linker.

For ld-like linkers rustc will use the -l:filename syntax

文法
(note the colon) when passing the library, so the linker won't add any prefixes
接頭辞
or suffixes as well.
See -l namespec in ld documentation
文書
for more details.
For linkers not supporting any verbatim modifiers (e.g. link.exe or ld64) the library name will be passed as is.

The default for this modifier is -verbatim.

This RFC changes the behavior

ふるまい
of raw-dylib linking kind specified
特定する、指定する、規定する
by RFC 2627. The .dll suffix (or other target-specified suffixes for other targets) is now added
たす
automatically.
自動的に

If your DLL doesn't have the .dll suffix, it can be specified
特定する、指定する、規定する
with +verbatim.

whole-archive

Only compatible with the static

静的な
linking kind.

+whole-archive means that the static

静的な
library is linked as a whole archive without throwing any object files away.

This modifier translates to --whole-archive for ld-like linkers, to /WHOLEARCHIVE for link.exe, and to -force_load for ld64.
The modifier does nothing for linkers that don't support it.

The default for this modifier is -whole-archive.

A motivating example for this modifier can be found in issue #56306.

as-needed

Only compatible with the dynamic and framework linking kinds.

+as-needed means that the library will be actually linked only if it satisfies

満たす、満足させる
some undefined symbols at the point at which it is specified
特定する、指定する、規定する
on the command line, making it similar
似ている、同様の
to static
静的な
libraries in this regard.

This modifier translates to --as-needed for ld-like linkers, and to -dead_strip_dylibs / -needed_library / -needed_framework for ld64.
The modifier does nothing for linkers that don't support it (e.g. link.exe).

The default for this modifier is unclear, some targets currently specify

特定する、指定する、規定する
it as +as-needed, some do not. We may want to try making +as-needed a default for all targets.

A motivating example for this modifier can be found in issue #57837.

Stability story

The modifier syntax

文法
can be stabilized independently from any specific
特定の
modifiers.

All the specific

特定の
modifiers start unstable and can be stabilized independently from each other given
与えられた
enough demand.

This RFC also proposes to guarantee

保証する
that the relative order
順序
of -l and -Clink-arg(s) command line options of rustc is preserved when passing them to linker.
(Currently they are passed independently and the order
順序
is not guaranteed.)

This provides

与える
ability to tweak linking of individual
個々の、それぞれの
libraries on the command line by using raw
生の
linker options.
An equivalent
等価
of order-preserving -Clink-arg, but in an attribute form,
形式、形態、形作る
is not provided
与える
at this time.

Drawbacks

Some extra complexity in parsing

構文解析する
the modifiers and converting
変換する
them into a form
形式、形態、形作る
suitable for the linker.

Not all modifiers are applicable to all targets and linkers, but that's true for many existing -C options as well.

Rationale and alternatives
代わりのもの、選択肢

Alternative:
代わりのもの、選択肢
rely on raw
生の
linker options

The primary

主要な、初等の、第一の
alternative
代わりのもの、選択肢
for the (relatively cross-platform) whole-archive and as-needed modifiers is to rely on more target-specific raw
生の
linker options more.

(Note, that raw

生の
linker options don't cover the bundle and verbatim modifiers that are rustc-specific.)

The modifier support is removed from the command line options, the desired effect is achieved by something like this.

-Clink-arg=-Wl,--whole-archive -lfoo -Clink-arg=-Wl,--no-whole-archive

Note the -Wl, that is needed when using gcc as a linker, but not when using an ld-like linker directly.

直接
So this solution is not only more target-specific, but also more linker specific
特定の
as well.

The -Wl, part can potentially be added

たす
automatically
自動的に
though, there's some prior art from CMake regarding this, see the LINKER: modifier for target_link_options.

Relying on raw

生の
linker options while linking with attributes will requires introducing a new attribute, see the paragraph about #[link(arg = "string")] in "Future possibilities".

Alternative:
代わりのもの、選択肢
merge modifiers into kind in attributes

#[link(kind = "static",

静的な
modifiers = "+foo,-bar")] -> #[link(kind = "static:+foo,-bar")].

This make attributes closer to command line, but it's unclear whether it's a goal we want to pursue. For example, we already write kind=name on command line, but kind = "...", name = "..." in attributes.

Prior art

gcc provides

与える
the -Wl,foo command line syntax
文法
(and some other similar
似ている、同様の
options) for passing arbitrary
任意の
options directly
直接
to the linker.

The relative order

順序
of -Wl options and -l options linking the libraries is preserved.

cl.exe provides

与える
/link link-opts for passing options directly
直接
to the linker, but the options supported by link.exe are generally order-independent, so it is not as relevant to modifying behavior
ふるまい
of specific
特定の
libraries as with ld-like linkers.

Unresolved questions

None currently.

Future possibilities

New modifiers

dedup

rustc doesn't currently deduplicate linked libraries in general

.

The reason is that sometimes the linked libraries need to be duplicated on the command line.

However, such cases are rare

まれ
and we may want to deduplicate the libraries by default, but provide the -dedup modifier as an opt-out for these rare
まれ
cases.

Introducing the dedup modifier with the current -dedup default doesn't make much sense.

Support #[link(arg = "string")] in addition
追加
to the modifiers

ld supports some other niche per-library options, for example --copy-dt-needed-entries.

ld also supports order-dependent options like --start-group/--end-group applying

適用する
to groups of libraries.

We may want to avoid

避ける、回避する
new modifiers for all possible cases like this and provide an order-preserving analogue of -C link-arg, but in the attribute form.
形式、形態、形作る

It may also resolve
解決する
issues with the existing unstable attribute #[link_args] and serve as its replacement.

Some analogue of CMake's LINKER: mentioned above can improve portability

移植性
here.