Skip to content

Commit d4c40b5

Browse files
committed
Bring the linkage documentation up-to-date
This includes documentation for all the previous changes done to linking in #10582. Additionally, this brings the list of feature-gates up-to-date with the currently recognized list of features.
1 parent f9d6fd2 commit d4c40b5

File tree

2 files changed

+223
-19
lines changed

2 files changed

+223
-19
lines changed

doc/rust.md

+139
Original file line numberDiff line numberDiff line change
@@ -2070,6 +2070,38 @@ The currently implemented features of the compiler are:
20702070
closure as `once` is unlikely to be supported going forward. So
20712071
they are hidden behind this feature until they are to be removed.
20722072

2073+
* `managed_boxes` - Usage of `@` pointers is gated due to many
2074+
planned changes to this feature. In the past, this has meant
2075+
"a GC pointer", but the current implementation uses
2076+
reference counting and will likely change drastically over
2077+
time. Additionally, the `@` syntax will no longer be used to
2078+
create GC boxes.
2079+
2080+
* `asm` - The `asm!` macro provides a means for inline assembly. This is often
2081+
useful, but the exact syntax for this feature along with its semantics
2082+
are likely to change, so this macro usage must be opted into.
2083+
2084+
* `non_ascii_idents` - The compiler supports the use of non-ascii identifiers,
2085+
but the implementation is a little rough around the
2086+
edges, so this can be seen as an experimental feature for
2087+
now until the specification of identifiers is fully
2088+
fleshed out.
2089+
2090+
* `thread_local` - The usage of the `#[thread_local]` attribute is experimental
2091+
and should be seen as unstable. This attribute is used to
2092+
declare a `static` as being unique per-thread leveraging
2093+
LLVM's implementation which works in concert with the kernel
2094+
loader and dynamic linker. This is not necessarily available
2095+
on all platforms, and usage of it is discouraged (rust
2096+
focuses more on task-local data instead of thread-local
2097+
data).
2098+
2099+
* `link_args` - This attribute is used to specify custom flags to the linker,
2100+
but usage is strongly discouraged. The compiler's usage of the
2101+
system linker is not guaranteed to continue in the future, and
2102+
if the system linker is not used then specifying custom flags
2103+
doesn't have much meaning.
2104+
20732105
If a feature is promoted to a language feature, then all existing programs will
20742106
start to receive compilation warnings about #[feature] directives which enabled
20752107
the new feature (because the directive is no longer necessary). However, if
@@ -3611,6 +3643,111 @@ queues, as well as code to copy values between queues and their recipients and
36113643
to serialize values for transmission over operating-system inter-process
36123644
communication facilities.
36133645

3646+
### Linkage
3647+
3648+
The Rust compiler supports various methods to link crates together both
3649+
statically and dynamically. This section will explore the various methods to
3650+
link Rust crates together, and more information about native libraries can be
3651+
found in the [ffi tutorial][ffi].
3652+
3653+
In one session of compilation, the compiler can generate multiple artifacts
3654+
through the usage of command line flags and the `crate_type` attribute.
3655+
3656+
* `--bin`, `#[crate_type = "bin"]` - A runnable executable will be produced.
3657+
This requires that there is a `main` function in the crate which will be run
3658+
when the program begins executing. This will link in all Rust and native
3659+
dependencies, producing a distributable binary.
3660+
3661+
* `--lib`, `#[crate_type = "lib"]` - A Rust library will be produced. This is
3662+
an ambiguous concept as to what exactly is produced because a library can
3663+
manifest itself in several forms. The purpose of this generic `lib` option is
3664+
to generate the "compiler recommended" style of library. The output library
3665+
will always be usable by rustc, but the actual type of library may change
3666+
from time-to-time. The remaining output types are all different flavors of
3667+
libraries, and the `lib` type can be seen as an alias for one of them (but
3668+
the actual one is compiler-defined).
3669+
3670+
* `--dylib`, `#[crate_type = "dylib"]` - A dynamic Rust library will be
3671+
produced. This is different from the `lib` output type in that this forces
3672+
dynamic library generation. The resulting dynamic library can be used as a
3673+
dependency for other libraries and/or executables. This output type will
3674+
create `*.so` files on linux, `*.dylib` files on osx, and `*.dll` files on
3675+
windows.
3676+
3677+
* `--staticlib`, `#[crate_type = "staticlib"]` - A static system library will
3678+
be produced. This is different from other library outputs in that the Rust
3679+
compiler will never attempt to link to `staticlib` outputs. The purpose of
3680+
this output type is to create a static library containing all of the local
3681+
crate's code along with all upstream dependencies. The static library is
3682+
actually a `*.a` archive on linux and osx and a `*.lib` file on windows. This
3683+
format is recommended for use in situtations such as linking Rust code into an
3684+
existing non-Rust application because it will not have dynamic dependencies on
3685+
other Rust code.
3686+
3687+
* `--rlib`, `#[crate_type = "rlib"]` - A "Rust library" file will be produced.
3688+
This is used as an intermediate artifact and can be thought of as a "static
3689+
Rust library". These `rlib` files, unlike `staticlib` files, are interpreted
3690+
by the Rust compiler in future linkage. This essentially means that `rustc`
3691+
will look for metadata in `rlib` files like it looks for metadata in dynamic
3692+
libraries. This form of output is used to produce statically linked
3693+
executables as well as `staticlib` outputs.
3694+
3695+
Note that these outputs are stackable in the sense that if multiple are
3696+
specified, then the compiler will produce each form of output at once without
3697+
having to recompile.
3698+
3699+
With all these different kinds of outputs, if crate A depends on crate B, then
3700+
the compiler could find B in various different forms throughout the system. The
3701+
only forms looked for by the compiler, however, are the `rlib` format and the
3702+
dynamic library format. With these two options for a dependent library, the
3703+
compiler must at some point make a choice between these two formats. With this
3704+
in mind, the compiler follows these rules when determining what format of
3705+
dependencies will be used:
3706+
3707+
1. If a dynamic library is being produced, then it is required for all upstream
3708+
Rust dependencies to also be dynamic. This is a limitation of the current
3709+
implementation of the linkage model. The reason behind this limitation is to
3710+
prevent multiple copies of the same upstream library from showing up, and in
3711+
the future it is planned to support a mixture of dynamic and static linking.
3712+
3713+
When producing a dynamic library, the compiler will generate an error if an
3714+
upstream dependency could not be found, and also if an upstream dependency
3715+
could only be found in an `rlib` format. Remember that `staticlib` formats
3716+
are always ignored by `rustc` for crate-linking purposes.
3717+
3718+
2. If a static library is being produced, all upstream dependecies are
3719+
required to be available in `rlib` formats. This requirement stems from the
3720+
same reasons that a dynamic library must have all dynamic dependencies.
3721+
3722+
Note that it is impossible to link in native dynamic dependencies to a static
3723+
library, and in this case warnings will be printed about all unlinked native
3724+
dynamic dependencies.
3725+
3726+
3. If an `rlib` file is being produced, then there are no restrictions on what
3727+
format the upstream dependencies are available in. It is simply required that
3728+
all upstream dependencies be available for reading metadata from.
3729+
3730+
The reason for this is that `rlib` files do not contain any of their upstream
3731+
dependencies. It wouldn't be very efficient for all `rlib` files to contain a
3732+
copy of `libstd.rlib`!
3733+
3734+
4. If an executable is being produced, then things get a little interesting. As
3735+
with the above limitations in dynamic and static libraries, it is required
3736+
for all upstream dependencies to be in the same format. The next question is
3737+
whether to prefer a dynamic or a static format. The compiler currently favors
3738+
static linking over dynamic linking, but this can be inverted with the `-Z
3739+
prefer-dynamic` flag to the compiler.
3740+
3741+
What this means is that first the compiler will attempt to find all upstream
3742+
dependencies as `rlib` files, and if successful, it will create a statically
3743+
linked executable. If an upstream dependency is missing as an `rlib` file,
3744+
then the compiler will force all dependencies to be dynamic and will generate
3745+
errors if dynamic versions could not be found.
3746+
3747+
In general, `--bin` or `--lib` should be sufficient for all compilation needs,
3748+
and the other options are just available if more fine-grained control is desired
3749+
over the output format of a Rust crate.
3750+
36143751
### Logging system
36153752

36163753
The runtime contains a system for directing [logging
@@ -3762,3 +3899,5 @@ Additional specific influences can be seen from the following languages:
37623899
* The typeclass system of Haskell.
37633900
* The lexical identifier rule of Python.
37643901
* The block syntax of Ruby.
3902+
3903+
[ffi]: tutorial-ffi.html

doc/tutorial-ffi.md

+84-19
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ foreign code. Rust is currently unable to call directly into a C++ library, but
88
snappy includes a C interface (documented in
99
[`snappy-c.h`](https://code.google.com/p/snappy/source/browse/trunk/snappy-c.h)).
1010

11-
The following is a minimal example of calling a foreign function which will compile if snappy is
12-
installed:
11+
The following is a minimal example of calling a foreign function which will
12+
compile if snappy is installed:
1313

1414
~~~~ {.xfail-test}
1515
use std::libc::size_t;
1616
17-
#[link_args = "-lsnappy"]
17+
#[link(name = "snappy")]
1818
extern {
1919
fn snappy_max_compressed_length(source_length: size_t) -> size_t;
2020
}
@@ -25,26 +25,28 @@ fn main() {
2525
}
2626
~~~~
2727

28-
The `extern` block is a list of function signatures in a foreign library, in this case with the
29-
platform's C ABI. The `#[link_args]` attribute is used to instruct the linker to link against the
30-
snappy library so the symbols are resolved.
28+
The `extern` block is a list of function signatures in a foreign library, in
29+
this case with the platform's C ABI. The `#[link(...)]` attribute is used to
30+
instruct the linker to link against the snappy library so the symbols are
31+
resolved.
3132

32-
Foreign functions are assumed to be unsafe so calls to them need to be wrapped with `unsafe {}` as a
33-
promise to the compiler that everything contained within truly is safe. C libraries often expose
34-
interfaces that aren't thread-safe, and almost any function that takes a pointer argument isn't
35-
valid for all possible inputs since the pointer could be dangling, and raw pointers fall outside of
33+
Foreign functions are assumed to be unsafe so calls to them need to be wrapped
34+
with `unsafe {}` as a promise to the compiler that everything contained within
35+
truly is safe. C libraries often expose interfaces that aren't thread-safe, and
36+
almost any function that takes a pointer argument isn't valid for all possible
37+
inputs since the pointer could be dangling, and raw pointers fall outside of
3638
Rust's safe memory model.
3739

38-
When declaring the argument types to a foreign function, the Rust compiler will not check if the
39-
declaration is correct, so specifying it correctly is part of keeping the binding correct at
40-
runtime.
40+
When declaring the argument types to a foreign function, the Rust compiler can
41+
not check if the declaration is correct, so specifying it correctly is part of
42+
keeping the binding correct at runtime.
4143

4244
The `extern` block can be extended to cover the entire snappy API:
4345

4446
~~~~ {.xfail-test}
4547
use std::libc::{c_int, size_t};
4648
47-
#[link_args = "-lsnappy"]
49+
#[link(name = "snappy")]
4850
extern {
4951
fn snappy_compress(input: *u8,
5052
input_length: size_t,
@@ -232,9 +234,72 @@ fn main() {
232234

233235
# Linking
234236

235-
In addition to the `#[link_args]` attribute for explicitly passing arguments to the linker, an
236-
`extern mod` block will pass `-lmodname` to the linker by default unless it has a `#[nolink]`
237-
attribute applied.
237+
The `link` attribute on `extern` blocks provides the basic building block for
238+
instructing rustc how it will link to native libraries. There are two accepted
239+
forms of the link attribute today:
240+
241+
* `#[link(name = "foo")]`
242+
* `#[link(name = "foo", kind = "bar")]`
243+
244+
In both of these cases, `foo` is the name of the native library that we're
245+
linking to, and in the second case `bar` is the type of native library that the
246+
compiler is linking to. There are currently three known types of native
247+
libraries:
248+
249+
* Dynamic - `#[link(name = "readline")]
250+
* Static - `#[link(name = "my_build_dependency", kind = "static")]
251+
* Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]
252+
253+
Note that frameworks are only available on OSX targets.
254+
255+
The different `kind` values are meant to differentiate how the native library
256+
participates in linkage. From a linkage perspective, the rust compiler creates
257+
two flavors of artifacts: partial (rlib/staticlib) and final (dylib/binary).
258+
Native dynamic libraries and frameworks are propagated to the final artifact
259+
boundary, while static libraries are not propagated at all.
260+
261+
A few examples of how this model can be used are:
262+
263+
* A native build dependency. Sometimes some C/C++ glue is needed when writing
264+
some rust code, but distribution of the C/C++ code in a library format is just
265+
a burden. In this case, the code will be archived into `libfoo.a` and then the
266+
rust crate would declare a dependency via `#[link(name = "foo", kind =
267+
"static")]`.
268+
269+
Regardless of the flavor of output for the crate, the native static library
270+
will be included in the output, meaning that distribution of the native static
271+
library is not necessary.
272+
273+
* A normal dynamic dependency. Common system libraries (like `readline`) are
274+
available on a large number of systems, and often a static copy of these
275+
libraries cannot be found. When this dependency is included in a rust crate,
276+
partial targets (like rlibs) will not link to the library, but when the rlib
277+
is included in a final target (like a binary), the native library will be
278+
linked in.
279+
280+
On OSX, frameworks behave with the same semantics as a dynamic library.
281+
282+
## The `link_args` attribute
283+
284+
There is one other way to tell rustc how to customize linking, and that is via
285+
the `link_args` attribute. This attribute is applied to `extern` blocks and
286+
specifies raw flags which need to get passed to the linker when producing an
287+
artifact. An example usage would be:
288+
289+
~~~ {.xfail-test}
290+
#[link_args = "-foo -bar -baz"]
291+
extern {}
292+
~~~
293+
294+
Note that this feature is currently hidden behind the `feature(link_args)` gate
295+
because this is not a sanctioned way of performing linking. Right now rustc
296+
shells out to the system linker, so it makes sense to provide extra command line
297+
arguments, but this will not always be the case. In the future rustc may use
298+
LLVM directly to link native libraries in which case `link_args` will have no
299+
meaning.
300+
301+
It is highly recommended to *not* use this attribute, and rather use the more
302+
formal `#[link(...)]` attribute on `extern` blocks instead.
238303

239304
# Unsafe blocks
240305

@@ -260,7 +325,7 @@ blocks with the `static` keyword:
260325
~~~{.xfail-test}
261326
use std::libc;
262327
263-
#[link_args = "-lreadline"]
328+
#[link(name = "readline")]
264329
extern {
265330
static rl_readline_version: libc::c_int;
266331
}
@@ -279,7 +344,7 @@ them.
279344
use std::libc;
280345
use std::ptr;
281346
282-
#[link_args = "-lreadline"]
347+
#[link(name = "readline")]
283348
extern {
284349
static mut rl_prompt: *libc::c_char;
285350
}

0 commit comments

Comments
 (0)