| //! Object files providing support for basic runtime facilities and added to the produced binaries |
| //! at the start and at the end of linking. |
| //! |
| //! Table of CRT objects for popular toolchains. |
| //! The `crtx` ones are generally distributed with libc and the `begin/end` ones with gcc. |
| //! See <https://dev.gentoo.org/~vapier/crt.txt> for some more details. |
| //! |
| //! | Pre-link CRT objects | glibc | musl | bionic | mingw | wasi | |
| //! |----------------------|------------------------|------------------------|------------------|-------------------|--------------| |
| //! | dynamic-nopic-exe | crt1, crti, crtbegin | crt1, crti, crtbegin | crtbegin_dynamic | crt2, crtbegin | crt1 | |
| //! | dynamic-pic-exe | Scrt1, crti, crtbeginS | Scrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin | crt1 | |
| //! | static-nopic-exe | crt1, crti, crtbeginT | crt1, crti, crtbegin | crtbegin_static | crt2, crtbegin | crt1 | |
| //! | static-pic-exe | rcrt1, crti, crtbeginS | rcrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin | crt1 | |
| //! | dynamic-dylib | crti, crtbeginS | crti, crtbeginS | crtbegin_so | dllcrt2, crtbegin | - | |
| //! | static-dylib (gcc) | crti, crtbeginT | crti, crtbeginS | crtbegin_so | dllcrt2, crtbegin | - | |
| //! | static-dylib (clang) | crti, crtbeginT | N/A | crtbegin_static | dllcrt2, crtbegin | - | |
| //! | wasi-reactor-exe | N/A | N/A | N/A | N/A | crt1-reactor | |
| //! |
| //! | Post-link CRT objects | glibc | musl | bionic | mingw | wasi | |
| //! |-----------------------|---------------|---------------|----------------|--------|------| |
| //! | dynamic-nopic-exe | crtend, crtn | crtend, crtn | crtend_android | crtend | - | |
| //! | dynamic-pic-exe | crtendS, crtn | crtendS, crtn | crtend_android | crtend | - | |
| //! | static-nopic-exe | crtend, crtn | crtend, crtn | crtend_android | crtend | - | |
| //! | static-pic-exe | crtendS, crtn | crtendS, crtn | crtend_android | crtend | - | |
| //! | dynamic-dylib | crtendS, crtn | crtendS, crtn | crtend_so | crtend | - | |
| //! | static-dylib (gcc) | crtend, crtn | crtendS, crtn | crtend_so | crtend | - | |
| //! | static-dylib (clang) | crtendS, crtn | N/A | crtend_so | crtend | - | |
| //! |
| //! Use cases for rustc linking the CRT objects explicitly: |
| //! - rustc needs to add its own Rust-specific objects (mingw is the example) |
| //! - gcc wrapper cannot be used for some reason and linker like ld or lld is used directly. |
| //! - gcc wrapper pulls wrong CRT objects (e.g. from glibc when we are targeting musl). |
| //! |
| //! In general it is preferable to rely on the target's native toolchain to pull the objects. |
| //! However, for some targets (musl, mingw) rustc historically provides a more self-contained |
| //! installation not requiring users to install the native target's toolchain. |
| //! In that case rustc distributes the objects as a part of the target's Rust toolchain |
| //! and falls back to linking with them manually. |
| //! Unlike native toolchains, rustc only currently adds the libc's objects during linking, |
| //! but not gcc's. As a result rustc cannot link with C++ static libraries (#36710) |
| //! when linking in self-contained mode. |
| |
| use crate::json::{Json, ToJson}; |
| use crate::spec::LinkOutputKind; |
| use std::borrow::Cow; |
| use std::collections::BTreeMap; |
| use std::str::FromStr; |
| |
| pub type CrtObjects = BTreeMap<LinkOutputKind, Vec<Cow<'static, str>>>; |
| |
| pub(super) fn new(obj_table: &[(LinkOutputKind, &[&'static str])]) -> CrtObjects { |
| obj_table.iter().map(|(z, k)| (*z, k.iter().map(|b| (*b).into()).collect())).collect() |
| } |
| |
| pub(super) fn all(obj: &'static str) -> CrtObjects { |
| new(&[ |
| (LinkOutputKind::DynamicNoPicExe, &[obj]), |
| (LinkOutputKind::DynamicPicExe, &[obj]), |
| (LinkOutputKind::StaticNoPicExe, &[obj]), |
| (LinkOutputKind::StaticPicExe, &[obj]), |
| (LinkOutputKind::DynamicDylib, &[obj]), |
| (LinkOutputKind::StaticDylib, &[obj]), |
| ]) |
| } |
| |
| pub(super) fn pre_musl_fallback() -> CrtObjects { |
| new(&[ |
| (LinkOutputKind::DynamicNoPicExe, &["crt1.o", "crti.o", "crtbegin.o"]), |
| (LinkOutputKind::DynamicPicExe, &["Scrt1.o", "crti.o", "crtbeginS.o"]), |
| (LinkOutputKind::StaticNoPicExe, &["crt1.o", "crti.o", "crtbegin.o"]), |
| (LinkOutputKind::StaticPicExe, &["rcrt1.o", "crti.o", "crtbeginS.o"]), |
| (LinkOutputKind::DynamicDylib, &["crti.o", "crtbeginS.o"]), |
| (LinkOutputKind::StaticDylib, &["crti.o", "crtbeginS.o"]), |
| ]) |
| } |
| |
| pub(super) fn post_musl_fallback() -> CrtObjects { |
| new(&[ |
| (LinkOutputKind::DynamicNoPicExe, &["crtend.o", "crtn.o"]), |
| (LinkOutputKind::DynamicPicExe, &["crtendS.o", "crtn.o"]), |
| (LinkOutputKind::StaticNoPicExe, &["crtend.o", "crtn.o"]), |
| (LinkOutputKind::StaticPicExe, &["crtendS.o", "crtn.o"]), |
| (LinkOutputKind::DynamicDylib, &["crtendS.o", "crtn.o"]), |
| (LinkOutputKind::StaticDylib, &["crtendS.o", "crtn.o"]), |
| ]) |
| } |
| |
| pub(super) fn pre_mingw_fallback() -> CrtObjects { |
| new(&[ |
| (LinkOutputKind::DynamicNoPicExe, &["crt2.o", "rsbegin.o"]), |
| (LinkOutputKind::DynamicPicExe, &["crt2.o", "rsbegin.o"]), |
| (LinkOutputKind::StaticNoPicExe, &["crt2.o", "rsbegin.o"]), |
| (LinkOutputKind::StaticPicExe, &["crt2.o", "rsbegin.o"]), |
| (LinkOutputKind::DynamicDylib, &["dllcrt2.o", "rsbegin.o"]), |
| (LinkOutputKind::StaticDylib, &["dllcrt2.o", "rsbegin.o"]), |
| ]) |
| } |
| |
| pub(super) fn post_mingw_fallback() -> CrtObjects { |
| all("rsend.o") |
| } |
| |
| pub(super) fn pre_mingw() -> CrtObjects { |
| all("rsbegin.o") |
| } |
| |
| pub(super) fn post_mingw() -> CrtObjects { |
| all("rsend.o") |
| } |
| |
| pub(super) fn pre_wasi_fallback() -> CrtObjects { |
| // Use crt1-command.o instead of crt1.o to enable support for new-style |
| // commands. See https://reviews.llvm.org/D81689 for more info. |
| new(&[ |
| (LinkOutputKind::DynamicNoPicExe, &["crt1-command.o"]), |
| (LinkOutputKind::DynamicPicExe, &["crt1-command.o"]), |
| (LinkOutputKind::StaticNoPicExe, &["crt1-command.o"]), |
| (LinkOutputKind::StaticPicExe, &["crt1-command.o"]), |
| (LinkOutputKind::WasiReactorExe, &["crt1-reactor.o"]), |
| ]) |
| } |
| |
| pub(super) fn post_wasi_fallback() -> CrtObjects { |
| new(&[]) |
| } |
| |
| /// Which logic to use to determine whether to fall back to the "self-contained" mode or not. |
| #[derive(Clone, Copy, PartialEq, Hash, Debug)] |
| pub enum CrtObjectsFallback { |
| Musl, |
| Mingw, |
| Wasm, |
| } |
| |
| impl FromStr for CrtObjectsFallback { |
| type Err = (); |
| |
| fn from_str(s: &str) -> Result<CrtObjectsFallback, ()> { |
| Ok(match s { |
| "musl" => CrtObjectsFallback::Musl, |
| "mingw" => CrtObjectsFallback::Mingw, |
| "wasm" => CrtObjectsFallback::Wasm, |
| _ => return Err(()), |
| }) |
| } |
| } |
| |
| impl ToJson for CrtObjectsFallback { |
| fn to_json(&self) -> Json { |
| match *self { |
| CrtObjectsFallback::Musl => "musl", |
| CrtObjectsFallback::Mingw => "mingw", |
| CrtObjectsFallback::Wasm => "wasm", |
| } |
| .to_json() |
| } |
| } |