rustc_target/spec/
crt_objects.rs

1//! Object files providing support for basic runtime facilities and added to the produced binaries
2//! at the start and at the end of linking.
3//!
4//! Table of CRT objects for popular toolchains.
5//! The `crtx` ones are generally distributed with libc and the `begin/end` ones with gcc.
6//! See <https://dev.gentoo.org/~vapier/crt.txt> for some more details.
7//!
8//! | Pre-link CRT objects | glibc                  | musl                   | bionic           | mingw             | wasi         |
9//! |----------------------|------------------------|------------------------|------------------|-------------------|--------------|
10//! | dynamic-nopic-exe    | crt1, crti, crtbegin   | crt1, crti, crtbegin   | crtbegin_dynamic | crt2, crtbegin    | crt1         |
11//! | dynamic-pic-exe      | Scrt1, crti, crtbeginS | Scrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin    | crt1         |
12//! | static-nopic-exe     | crt1, crti, crtbeginT  | crt1, crti, crtbegin   | crtbegin_static  | crt2, crtbegin    | crt1         |
13//! | static-pic-exe       | rcrt1, crti, crtbeginS | rcrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin    | crt1         |
14//! | dynamic-dylib        | crti, crtbeginS        | crti, crtbeginS        | crtbegin_so      | dllcrt2, crtbegin | -            |
15//! | static-dylib (gcc)   | crti, crtbeginT        | crti, crtbeginS        | crtbegin_so      | dllcrt2, crtbegin | -            |
16//! | static-dylib (clang) | crti, crtbeginT        | N/A                    | crtbegin_static  | dllcrt2, crtbegin | -            |
17//! | wasi-reactor-exe     | N/A                    | N/A                    | N/A              | N/A               | crt1-reactor |
18//!
19//! | Post-link CRT objects | glibc         | musl          | bionic         | mingw  | wasi |
20//! |-----------------------|---------------|---------------|----------------|--------|------|
21//! | dynamic-nopic-exe     | crtend, crtn  | crtend, crtn  | crtend_android | crtend | -    |
22//! | dynamic-pic-exe       | crtendS, crtn | crtendS, crtn | crtend_android | crtend | -    |
23//! | static-nopic-exe      | crtend, crtn  | crtend, crtn  | crtend_android | crtend | -    |
24//! | static-pic-exe        | crtendS, crtn | crtendS, crtn | crtend_android | crtend | -    |
25//! | dynamic-dylib         | crtendS, crtn | crtendS, crtn | crtend_so      | crtend | -    |
26//! | static-dylib (gcc)    | crtend, crtn  | crtendS, crtn | crtend_so      | crtend | -    |
27//! | static-dylib (clang)  | crtendS, crtn | N/A           | crtend_so      | crtend | -    |
28//!
29//! Use cases for rustc linking the CRT objects explicitly:
30//!     - rustc needs to add its own Rust-specific objects (mingw is the example)
31//!     - gcc wrapper cannot be used for some reason and linker like ld or lld is used directly.
32//!     - gcc wrapper pulls wrong CRT objects (e.g. from glibc when we are targeting musl).
33//!
34//! In general it is preferable to rely on the target's native toolchain to pull the objects.
35//! However, for some targets (musl, mingw) rustc historically provides a more self-contained
36//! installation not requiring users to install the native target's toolchain.
37//! In that case rustc distributes the objects as a part of the target's Rust toolchain
38//! and falls back to linking with them manually.
39//! Unlike native toolchains, rustc only currently adds the libc's objects during linking,
40//! but not gcc's. As a result rustc cannot link with C++ static libraries (#36710)
41//! when linking in self-contained mode.
42
43use std::borrow::Cow;
44use std::collections::BTreeMap;
45
46use crate::spec::LinkOutputKind;
47
48pub type CrtObjects = BTreeMap<LinkOutputKind, Vec<Cow<'static, str>>>;
49
50pub(super) fn new(obj_table: &[(LinkOutputKind, &[&'static str])]) -> CrtObjects {
51    obj_table.iter().map(|(z, k)| (*z, k.iter().map(|b| (*b).into()).collect())).collect()
52}
53
54pub(super) fn all(obj: &'static str) -> CrtObjects {
55    new(&[
56        (LinkOutputKind::DynamicNoPicExe, &[obj]),
57        (LinkOutputKind::DynamicPicExe, &[obj]),
58        (LinkOutputKind::StaticNoPicExe, &[obj]),
59        (LinkOutputKind::StaticPicExe, &[obj]),
60        (LinkOutputKind::DynamicDylib, &[obj]),
61        (LinkOutputKind::StaticDylib, &[obj]),
62    ])
63}
64
65pub(super) fn pre_musl_self_contained() -> CrtObjects {
66    new(&[
67        (LinkOutputKind::DynamicNoPicExe, &["crt1.o", "crti.o", "crtbegin.o"]),
68        (LinkOutputKind::DynamicPicExe, &["Scrt1.o", "crti.o", "crtbeginS.o"]),
69        (LinkOutputKind::StaticNoPicExe, &["crt1.o", "crti.o", "crtbegin.o"]),
70        (LinkOutputKind::StaticPicExe, &["rcrt1.o", "crti.o", "crtbeginS.o"]),
71        (LinkOutputKind::DynamicDylib, &["crti.o", "crtbeginS.o"]),
72        (LinkOutputKind::StaticDylib, &["crti.o", "crtbeginS.o"]),
73    ])
74}
75
76pub(super) fn post_musl_self_contained() -> CrtObjects {
77    new(&[
78        (LinkOutputKind::DynamicNoPicExe, &["crtend.o", "crtn.o"]),
79        (LinkOutputKind::DynamicPicExe, &["crtendS.o", "crtn.o"]),
80        (LinkOutputKind::StaticNoPicExe, &["crtend.o", "crtn.o"]),
81        (LinkOutputKind::StaticPicExe, &["crtendS.o", "crtn.o"]),
82        (LinkOutputKind::DynamicDylib, &["crtendS.o", "crtn.o"]),
83        (LinkOutputKind::StaticDylib, &["crtendS.o", "crtn.o"]),
84    ])
85}
86
87pub(super) fn pre_mingw_self_contained() -> CrtObjects {
88    new(&[
89        (LinkOutputKind::DynamicNoPicExe, &["crt2.o", "rsbegin.o"]),
90        (LinkOutputKind::DynamicPicExe, &["crt2.o", "rsbegin.o"]),
91        (LinkOutputKind::StaticNoPicExe, &["crt2.o", "rsbegin.o"]),
92        (LinkOutputKind::StaticPicExe, &["crt2.o", "rsbegin.o"]),
93        (LinkOutputKind::DynamicDylib, &["dllcrt2.o", "rsbegin.o"]),
94        (LinkOutputKind::StaticDylib, &["dllcrt2.o", "rsbegin.o"]),
95    ])
96}
97
98pub(super) fn post_mingw_self_contained() -> CrtObjects {
99    all("rsend.o")
100}
101
102pub(super) fn pre_mingw() -> CrtObjects {
103    all("rsbegin.o")
104}
105
106pub(super) fn post_mingw() -> CrtObjects {
107    all("rsend.o")
108}
109
110pub(super) fn pre_wasi_self_contained() -> CrtObjects {
111    // Use crt1-command.o instead of crt1.o to enable support for new-style
112    // commands. See https://reviews.llvm.org/D81689 for more info.
113    new(&[
114        (LinkOutputKind::DynamicNoPicExe, &["crt1-command.o"]),
115        (LinkOutputKind::DynamicPicExe, &["crt1-command.o"]),
116        (LinkOutputKind::StaticNoPicExe, &["crt1-command.o"]),
117        (LinkOutputKind::StaticPicExe, &["crt1-command.o"]),
118        (LinkOutputKind::WasiReactorExe, &["crt1-reactor.o"]),
119    ])
120}
121
122pub(super) fn post_wasi_self_contained() -> CrtObjects {
123    new(&[])
124}