]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/install.rs
Auto merge of #80711 - camelid:intrinsic-of-val-safety, r=oli-obk
[rust.git] / src / bootstrap / install.rs
1 //! Implementation of the install aspects of the compiler.
2 //!
3 //! This module is responsible for installing the standard library,
4 //! compiler, and documentation.
5
6 use std::env;
7 use std::fs;
8 use std::path::{Component, Path, PathBuf};
9 use std::process::Command;
10
11 use build_helper::t;
12
13 use crate::dist::{self, sanitize_sh};
14 use crate::tarball::GeneratedTarball;
15 use crate::Compiler;
16
17 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
18 use crate::config::{Config, TargetSelection};
19
20 fn install_sh(
21     builder: &Builder<'_>,
22     package: &str,
23     stage: u32,
24     host: Option<TargetSelection>,
25     tarball: &GeneratedTarball,
26 ) {
27     builder.info(&format!("Install {} stage{} ({:?})", package, stage, host));
28
29     let prefix_default = PathBuf::from("/usr/local");
30     let sysconfdir_default = PathBuf::from("/etc");
31     let datadir_default = PathBuf::from("share");
32     let docdir_default = datadir_default.join("doc/rust");
33     let libdir_default = PathBuf::from("lib");
34     let mandir_default = datadir_default.join("man");
35     let prefix = builder.config.prefix.as_ref().unwrap_or(&prefix_default);
36     let sysconfdir = builder.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
37     let datadir = builder.config.datadir.as_ref().unwrap_or(&datadir_default);
38     let docdir = builder.config.docdir.as_ref().unwrap_or(&docdir_default);
39     let bindir = &builder.config.bindir;
40     let libdir = builder.config.libdir.as_ref().unwrap_or(&libdir_default);
41     let mandir = builder.config.mandir.as_ref().unwrap_or(&mandir_default);
42
43     let sysconfdir = prefix.join(sysconfdir);
44     let datadir = prefix.join(datadir);
45     let docdir = prefix.join(docdir);
46     let bindir = prefix.join(bindir);
47     let libdir = prefix.join(libdir);
48     let mandir = prefix.join(mandir);
49
50     let destdir = env::var_os("DESTDIR").map(PathBuf::from);
51
52     let prefix = add_destdir(&prefix, &destdir);
53     let sysconfdir = add_destdir(&sysconfdir, &destdir);
54     let datadir = add_destdir(&datadir, &destdir);
55     let docdir = add_destdir(&docdir, &destdir);
56     let bindir = add_destdir(&bindir, &destdir);
57     let libdir = add_destdir(&libdir, &destdir);
58     let mandir = add_destdir(&mandir, &destdir);
59
60     let prefix = {
61         fs::create_dir_all(&prefix)
62             .unwrap_or_else(|err| panic!("could not create {}: {}", prefix.display(), err));
63         fs::canonicalize(&prefix)
64             .unwrap_or_else(|err| panic!("could not canonicalize {}: {}", prefix.display(), err))
65     };
66
67     let empty_dir = builder.out.join("tmp/empty_dir");
68
69     t!(fs::create_dir_all(&empty_dir));
70
71     let mut cmd = Command::new("sh");
72     cmd.current_dir(&empty_dir)
73         .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh")))
74         .arg(format!("--prefix={}", sanitize_sh(&prefix)))
75         .arg(format!("--sysconfdir={}", sanitize_sh(&sysconfdir)))
76         .arg(format!("--datadir={}", sanitize_sh(&datadir)))
77         .arg(format!("--docdir={}", sanitize_sh(&docdir)))
78         .arg(format!("--bindir={}", sanitize_sh(&bindir)))
79         .arg(format!("--libdir={}", sanitize_sh(&libdir)))
80         .arg(format!("--mandir={}", sanitize_sh(&mandir)))
81         .arg("--disable-ldconfig");
82     builder.run(&mut cmd);
83     t!(fs::remove_dir_all(&empty_dir));
84 }
85
86 fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
87     let mut ret = match *destdir {
88         Some(ref dest) => dest.clone(),
89         None => return path.to_path_buf(),
90     };
91     for part in path.components() {
92         if let Component::Normal(s) = part {
93             ret.push(s)
94         }
95     }
96     ret
97 }
98
99 macro_rules! install {
100     (($sel:ident, $builder:ident, $_config:ident),
101        $($name:ident,
102        $path:expr,
103        $default_cond:expr,
104        only_hosts: $only_hosts:expr,
105        $run_item:block $(, $c:ident)*;)+) => {
106         $(
107             #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
108         pub struct $name {
109             pub compiler: Compiler,
110             pub target: TargetSelection,
111         }
112
113         impl $name {
114             #[allow(dead_code)]
115             fn should_build(config: &Config) -> bool {
116                 config.extended && config.tools.as_ref()
117                     .map_or(true, |t| t.contains($path))
118             }
119         }
120
121         impl Step for $name {
122             type Output = ();
123             const DEFAULT: bool = true;
124             const ONLY_HOSTS: bool = $only_hosts;
125             $(const $c: bool = true;)*
126
127             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
128                 let $_config = &run.builder.config;
129                 run.path($path).default_condition($default_cond)
130             }
131
132             fn make_run(run: RunConfig<'_>) {
133                 run.builder.ensure($name {
134                     compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
135                     target: run.target,
136                 });
137             }
138
139             fn run($sel, $builder: &Builder<'_>) {
140                 $run_item
141             }
142         })+
143     }
144 }
145
146 install!((self, builder, _config),
147     Docs, "src/doc", _config.docs, only_hosts: false, {
148         let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs");
149         install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball);
150     };
151     Std, "library/std", true, only_hosts: false, {
152         for target in &builder.targets {
153             let tarball = builder.ensure(dist::Std {
154                 compiler: self.compiler,
155                 target: *target
156             }).expect("missing std");
157             install_sh(builder, "std", self.compiler.stage, Some(*target), &tarball);
158         }
159     };
160     Cargo, "cargo", Self::should_build(_config), only_hosts: true, {
161         let tarball = builder.ensure(dist::Cargo { compiler: self.compiler, target: self.target });
162         install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball);
163     };
164     Rls, "rls", Self::should_build(_config), only_hosts: true, {
165         if let Some(tarball) = builder.ensure(dist::Rls { compiler: self.compiler, target: self.target }) {
166             install_sh(builder, "rls", self.compiler.stage, Some(self.target), &tarball);
167         } else {
168             builder.info(
169                 &format!("skipping Install RLS stage{} ({})", self.compiler.stage, self.target),
170             );
171         }
172     };
173     RustAnalyzer, "rust-analyzer", Self::should_build(_config), only_hosts: true, {
174         let tarball = builder
175             .ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target })
176             .expect("missing rust-analyzer");
177         install_sh(builder, "rust-analyzer", self.compiler.stage, Some(self.target), &tarball);
178     };
179     Clippy, "clippy", Self::should_build(_config), only_hosts: true, {
180         let tarball = builder.ensure(dist::Clippy { compiler: self.compiler, target: self.target });
181         install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball);
182     };
183     Miri, "miri", Self::should_build(_config), only_hosts: true, {
184         if let Some(tarball) = builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }) {
185             install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
186         } else {
187             builder.info(
188                 &format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target),
189             );
190         }
191     };
192     Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
193         if let Some(tarball) = builder.ensure(dist::Rustfmt {
194             compiler: self.compiler,
195             target: self.target
196         }) {
197             install_sh(builder, "rustfmt", self.compiler.stage, Some(self.target), &tarball);
198         } else {
199             builder.info(
200                 &format!("skipping Install Rustfmt stage{} ({})", self.compiler.stage, self.target),
201             );
202         }
203     };
204     Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
205         let tarball = builder.ensure(dist::Analysis {
206             // Find the actual compiler (handling the full bootstrap option) which
207             // produced the save-analysis data because that data isn't copied
208             // through the sysroot uplifting.
209             compiler: builder.compiler_for(builder.top_stage, builder.config.build, self.target),
210             target: self.target
211         }).expect("missing analysis");
212         install_sh(builder, "analysis", self.compiler.stage, Some(self.target), &tarball);
213     };
214     Rustc, "src/librustc", true, only_hosts: true, {
215         let tarball = builder.ensure(dist::Rustc {
216             compiler: builder.compiler(builder.top_stage, self.target),
217         });
218         install_sh(builder, "rustc", self.compiler.stage, Some(self.target), &tarball);
219     };
220 );
221
222 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
223 pub struct Src {
224     pub stage: u32,
225 }
226
227 impl Step for Src {
228     type Output = ();
229     const DEFAULT: bool = true;
230     const ONLY_HOSTS: bool = true;
231
232     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
233         let config = &run.builder.config;
234         let cond = config.extended && config.tools.as_ref().map_or(true, |t| t.contains("src"));
235         run.path("src").default_condition(cond)
236     }
237
238     fn make_run(run: RunConfig<'_>) {
239         run.builder.ensure(Src { stage: run.builder.top_stage });
240     }
241
242     fn run(self, builder: &Builder<'_>) {
243         let tarball = builder.ensure(dist::Src);
244         install_sh(builder, "src", self.stage, None, &tarball);
245     }
246 }