]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/cc.rs
Rollup merge of #44533 - nrc:rustfmt-submod, r=alexcrichton
[rust.git] / src / bootstrap / cc.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! C-compiler probing and detection.
12 //!
13 //! This module will fill out the `cc` and `cxx` maps of `Build` by looking for
14 //! C and C++ compilers for each target configured. A compiler is found through
15 //! a number of vectors (in order of precedence)
16 //!
17 //! 1. Configuration via `target.$target.cc` in `config.toml`.
18 //! 2. Configuration via `target.$target.android-ndk` in `config.toml`, if
19 //!    applicable
20 //! 3. Special logic to probe on OpenBSD
21 //! 4. The `CC_$target` environment variable.
22 //! 5. The `CC` environment variable.
23 //! 6. "cc"
24 //!
25 //! Some of this logic is implemented here, but much of it is farmed out to the
26 //! `gcc` crate itself, so we end up having the same fallbacks as there.
27 //! Similar logic is then used to find a C++ compiler, just some s/cc/c++/ is
28 //! used.
29 //!
30 //! It is intended that after this module has run no C/C++ compiler will
31 //! ever be probed for. Instead the compilers found here will be used for
32 //! everything.
33
34 use std::process::Command;
35 use std::iter;
36
37 use build_helper::{cc2ar, output};
38 use gcc;
39
40 use Build;
41 use config::Target;
42 use cache::Interned;
43
44 pub fn find(build: &mut Build) {
45     // For all targets we're going to need a C compiler for building some shims
46     // and such as well as for being a linker for Rust code.
47     for target in build.targets.iter().chain(&build.hosts).cloned().chain(iter::once(build.build)) {
48         let mut cfg = gcc::Build::new();
49         cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false)
50            .target(&target).host(&build.build);
51
52         let config = build.config.target_config.get(&target);
53         if let Some(cc) = config.and_then(|c| c.cc.as_ref()) {
54             cfg.compiler(cc);
55         } else {
56             set_compiler(&mut cfg, "gcc", target, config, build);
57         }
58
59         let compiler = cfg.get_compiler();
60         let ar = cc2ar(compiler.path(), &target);
61         build.verbose(&format!("CC_{} = {:?}", &target, compiler.path()));
62         if let Some(ref ar) = ar {
63             build.verbose(&format!("AR_{} = {:?}", &target, ar));
64         }
65         build.cc.insert(target, (compiler, ar));
66     }
67
68     // For all host triples we need to find a C++ compiler as well
69     for host in build.hosts.iter().cloned().chain(iter::once(build.build)) {
70         let mut cfg = gcc::Build::new();
71         cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false).cpp(true)
72            .target(&host).host(&build.build);
73         let config = build.config.target_config.get(&host);
74         if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
75             cfg.compiler(cxx);
76         } else {
77             set_compiler(&mut cfg, "g++", host, config, build);
78         }
79         let compiler = cfg.get_compiler();
80         build.verbose(&format!("CXX_{} = {:?}", host, compiler.path()));
81         build.cxx.insert(host, compiler);
82     }
83 }
84
85 fn set_compiler(cfg: &mut gcc::Build,
86                 gnu_compiler: &str,
87                 target: Interned<String>,
88                 config: Option<&Target>,
89                 build: &Build) {
90     match &*target {
91         // When compiling for android we may have the NDK configured in the
92         // config.toml in which case we look there. Otherwise the default
93         // compiler already takes into account the triple in question.
94         t if t.contains("android") => {
95             if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) {
96                 let target = target.replace("armv7", "arm");
97                 let compiler = format!("{}-{}", target, gnu_compiler);
98                 cfg.compiler(ndk.join("bin").join(compiler));
99             }
100         }
101
102         // The default gcc version from OpenBSD may be too old, try using egcc,
103         // which is a gcc version from ports, if this is the case.
104         t if t.contains("openbsd") => {
105             let c = cfg.get_compiler();
106             if !c.path().ends_with(gnu_compiler) {
107                 return
108             }
109
110             let output = output(c.to_command().arg("--version"));
111             let i = match output.find(" 4.") {
112                 Some(i) => i,
113                 None => return,
114             };
115             match output[i + 3..].chars().next().unwrap() {
116                 '0' ... '6' => {}
117                 _ => return,
118             }
119             let alternative = format!("e{}", gnu_compiler);
120             if Command::new(&alternative).output().is_ok() {
121                 cfg.compiler(alternative);
122             }
123         }
124
125         "mips-unknown-linux-musl" => {
126             if cfg.get_compiler().path().to_str() == Some("gcc") {
127                 cfg.compiler("mips-linux-musl-gcc");
128             }
129         }
130         "mipsel-unknown-linux-musl" => {
131             if cfg.get_compiler().path().to_str() == Some("gcc") {
132                 cfg.compiler("mipsel-linux-musl-gcc");
133             }
134         }
135
136         t if t.contains("musl") => {
137             if let Some(root) = build.musl_root(target) {
138                 let guess = root.join("bin/musl-gcc");
139                 if guess.exists() {
140                     cfg.compiler(guess);
141                 }
142             }
143         }
144
145         _ => {}
146     }
147 }