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, pkgname, sanitize_sh, tmpdir}
;
16 use crate::builder
::{Builder, RunConfig, ShouldRun, Step}
;
17 use crate::cache
::Interned
;
18 use crate::config
::Config
;
20 pub fn install_docs(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
21 install_sh(builder
, "docs", "rust-docs", stage
, Some(host
));
24 pub fn install_std(builder
: &Builder
<'_
>, stage
: u32, target
: Interned
<String
>) {
25 install_sh(builder
, "std", "rust-std", stage
, Some(target
));
28 pub fn install_cargo(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
29 install_sh(builder
, "cargo", "cargo", stage
, Some(host
));
32 pub fn install_rls(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
33 install_sh(builder
, "rls", "rls", stage
, Some(host
));
35 pub fn install_rust_analyzer(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
36 install_sh(builder
, "rust-analyzer", "rust-analyzer", stage
, Some(host
));
38 pub fn install_clippy(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
39 install_sh(builder
, "clippy", "clippy", stage
, Some(host
));
41 pub fn install_miri(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
42 install_sh(builder
, "miri", "miri", stage
, Some(host
));
45 pub fn install_rustfmt(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
46 install_sh(builder
, "rustfmt", "rustfmt", stage
, Some(host
));
49 pub fn install_analysis(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
50 install_sh(builder
, "analysis", "rust-analysis", stage
, Some(host
));
53 pub fn install_src(builder
: &Builder
<'_
>, stage
: u32) {
54 install_sh(builder
, "src", "rust-src", stage
, None
);
56 pub fn install_rustc(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
57 install_sh(builder
, "rustc", "rustc", stage
, Some(host
));
61 builder
: &Builder
<'_
>,
65 host
: Option
<Interned
<String
>>,
67 builder
.info(&format
!("Install {} stage{} ({:?})", package
, stage
, host
));
69 let prefix_default
= PathBuf
::from("/usr/local");
70 let sysconfdir_default
= PathBuf
::from("/etc");
71 let datadir_default
= PathBuf
::from("share");
72 let docdir_default
= datadir_default
.join("doc/rust");
73 let libdir_default
= PathBuf
::from("lib");
74 let mandir_default
= datadir_default
.join("man");
75 let prefix
= builder
.config
.prefix
.as_ref().map_or(prefix_default
, |p
| {
77 .unwrap_or_else(|err
| panic
!("could not create {}: {}", p
.display(), err
));
79 .unwrap_or_else(|err
| panic
!("could not canonicalize {}: {}", p
.display(), err
))
81 let sysconfdir
= builder
.config
.sysconfdir
.as_ref().unwrap_or(&sysconfdir_default
);
82 let datadir
= builder
.config
.datadir
.as_ref().unwrap_or(&datadir_default
);
83 let docdir
= builder
.config
.docdir
.as_ref().unwrap_or(&docdir_default
);
84 let bindir
= &builder
.config
.bindir
;
85 let libdir
= builder
.config
.libdir
.as_ref().unwrap_or(&libdir_default
);
86 let mandir
= builder
.config
.mandir
.as_ref().unwrap_or(&mandir_default
);
88 let sysconfdir
= prefix
.join(sysconfdir
);
89 let datadir
= prefix
.join(datadir
);
90 let docdir
= prefix
.join(docdir
);
91 let bindir
= prefix
.join(bindir
);
92 let libdir
= prefix
.join(libdir
);
93 let mandir
= prefix
.join(mandir
);
95 let destdir
= env
::var_os("DESTDIR").map(PathBuf
::from
);
97 let prefix
= add_destdir(&prefix
, &destdir
);
98 let sysconfdir
= add_destdir(&sysconfdir
, &destdir
);
99 let datadir
= add_destdir(&datadir
, &destdir
);
100 let docdir
= add_destdir(&docdir
, &destdir
);
101 let bindir
= add_destdir(&bindir
, &destdir
);
102 let libdir
= add_destdir(&libdir
, &destdir
);
103 let mandir
= add_destdir(&mandir
, &destdir
);
105 let empty_dir
= builder
.out
.join("tmp/empty_dir");
107 t
!(fs
::create_dir_all(&empty_dir
));
108 let package_name
= if let Some(host
) = host
{
109 format
!("{}-{}", pkgname(builder
, name
), host
)
111 pkgname(builder
, name
)
114 let mut cmd
= Command
::new("sh");
115 cmd
.current_dir(&empty_dir
)
116 .arg(sanitize_sh(&tmpdir(builder
).join(&package_name
).join("install.sh")))
117 .arg(format
!("--prefix={}", sanitize_sh(&prefix
)))
118 .arg(format
!("--sysconfdir={}", sanitize_sh(&sysconfdir
)))
119 .arg(format
!("--datadir={}", sanitize_sh(&datadir
)))
120 .arg(format
!("--docdir={}", sanitize_sh(&docdir
)))
121 .arg(format
!("--bindir={}", sanitize_sh(&bindir
)))
122 .arg(format
!("--libdir={}", sanitize_sh(&libdir
)))
123 .arg(format
!("--mandir={}", sanitize_sh(&mandir
)))
124 .arg("--disable-ldconfig");
125 builder
.run(&mut cmd
);
126 t
!(fs
::remove_dir_all(&empty_dir
));
129 fn add_destdir(path
: &Path
, destdir
: &Option
<PathBuf
>) -> PathBuf
{
130 let mut ret
= match *destdir
{
131 Some(ref dest
) => dest
.clone(),
132 None
=> return path
.to_path_buf(),
134 for part
in path
.components() {
135 if let Component
::Normal(s
) = part
{
142 macro_rules
! install
{
143 (($sel
:ident
, $builder
:ident
, $_config
:ident
),
147 only_hosts
: $only_hosts
:expr
,
148 $run_item
:block $
(, $c
:ident
)*;)+) => {
150 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
152 pub compiler
: Compiler
,
153 pub target
: Interned
<String
>,
158 fn should_build(config
: &Config
) -> bool
{
159 config
.extended
&& config
.tools
.as_ref()
160 .map_or(true, |t
| t
.contains($path
))
164 impl Step
for $name
{
166 const DEFAULT
: bool
= true;
167 const ONLY_HOSTS
: bool
= $only_hosts
;
168 $
(const $c
: bool
= true;)*
170 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
171 let $_config
= &run
.builder
.config
;
172 run
.path($path
).default_condition($default_cond
)
175 fn make_run(run
: RunConfig
<'_
>) {
176 run
.builder
.ensure($name
{
177 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.builder
.config
.build
),
182 fn run($sel
, $builder
: &Builder
<'_
>) {
189 install
!((self, builder
, _config
),
190 Docs
, "src/doc", _config
.docs
, only_hosts
: false, {
191 builder
.ensure(dist
::Docs { host: self.target }
);
192 install_docs(builder
, self.compiler
.stage
, self.target
);
194 Std
, "src/libstd", true, only_hosts
: true, {
195 for target
in &builder
.targets
{
196 builder
.ensure(dist
::Std
{
197 compiler
: self.compiler
,
200 install_std(builder
, self.compiler
.stage
, *target
);
203 Cargo
, "cargo", Self::should_build(_config
), only_hosts
: true, {
204 builder
.ensure(dist
::Cargo { compiler: self.compiler, target: self.target }
);
205 install_cargo(builder
, self.compiler
.stage
, self.target
);
207 Rls
, "rls", Self::should_build(_config
), only_hosts
: true, {
208 if builder
.ensure(dist
::Rls { compiler: self.compiler, target: self.target }
).is_some() {
209 install_rls(builder
, self.compiler
.stage
, self.target
);
212 &format
!("skipping Install RLS stage{} ({})", self.compiler
.stage
, self.target
),
216 RustAnalyzer
, "rust-analyzer", Self::should_build(_config
), only_hosts
: true, {
217 builder
.ensure(dist
::RustAnalyzer { compiler: self.compiler, target: self.target }
);
218 install_rust_analyzer(builder
, self.compiler
.stage
, self.target
);
220 Clippy
, "clippy", Self::should_build(_config
), only_hosts
: true, {
221 builder
.ensure(dist
::Clippy { compiler: self.compiler, target: self.target }
);
222 install_clippy(builder
, self.compiler
.stage
, self.target
);
224 Miri
, "miri", Self::should_build(_config
), only_hosts
: true, {
225 if builder
.ensure(dist
::Miri { compiler: self.compiler, target: self.target }
).is_some() {
226 install_miri(builder
, self.compiler
.stage
, self.target
);
229 &format
!("skipping Install miri stage{} ({})", self.compiler
.stage
, self.target
),
233 Rustfmt
, "rustfmt", Self::should_build(_config
), only_hosts
: true, {
234 if builder
.ensure(dist
::Rustfmt
{
235 compiler
: self.compiler
,
238 install_rustfmt(builder
, self.compiler
.stage
, self.target
);
241 &format
!("skipping Install Rustfmt stage{} ({})", self.compiler
.stage
, self.target
),
245 Analysis
, "analysis", Self::should_build(_config
), only_hosts
: false, {
246 builder
.ensure(dist
::Analysis
{
247 // Find the actual compiler (handling the full bootstrap option) which
248 // produced the save-analysis data because that data isn't copied
249 // through the sysroot uplifting.
250 compiler
: builder
.compiler_for(builder
.top_stage
, builder
.config
.build
, self.target
),
253 install_analysis(builder
, self.compiler
.stage
, self.target
);
255 Rustc
, "src/librustc", true, only_hosts
: true, {
256 builder
.ensure(dist
::Rustc
{
257 compiler
: builder
.compiler(builder
.top_stage
, self.target
),
259 install_rustc(builder
, self.compiler
.stage
, self.target
);
263 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
270 const DEFAULT
: bool
= true;
271 const ONLY_HOSTS
: bool
= true;
273 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
274 let config
= &run
.builder
.config
;
275 let cond
= config
.extended
&& config
.tools
.as_ref().map_or(true, |t
| t
.contains("src"));
276 run
.path("src").default_condition(cond
)
279 fn make_run(run
: RunConfig
<'_
>) {
280 run
.builder
.ensure(Src { stage: run.builder.top_stage }
);
283 fn run(self, builder
: &Builder
<'_
>) {
284 builder
.ensure(dist
::Src
);
285 install_src(builder
, self.stage
);