1 //! Implementation of the install aspects of the compiler.
3 //! This module is responsible for installing the standard library,
4 //! compiler, and documentation.
8 use std::path::{Component, Path, PathBuf};
9 use std::process::Command;
13 use crate::dist::{self, sanitize_sh};
14 use crate::tarball::GeneratedTarball;
17 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
18 use crate::config::{Config, TargetSelection};
21 builder: &Builder<'_>,
24 host: Option<TargetSelection>,
25 tarball: &GeneratedTarball,
27 builder.info(&format!("Install {} stage{} ({:?})", package, stage, host));
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);
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);
50 let destdir = env::var_os("DESTDIR").map(PathBuf::from);
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);
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))
67 let empty_dir = builder.out.join("tmp/empty_dir");
69 t!(fs::create_dir_all(&empty_dir));
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));
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(),
91 for part in path.components() {
92 if let Component::Normal(s) = part {
99 macro_rules! install {
100 (($sel:ident, $builder:ident, $_config:ident),
104 only_hosts: $only_hosts:expr,
105 $run_item:block $(, $c:ident)*;)+) => {
107 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
109 pub compiler: Compiler,
110 pub target: TargetSelection,
115 fn should_build(config: &Config) -> bool {
116 config.extended && config.tools.as_ref()
117 .map_or(true, |t| t.contains($path))
121 impl Step for $name {
123 const DEFAULT: bool = true;
124 const ONLY_HOSTS: bool = $only_hosts;
125 $(const $c: bool = true;)*
127 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
128 let $_config = &run.builder.config;
129 run.path($path).default_condition($default_cond)
132 fn make_run(run: RunConfig<'_>) {
133 run.builder.ensure($name {
134 compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
139 fn run($sel, $builder: &Builder<'_>) {
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);
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,
156 }).expect("missing std");
157 install_sh(builder, "std", self.compiler.stage, Some(*target), &tarball);
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);
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);
169 &format!("skipping Install RLS stage{} ({})", self.compiler.stage, self.target),
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);
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);
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);
188 &format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target),
192 Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
193 if let Some(tarball) = builder.ensure(dist::Rustfmt {
194 compiler: self.compiler,
197 install_sh(builder, "rustfmt", self.compiler.stage, Some(self.target), &tarball);
200 &format!("skipping Install Rustfmt stage{} ({})", self.compiler.stage, self.target),
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),
211 }).expect("missing analysis");
212 install_sh(builder, "analysis", self.compiler.stage, Some(self.target), &tarball);
214 Rustc, "src/librustc", true, only_hosts: true, {
215 let tarball = builder.ensure(dist::Rustc {
216 compiler: builder.compiler(builder.top_stage, self.target),
218 install_sh(builder, "rustc", self.compiler.stage, Some(self.target), &tarball);
222 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
229 const DEFAULT: bool = true;
230 const ONLY_HOSTS: bool = true;
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)
238 fn make_run(run: RunConfig<'_>) {
239 run.builder.ensure(Src { stage: run.builder.top_stage });
242 fn run(self, builder: &Builder<'_>) {
243 let tarball = builder.ensure(dist::Src);
244 install_sh(builder, "src", self.stage, None, &tarball);