1# Linkage
2
3> Note: This section is described more in terms of the compiler than of
4> the language.
5
6The compiler supports various methods to link crates together both
7statically and dynamically. This section will explore the various methods to
8link crates together, and more information about native libraries can be
9found in the [FFI section of the book][ffi].
10
11[ffi]: ../book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code
12
13In one session of compilation, the compiler can generate multiple artifacts
14through the usage of either command line flags or the `crate_type` attribute.
15If one or more command line flags are specified, all `crate_type` attributes will
16be ignored in favor of only building the artifacts specified by command line.
17
18* `--crate-type=bin`, `#[crate_type = "bin"]` - A runnable executable will be
19  produced. This requires that there is a `main` function in the crate which
20  will be run when the program begins executing. This will link in all Rust and
21  native dependencies, producing a single distributable binary.
22  This is the default crate type.
23
24* `--crate-type=lib`, `#[crate_type = "lib"]` - A Rust library will be produced.
25  This is an ambiguous concept as to what exactly is produced because a library
26  can manifest itself in several forms. The purpose of this generic `lib` option
27  is to generate the "compiler recommended" style of library. The output library
28  will always be usable by rustc, but the actual type of library may change from
29  time-to-time. The remaining output types are all different flavors of
30  libraries, and the `lib` type can be seen as an alias for one of them (but the
31  actual one is compiler-defined).
32
33* `--crate-type=dylib`, `#[crate_type = "dylib"]` - A dynamic Rust library will
34  be produced. This is different from the `lib` output type in that this forces
35  dynamic library generation. The resulting dynamic library can be used as a
36  dependency for other libraries and/or executables. This output type will
37  create `*.so` files on Linux, `*.dylib` files on macOS, and `*.dll` files on
38  Windows.
39
40* `--crate-type=staticlib`, `#[crate_type = "staticlib"]` - A static system
41  library will be produced. This is different from other library outputs in that
42  the compiler will never attempt to link to `staticlib` outputs. The
43  purpose of this output type is to create a static library containing all of
44  the local crate's code along with all upstream dependencies. This output type
45  will create `*.a` files on Linux, macOS and Windows (MinGW), and `*.lib` files
46  on Windows (MSVC). This format is recommended for use in situations such as
47  linking Rust code into an existing non-Rust application
48  because it will not have dynamic dependencies on other Rust code.
49
50* `--crate-type=cdylib`, `#[crate_type = "cdylib"]` - A dynamic system
51  library will be produced.  This is used when compiling
52  a dynamic library to be loaded from another language.  This output type will
53  create `*.so` files on Linux, `*.dylib` files on macOS, and `*.dll` files on
54  Windows.
55
56* `--crate-type=rlib`, `#[crate_type = "rlib"]` - A "Rust library" file will be
57  produced. This is used as an intermediate artifact and can be thought of as a
58  "static Rust library". These `rlib` files, unlike `staticlib` files, are
59  interpreted by the compiler in future linkage. This essentially means
60  that `rustc` will look for metadata in `rlib` files like it looks for metadata
61  in dynamic libraries. This form of output is used to produce statically linked
62  executables as well as `staticlib` outputs.
63
64* `--crate-type=proc-macro`, `#[crate_type = "proc-macro"]` - The output
65  produced is not specified, but if a `-L` path is provided to it then the
66  compiler will recognize the output artifacts as a macro and it can be loaded
67  for a program. Crates compiled with this crate type  must only export
68  [procedural macros]. The compiler will automatically set the `proc_macro`
69  [configuration option]. The crates are always compiled with the same target
70  that the compiler itself was built with. For example, if you are executing
71  the compiler from Linux with an `x86_64` CPU, the target will be
72  `x86_64-unknown-linux-gnu` even if the crate is a dependency of another crate
73  being built for a different target.
74
75Note that these outputs are stackable in the sense that if multiple are
76specified, then the compiler will produce each form of output at once without
77having to recompile. However, this only applies for outputs specified by the
78same method. If only `crate_type` attributes are specified, then they will all
79be built, but if one or more `--crate-type` command line flags are specified,
80then only those outputs will be built.
81
82With all these different kinds of outputs, if crate A depends on crate B, then
83the compiler could find B in various different forms throughout the system. The
84only forms looked for by the compiler, however, are the `rlib` format and the
85dynamic library format. With these two options for a dependent library, the
86compiler must at some point make a choice between these two formats. With this
87in mind, the compiler follows these rules when determining what format of
88dependencies will be used:
89
901. If a static library is being produced, all upstream dependencies are
91   required to be available in `rlib` formats. This requirement stems from the
92   reason that a dynamic library cannot be converted into a static format.
93
94   Note that it is impossible to link in native dynamic dependencies to a static
95   library, and in this case warnings will be printed about all unlinked native
96   dynamic dependencies.
97
982. If an `rlib` file is being produced, then there are no restrictions on what
99   format the upstream dependencies are available in. It is simply required that
100   all upstream dependencies be available for reading metadata from.
101
102   The reason for this is that `rlib` files do not contain any of their upstream
103   dependencies. It wouldn't be very efficient for all `rlib` files to contain a
104   copy of `libstd.rlib`!
105
1063. If an executable is being produced and the `-C prefer-dynamic` flag is not
107   specified, then dependencies are first attempted to be found in the `rlib`
108   format. If some dependencies are not available in an rlib format, then
109   dynamic linking is attempted (see below).
110
1114. If a dynamic library or an executable that is being dynamically linked is
112   being produced, then the compiler will attempt to reconcile the available
113   dependencies in either the rlib or dylib format to create a final product.
114
115   A major goal of the compiler is to ensure that a library never appears more
116   than once in any artifact. For example, if dynamic libraries B and C were
117   each statically linked to library A, then a crate could not link to B and C
118   together because there would be two copies of A. The compiler allows mixing
119   the rlib and dylib formats, but this restriction must be satisfied.
120
121   The compiler currently implements no method of hinting what format a library
122   should be linked with. When dynamically linking, the compiler will attempt to
123   maximize dynamic dependencies while still allowing some dependencies to be
124   linked in via an rlib.
125
126   For most situations, having all libraries available as a dylib is recommended
127   if dynamically linking. For other situations, the compiler will emit a
128   warning if it is unable to determine which formats to link each library with.
129
130In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for
131all compilation needs, and the other options are just available if more
132fine-grained control is desired over the output format of a crate.
133
134## Static and dynamic C runtimes
135
136The standard library in general strives to support both statically linked and
137dynamically linked C runtimes for targets as appropriate. For example the
138`x86_64-pc-windows-msvc` and `x86_64-unknown-linux-musl` targets typically come
139with both runtimes and the user selects which one they'd like. All targets in
140the compiler have a default mode of linking to the C runtime. Typically targets
141are linked dynamically by default, but there are exceptions which are static by
142default such as:
143
144* `arm-unknown-linux-musleabi`
145* `arm-unknown-linux-musleabihf`
146* `armv7-unknown-linux-musleabihf`
147* `i686-unknown-linux-musl`
148* `x86_64-unknown-linux-musl`
149
150The linkage of the C runtime is configured to respect the `crt-static` target
151feature. These target features are typically configured from the command line
152via flags to the compiler itself. For example to enable a static runtime you
153would execute:
154
155```sh
156rustc -C target-feature=+crt-static foo.rs
157```
158
159whereas to link dynamically to the C runtime you would execute:
160
161```sh
162rustc -C target-feature=-crt-static foo.rs
163```
164
165Targets which do not support switching between linkage of the C runtime will
166ignore this flag. It's recommended to inspect the resulting binary to ensure
167that it's linked as you would expect after the compiler succeeds.
168
169Crates may also learn about how the C runtime is being linked. Code on MSVC, for
170example, needs to be compiled differently (e.g. with `/MT` or `/MD`) depending
171on the runtime being linked. This is exported currently through the
172[`cfg` attribute `target_feature` option]:
173
174```rust
175#[cfg(target_feature = "crt-static")]
176fn foo() {
177    println!("the C runtime should be statically linked");
178}
179
180#[cfg(not(target_feature = "crt-static"))]
181fn foo() {
182    println!("the C runtime should be dynamically linked");
183}
184```
185
186Also note that Cargo build scripts can learn about this feature through
187[environment variables][cargo]. In a build script you can detect the linkage
188via:
189
190```rust
191use std::env;
192
193fn main() {
194    let linkage = env::var("CARGO_CFG_TARGET_FEATURE").unwrap_or(String::new());
195
196    if linkage.contains("crt-static") {
197        println!("the C runtime will be statically linked");
198    } else {
199        println!("the C runtime will be dynamically linked");
200    }
201}
202```
203
204[cargo]: ../cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
205
206To use this feature locally, you typically will use the `RUSTFLAGS` environment
207variable to specify flags to the compiler through Cargo. For example to compile
208a statically linked binary on MSVC you would execute:
209
210```sh
211RUSTFLAGS='-C target-feature=+crt-static' cargo build --target x86_64-pc-windows-msvc
212```
213
214[`cfg` attribute `target_feature` option]: conditional-compilation.md#target_feature
215[configuration option]: conditional-compilation.md
216[procedural macros]: procedural-macros.md
217