]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_codegen_cranelift/src/toolchain.rs
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / compiler / rustc_codegen_cranelift / src / toolchain.rs
1 //! Locating various executables part of a C toolchain.
2
3 use std::path::PathBuf;
4
5 use rustc_middle::bug;
6 use rustc_session::Session;
7 use rustc_target::spec::LinkerFlavor;
8
9 /// Tries to infer the path of a binary for the target toolchain from the linker name.
10 pub(crate) fn get_toolchain_binary(sess: &Session, tool: &str) -> PathBuf {
11 let (mut linker, _linker_flavor) = linker_and_flavor(sess);
12 let linker_file_name = linker
13 .file_name()
14 .and_then(|name| name.to_str())
15 .unwrap_or_else(|| sess.fatal("couldn't extract file name from specified linker"));
16
17 if linker_file_name == "ld.lld" {
18 if tool != "ld" {
19 linker.set_file_name(tool)
20 }
21 } else {
22 let tool_file_name = linker_file_name
23 .replace("ld", tool)
24 .replace("gcc", tool)
25 .replace("clang", tool)
26 .replace("cc", tool);
27
28 linker.set_file_name(tool_file_name)
29 }
30
31 linker
32 }
33
34 // Adapted from https://github.com/rust-lang/rust/blob/5db778affee7c6600c8e7a177c48282dab3f6292/src/librustc_codegen_ssa/back/link.rs#L848-L931
35 fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
36 fn infer_from(
37 sess: &Session,
38 linker: Option<PathBuf>,
39 flavor: Option<LinkerFlavor>,
40 ) -> Option<(PathBuf, LinkerFlavor)> {
41 match (linker, flavor) {
42 (Some(linker), Some(flavor)) => Some((linker, flavor)),
43 // only the linker flavor is known; use the default linker for the selected flavor
44 (None, Some(flavor)) => Some((
45 PathBuf::from(match flavor {
46 LinkerFlavor::Em => {
47 if cfg!(windows) {
48 "emcc.bat"
49 } else {
50 "emcc"
51 }
52 }
53 LinkerFlavor::Gcc => {
54 if cfg!(any(target_os = "solaris", target_os = "illumos")) {
55 // On historical Solaris systems, "cc" may have
56 // been Sun Studio, which is not flag-compatible
57 // with "gcc". This history casts a long shadow,
58 // and many modern illumos distributions today
59 // ship GCC as "gcc" without also making it
60 // available as "cc".
61 "gcc"
62 } else {
63 "cc"
64 }
65 }
66 LinkerFlavor::Ld => "ld",
67 LinkerFlavor::Msvc => "link.exe",
68 LinkerFlavor::Lld(_) => "lld",
69 LinkerFlavor::PtxLinker => "rust-ptx-linker",
70 }),
71 flavor,
72 )),
73 (Some(linker), None) => {
74 let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| {
75 sess.fatal("couldn't extract file stem from specified linker")
76 });
77
78 let flavor = if stem == "emcc" {
79 LinkerFlavor::Em
80 } else if stem == "gcc"
81 || stem.ends_with("-gcc")
82 || stem == "clang"
83 || stem.ends_with("-clang")
84 {
85 LinkerFlavor::Gcc
86 } else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") {
87 LinkerFlavor::Ld
88 } else if stem == "link" || stem == "lld-link" {
89 LinkerFlavor::Msvc
90 } else if stem == "lld" || stem == "rust-lld" {
91 LinkerFlavor::Lld(sess.target.lld_flavor)
92 } else {
93 // fall back to the value in the target spec
94 sess.target.linker_flavor
95 };
96
97 Some((linker, flavor))
98 }
99 (None, None) => None,
100 }
101 }
102
103 // linker and linker flavor specified via command line have precedence over what the target
104 // specification specifies
105 if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), sess.opts.cg.linker_flavor) {
106 return ret;
107 }
108
109 if let Some(ret) = infer_from(
110 sess,
111 sess.target.linker.clone().map(PathBuf::from),
112 Some(sess.target.linker_flavor),
113 ) {
114 return ret;
115 }
116
117 bug!("Not enough information provided to determine how to invoke the linker");
118 }