]> git.proxmox.com Git - rustc.git/blob - src/bootstrap/sanity.rs
New upstream version 1.13.0+dfsg1
[rustc.git] / src / bootstrap / sanity.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 //! Sanity checking performed by rustbuild before actually executing anything.
12 //!
13 //! This module contains the implementation of ensuring that the build
14 //! environment looks reasonable before progressing. This will verify that
15 //! various programs like git and python exist, along with ensuring that all C
16 //! compilers for cross-compiling are found.
17 //!
18 //! In theory if we get past this phase it's a bug if a build fails, but in
19 //! practice that's likely not true!
20
21 use std::collections::HashSet;
22 use std::env;
23 use std::ffi::{OsStr, OsString};
24 use std::fs;
25 use std::process::Command;
26
27 use build_helper::output;
28
29 use Build;
30
31 pub fn check(build: &mut Build) {
32 let mut checked = HashSet::new();
33 let path = env::var_os("PATH").unwrap_or(OsString::new());
34 // On Windows, quotes are invalid characters for filename paths, and if
35 // one is present as part of the PATH then that can lead to the system
36 // being unable to identify the files properly. See
37 // https://github.com/rust-lang/rust/issues/34959 for more details.
38 if cfg!(windows) {
39 if path.to_string_lossy().contains("\"") {
40 panic!("PATH contains invalid character '\"'");
41 }
42 }
43 let mut need_cmd = |cmd: &OsStr| {
44 if !checked.insert(cmd.to_owned()) {
45 return
46 }
47 for path in env::split_paths(&path).map(|p| p.join(cmd)) {
48 if fs::metadata(&path).is_ok() ||
49 fs::metadata(path.with_extension("exe")).is_ok() {
50 return
51 }
52 }
53 panic!("\n\ncouldn't find required command: {:?}\n\n", cmd);
54 };
55
56 // If we've got a git directory we're gona need git to update
57 // submodules and learn about various other aspects.
58 if fs::metadata(build.src.join(".git")).is_ok() {
59 need_cmd("git".as_ref());
60 }
61
62 // We need cmake, but only if we're actually building LLVM
63 for host in build.config.host.iter() {
64 if let Some(config) = build.config.target_config.get(host) {
65 if config.llvm_config.is_some() {
66 continue
67 }
68 }
69 need_cmd("cmake".as_ref());
70 if build.config.ninja {
71 need_cmd("ninja".as_ref())
72 }
73 break
74 }
75
76 need_cmd("python".as_ref());
77
78 // If a manual nodejs was added to the config,
79 // of if a nodejs install is detected through config, use it.
80 if let Some(ref s) = build.config.nodejs {
81 need_cmd(s.as_ref());
82 }
83
84 // We're gonna build some custom C code here and there, host triples
85 // also build some C++ shims for LLVM so we need a C++ compiler.
86 for target in build.config.target.iter() {
87 need_cmd(build.cc(target).as_ref());
88 if let Some(ar) = build.ar(target) {
89 need_cmd(ar.as_ref());
90 }
91 }
92 for host in build.config.host.iter() {
93 need_cmd(build.cxx(host).as_ref());
94 }
95
96 // Externally configured LLVM requires FileCheck to exist
97 let filecheck = build.llvm_filecheck(&build.config.build);
98 if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
99 panic!("filecheck executable {:?} does not exist", filecheck);
100 }
101
102 for target in build.config.target.iter() {
103 // Either can't build or don't want to run jemalloc on these targets
104 if target.contains("rumprun") ||
105 target.contains("bitrig") ||
106 target.contains("openbsd") ||
107 target.contains("msvc") ||
108 target.contains("emscripten") {
109 build.config.use_jemalloc = false;
110 }
111
112 // Can't compile for iOS unless we're on OSX
113 if target.contains("apple-ios") &&
114 !build.config.build.contains("apple-darwin") {
115 panic!("the iOS target is only supported on OSX");
116 }
117
118 // Make sure musl-root is valid if specified
119 if target.contains("musl") && !target.contains("mips") {
120 match build.musl_root(target) {
121 Some(root) => {
122 if fs::metadata(root.join("lib/libc.a")).is_err() {
123 panic!("couldn't find libc.a in musl dir: {}",
124 root.join("lib").display());
125 }
126 if fs::metadata(root.join("lib/libunwind.a")).is_err() {
127 panic!("couldn't find libunwind.a in musl dir: {}",
128 root.join("lib").display());
129 }
130 }
131 None => {
132 panic!("when targeting MUSL either the build.musl-root \
133 option or the target.$TARGET.musl-root one must \
134 be specified in config.toml")
135 }
136 }
137 }
138
139 if target.contains("msvc") {
140 // There are three builds of cmake on windows: MSVC, MinGW, and
141 // Cygwin. The Cygwin build does not have generators for Visual
142 // Studio, so detect that here and error.
143 let out = output(Command::new("cmake").arg("--help"));
144 if !out.contains("Visual Studio") {
145 panic!("
146 cmake does not support Visual Studio generators.
147
148 This is likely due to it being an msys/cygwin build of cmake,
149 rather than the required windows version, built using MinGW
150 or Visual Studio.
151
152 If you are building under msys2 try installing the mingw-w64-x86_64-cmake
153 package instead of cmake:
154
155 $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
156 ");
157 }
158 }
159
160 if target.contains("arm-linux-android") {
161 need_cmd("adb".as_ref());
162 }
163 }
164
165 for host in build.flags.host.iter() {
166 if !build.config.host.contains(host) {
167 panic!("specified host `{}` is not in the ./configure list", host);
168 }
169 }
170 for target in build.flags.target.iter() {
171 if !build.config.target.contains(target) {
172 panic!("specified target `{}` is not in the ./configure list",
173 target);
174 }
175 }
176
177 let run = |cmd: &mut Command| {
178 cmd.output().map(|output| {
179 String::from_utf8_lossy(&output.stdout)
180 .lines().next().unwrap()
181 .to_string()
182 })
183 };
184 build.gdb_version = run(Command::new("gdb").arg("--version")).ok();
185 build.lldb_version = run(Command::new("lldb").arg("--version")).ok();
186 if build.lldb_version.is_some() {
187 build.lldb_python_dir = run(Command::new("lldb").arg("-P")).ok();
188 }
189 }