]>
Commit | Line | Data |
---|---|---|
c30ab7b3 SL |
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 | ||
32a655c1 | 6 | use std::env; |
c30ab7b3 | 7 | use std::fs; |
fc512014 | 8 | use std::path::{Component, PathBuf}; |
c30ab7b3 SL |
9 | use std::process::Command; |
10 | ||
48663c56 XL |
11 | use build_helper::t; |
12 | ||
fc512014 XL |
13 | use crate::dist::{self, sanitize_sh}; |
14 | use crate::tarball::GeneratedTarball; | |
dc9dc135 | 15 | use crate::Compiler; |
7cac9316 | 16 | |
0731742a | 17 | use crate::builder::{Builder, RunConfig, ShouldRun, Step}; |
3dfed10e | 18 | use crate::config::{Config, TargetSelection}; |
7cac9316 | 19 | |
3b2f2976 | 20 | fn install_sh( |
9fa01778 | 21 | builder: &Builder<'_>, |
3b2f2976 | 22 | package: &str, |
3b2f2976 | 23 | stage: u32, |
3dfed10e | 24 | host: Option<TargetSelection>, |
fc512014 | 25 | tarball: &GeneratedTarball, |
3b2f2976 | 26 | ) { |
83c7162d | 27 | builder.info(&format!("Install {} stage{} ({:?})", package, stage, host)); |
3b2f2976 | 28 | |
fc512014 XL |
29 | let prefix = default_path(&builder.config.prefix, "/usr/local"); |
30 | let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc")); | |
31 | let datadir = prefix.join(default_path(&builder.config.datadir, "share")); | |
32 | let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc/rust")); | |
33 | let mandir = prefix.join(default_path(&builder.config.mandir, "share/man")); | |
34 | let libdir = prefix.join(default_path(&builder.config.libdir, "lib")); | |
35 | let bindir = prefix.join(&builder.config.bindir); // Default in config.rs | |
3b2f2976 | 36 | |
83c7162d | 37 | let empty_dir = builder.out.join("tmp/empty_dir"); |
3b2f2976 | 38 | t!(fs::create_dir_all(&empty_dir)); |
7cac9316 | 39 | |
3b2f2976 XL |
40 | let mut cmd = Command::new("sh"); |
41 | cmd.current_dir(&empty_dir) | |
fc512014 XL |
42 | .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh"))) |
43 | .arg(format!("--prefix={}", prepare_dir(prefix))) | |
44 | .arg(format!("--sysconfdir={}", prepare_dir(sysconfdir))) | |
45 | .arg(format!("--datadir={}", prepare_dir(datadir))) | |
46 | .arg(format!("--docdir={}", prepare_dir(docdir))) | |
47 | .arg(format!("--bindir={}", prepare_dir(bindir))) | |
48 | .arg(format!("--libdir={}", prepare_dir(libdir))) | |
49 | .arg(format!("--mandir={}", prepare_dir(mandir))) | |
3b2f2976 | 50 | .arg("--disable-ldconfig"); |
83c7162d | 51 | builder.run(&mut cmd); |
3b2f2976 | 52 | t!(fs::remove_dir_all(&empty_dir)); |
c30ab7b3 | 53 | } |
32a655c1 | 54 | |
fc512014 XL |
55 | fn default_path(config: &Option<PathBuf>, default: &str) -> PathBuf { |
56 | PathBuf::from(config.as_ref().cloned().unwrap_or_else(|| PathBuf::from(default))) | |
57 | } | |
58 | ||
59 | fn prepare_dir(mut path: PathBuf) -> String { | |
60 | // The DESTDIR environment variable is a standard way to install software in a subdirectory | |
61 | // while keeping the original directory structure, even if the prefix or other directories | |
62 | // contain absolute paths. | |
63 | // | |
64 | // More information on the environment variable is available here: | |
65 | // https://www.gnu.org/prep/standards/html_node/DESTDIR.html | |
66 | if let Some(destdir) = env::var_os("DESTDIR").map(PathBuf::from) { | |
67 | let without_destdir = path.clone(); | |
68 | path = destdir; | |
69 | // Custom .join() which ignores disk roots. | |
70 | for part in without_destdir.components() { | |
71 | if let Component::Normal(s) = part { | |
72 | path.push(s) | |
73 | } | |
32a655c1 SL |
74 | } |
75 | } | |
fc512014 XL |
76 | |
77 | // The installation command is not executed from the current directory, but from a temporary | |
78 | // directory. To prevent relative paths from breaking this converts relative paths to absolute | |
79 | // paths. std::fs::canonicalize is not used as that requires the path to actually be present. | |
80 | if path.is_relative() { | |
81 | path = std::env::current_dir().expect("failed to get the current directory").join(path); | |
82 | assert!(path.is_absolute(), "could not make the path relative"); | |
83 | } | |
84 | ||
85 | sanitize_sh(&path) | |
32a655c1 | 86 | } |
3b2f2976 XL |
87 | |
88 | macro_rules! install { | |
89 | (($sel:ident, $builder:ident, $_config:ident), | |
90 | $($name:ident, | |
91 | $path:expr, | |
92 | $default_cond:expr, | |
93 | only_hosts: $only_hosts:expr, | |
94 | $run_item:block $(, $c:ident)*;)+) => { | |
95 | $( | |
96 | #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] | |
97 | pub struct $name { | |
dc9dc135 | 98 | pub compiler: Compiler, |
3dfed10e | 99 | pub target: TargetSelection, |
3b2f2976 XL |
100 | } |
101 | ||
2c00a5a8 XL |
102 | impl $name { |
103 | #[allow(dead_code)] | |
104 | fn should_build(config: &Config) -> bool { | |
105 | config.extended && config.tools.as_ref() | |
106 | .map_or(true, |t| t.contains($path)) | |
107 | } | |
2c00a5a8 XL |
108 | } |
109 | ||
3b2f2976 XL |
110 | impl Step for $name { |
111 | type Output = (); | |
112 | const DEFAULT: bool = true; | |
3b2f2976 XL |
113 | const ONLY_HOSTS: bool = $only_hosts; |
114 | $(const $c: bool = true;)* | |
115 | ||
9fa01778 | 116 | fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { |
3b2f2976 XL |
117 | let $_config = &run.builder.config; |
118 | run.path($path).default_condition($default_cond) | |
119 | } | |
120 | ||
9fa01778 | 121 | fn make_run(run: RunConfig<'_>) { |
3b2f2976 | 122 | run.builder.ensure($name { |
dc9dc135 | 123 | compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build), |
3b2f2976 | 124 | target: run.target, |
3b2f2976 XL |
125 | }); |
126 | } | |
127 | ||
9fa01778 | 128 | fn run($sel, $builder: &Builder<'_>) { |
3b2f2976 XL |
129 | $run_item |
130 | } | |
131 | })+ | |
132 | } | |
133 | } | |
134 | ||
135 | install!((self, builder, _config), | |
136 | Docs, "src/doc", _config.docs, only_hosts: false, { | |
fc512014 XL |
137 | let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs"); |
138 | install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball); | |
3b2f2976 | 139 | }; |
1b1a35ee | 140 | Std, "library/std", true, only_hosts: false, { |
83c7162d | 141 | for target in &builder.targets { |
fc512014 | 142 | let tarball = builder.ensure(dist::Std { |
dc9dc135 | 143 | compiler: self.compiler, |
abe05a73 | 144 | target: *target |
fc512014 XL |
145 | }).expect("missing std"); |
146 | install_sh(builder, "std", self.compiler.stage, Some(*target), &tarball); | |
abe05a73 | 147 | } |
3b2f2976 | 148 | }; |
2c00a5a8 | 149 | Cargo, "cargo", Self::should_build(_config), only_hosts: true, { |
fc512014 XL |
150 | let tarball = builder.ensure(dist::Cargo { compiler: self.compiler, target: self.target }); |
151 | install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball); | |
3b2f2976 | 152 | }; |
2c00a5a8 | 153 | Rls, "rls", Self::should_build(_config), only_hosts: true, { |
fc512014 XL |
154 | if let Some(tarball) = builder.ensure(dist::Rls { compiler: self.compiler, target: self.target }) { |
155 | install_sh(builder, "rls", self.compiler.stage, Some(self.target), &tarball); | |
abe05a73 | 156 | } else { |
dc9dc135 XL |
157 | builder.info( |
158 | &format!("skipping Install RLS stage{} ({})", self.compiler.stage, self.target), | |
159 | ); | |
abe05a73 XL |
160 | } |
161 | }; | |
f035d41b | 162 | RustAnalyzer, "rust-analyzer", Self::should_build(_config), only_hosts: true, { |
fc512014 XL |
163 | let tarball = builder |
164 | .ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target }) | |
165 | .expect("missing rust-analyzer"); | |
166 | install_sh(builder, "rust-analyzer", self.compiler.stage, Some(self.target), &tarball); | |
f035d41b | 167 | }; |
8faf50e0 | 168 | Clippy, "clippy", Self::should_build(_config), only_hosts: true, { |
fc512014 XL |
169 | let tarball = builder.ensure(dist::Clippy { compiler: self.compiler, target: self.target }); |
170 | install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball); | |
8faf50e0 | 171 | }; |
0731742a | 172 | Miri, "miri", Self::should_build(_config), only_hosts: true, { |
fc512014 XL |
173 | if let Some(tarball) = builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }) { |
174 | install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball); | |
0731742a | 175 | } else { |
dc9dc135 XL |
176 | builder.info( |
177 | &format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target), | |
178 | ); | |
0731742a XL |
179 | } |
180 | }; | |
2c00a5a8 | 181 | Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, { |
fc512014 | 182 | if let Some(tarball) = builder.ensure(dist::Rustfmt { |
dc9dc135 XL |
183 | compiler: self.compiler, |
184 | target: self.target | |
fc512014 XL |
185 | }) { |
186 | install_sh(builder, "rustfmt", self.compiler.stage, Some(self.target), &tarball); | |
abe05a73 | 187 | } else { |
83c7162d | 188 | builder.info( |
dc9dc135 XL |
189 | &format!("skipping Install Rustfmt stage{} ({})", self.compiler.stage, self.target), |
190 | ); | |
abe05a73 | 191 | } |
3b2f2976 | 192 | }; |
2c00a5a8 | 193 | Analysis, "analysis", Self::should_build(_config), only_hosts: false, { |
fc512014 | 194 | let tarball = builder.ensure(dist::Analysis { |
dc9dc135 XL |
195 | // Find the actual compiler (handling the full bootstrap option) which |
196 | // produced the save-analysis data because that data isn't copied | |
197 | // through the sysroot uplifting. | |
198 | compiler: builder.compiler_for(builder.top_stage, builder.config.build, self.target), | |
3b2f2976 | 199 | target: self.target |
fc512014 XL |
200 | }).expect("missing analysis"); |
201 | install_sh(builder, "analysis", self.compiler.stage, Some(self.target), &tarball); | |
3b2f2976 | 202 | }; |
3b2f2976 | 203 | Rustc, "src/librustc", true, only_hosts: true, { |
fc512014 | 204 | let tarball = builder.ensure(dist::Rustc { |
60c5eb7d | 205 | compiler: builder.compiler(builder.top_stage, self.target), |
3b2f2976 | 206 | }); |
fc512014 | 207 | install_sh(builder, "rustc", self.compiler.stage, Some(self.target), &tarball); |
3b2f2976 XL |
208 | }; |
209 | ); | |
0531ce1d XL |
210 | |
211 | #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] | |
212 | pub struct Src { | |
213 | pub stage: u32, | |
214 | } | |
215 | ||
216 | impl Step for Src { | |
217 | type Output = (); | |
218 | const DEFAULT: bool = true; | |
219 | const ONLY_HOSTS: bool = true; | |
220 | ||
9fa01778 | 221 | fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { |
0531ce1d | 222 | let config = &run.builder.config; |
dc9dc135 | 223 | let cond = config.extended && config.tools.as_ref().map_or(true, |t| t.contains("src")); |
0531ce1d XL |
224 | run.path("src").default_condition(cond) |
225 | } | |
226 | ||
9fa01778 | 227 | fn make_run(run: RunConfig<'_>) { |
dc9dc135 | 228 | run.builder.ensure(Src { stage: run.builder.top_stage }); |
0531ce1d XL |
229 | } |
230 | ||
9fa01778 | 231 | fn run(self, builder: &Builder<'_>) { |
fc512014 XL |
232 | let tarball = builder.ensure(dist::Src); |
233 | install_sh(builder, "src", self.stage, None, &tarball); | |
0531ce1d XL |
234 | } |
235 | } |