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
::{Path, PathBuf, Component}
;
9 use std
::process
::Command
;
13 use crate::dist
::{self, pkgname, sanitize_sh, tmpdir}
;
15 use crate::builder
::{Builder, RunConfig, ShouldRun, Step}
;
16 use crate::cache
::Interned
;
17 use crate::config
::Config
;
19 pub fn install_docs(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
20 install_sh(builder
, "docs", "rust-docs", stage
, Some(host
));
23 pub fn install_std(builder
: &Builder
<'_
>, stage
: u32, target
: Interned
<String
>) {
24 install_sh(builder
, "std", "rust-std", stage
, Some(target
));
27 pub fn install_cargo(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
28 install_sh(builder
, "cargo", "cargo", stage
, Some(host
));
31 pub fn install_rls(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
32 install_sh(builder
, "rls", "rls", stage
, Some(host
));
34 pub fn install_clippy(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
35 install_sh(builder
, "clippy", "clippy", stage
, Some(host
));
37 pub fn install_miri(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
38 install_sh(builder
, "miri", "miri", stage
, Some(host
));
41 pub fn install_rustfmt(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
42 install_sh(builder
, "rustfmt", "rustfmt", stage
, Some(host
));
45 pub fn install_analysis(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
46 install_sh(builder
, "analysis", "rust-analysis", stage
, Some(host
));
49 pub fn install_src(builder
: &Builder
<'_
>, stage
: u32) {
50 install_sh(builder
, "src", "rust-src", stage
, None
);
52 pub fn install_rustc(builder
: &Builder
<'_
>, stage
: u32, host
: Interned
<String
>) {
53 install_sh(builder
, "rustc", "rustc", stage
, Some(host
));
57 builder
: &Builder
<'_
>,
61 host
: Option
<Interned
<String
>>
63 builder
.info(&format
!("Install {} stage{} ({:?})", package
, stage
, host
));
65 let prefix_default
= PathBuf
::from("/usr/local");
66 let sysconfdir_default
= PathBuf
::from("/etc");
67 let datadir_default
= PathBuf
::from("share");
68 let docdir_default
= datadir_default
.join("doc/rust");
69 let bindir_default
= PathBuf
::from("bin");
70 let libdir_default
= PathBuf
::from("lib");
71 let mandir_default
= datadir_default
.join("man");
72 let prefix
= builder
.config
.prefix
.as_ref().map_or(prefix_default
, |p
| {
73 fs
::canonicalize(p
).unwrap_or_else(|_
| panic
!("could not canonicalize {}", p
.display()))
75 let sysconfdir
= builder
.config
.sysconfdir
.as_ref().unwrap_or(&sysconfdir_default
);
76 let datadir
= builder
.config
.datadir
.as_ref().unwrap_or(&datadir_default
);
77 let docdir
= builder
.config
.docdir
.as_ref().unwrap_or(&docdir_default
);
78 let bindir
= builder
.config
.bindir
.as_ref().unwrap_or(&bindir_default
);
79 let libdir
= builder
.config
.libdir
.as_ref().unwrap_or(&libdir_default
);
80 let mandir
= builder
.config
.mandir
.as_ref().unwrap_or(&mandir_default
);
82 let sysconfdir
= prefix
.join(sysconfdir
);
83 let datadir
= prefix
.join(datadir
);
84 let docdir
= prefix
.join(docdir
);
85 let bindir
= prefix
.join(bindir
);
86 let libdir
= prefix
.join(libdir
);
87 let mandir
= prefix
.join(mandir
);
89 let destdir
= env
::var_os("DESTDIR").map(PathBuf
::from
);
91 let prefix
= add_destdir(&prefix
, &destdir
);
92 let sysconfdir
= add_destdir(&sysconfdir
, &destdir
);
93 let datadir
= add_destdir(&datadir
, &destdir
);
94 let docdir
= add_destdir(&docdir
, &destdir
);
95 let bindir
= add_destdir(&bindir
, &destdir
);
96 let libdir
= add_destdir(&libdir
, &destdir
);
97 let mandir
= add_destdir(&mandir
, &destdir
);
99 let empty_dir
= builder
.out
.join("tmp/empty_dir");
101 t
!(fs
::create_dir_all(&empty_dir
));
102 let package_name
= if let Some(host
) = host
{
103 format
!("{}-{}", pkgname(builder
, name
), host
)
105 pkgname(builder
, name
)
108 let mut cmd
= Command
::new("sh");
109 cmd
.current_dir(&empty_dir
)
110 .arg(sanitize_sh(&tmpdir(builder
).join(&package_name
).join("install.sh")))
111 .arg(format
!("--prefix={}", sanitize_sh(&prefix
)))
112 .arg(format
!("--sysconfdir={}", sanitize_sh(&sysconfdir
)))
113 .arg(format
!("--datadir={}", sanitize_sh(&datadir
)))
114 .arg(format
!("--docdir={}", sanitize_sh(&docdir
)))
115 .arg(format
!("--bindir={}", sanitize_sh(&bindir
)))
116 .arg(format
!("--libdir={}", sanitize_sh(&libdir
)))
117 .arg(format
!("--mandir={}", sanitize_sh(&mandir
)))
118 .arg("--disable-ldconfig");
119 builder
.run(&mut cmd
);
120 t
!(fs
::remove_dir_all(&empty_dir
));
123 fn add_destdir(path
: &Path
, destdir
: &Option
<PathBuf
>) -> PathBuf
{
124 let mut ret
= match *destdir
{
125 Some(ref dest
) => dest
.clone(),
126 None
=> return path
.to_path_buf(),
128 for part
in path
.components() {
130 Component
::Normal(s
) => ret
.push(s
),
137 macro_rules
! install
{
138 (($sel
:ident
, $builder
:ident
, $_config
:ident
),
142 only_hosts
: $only_hosts
:expr
,
143 $run_item
:block $
(, $c
:ident
)*;)+) => {
145 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
148 pub target
: Interned
<String
>,
149 pub host
: Interned
<String
>,
154 fn should_build(config
: &Config
) -> bool
{
155 config
.extended
&& config
.tools
.as_ref()
156 .map_or(true, |t
| t
.contains($path
))
160 fn should_install(builder
: &Builder
<'_
>) -> bool
{
161 builder
.config
.tools
.as_ref().map_or(false, |t
| t
.contains($path
))
165 impl Step
for $name
{
167 const DEFAULT
: bool
= true;
168 const ONLY_HOSTS
: bool
= $only_hosts
;
169 $
(const $c
: bool
= true;)*
171 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
172 let $_config
= &run
.builder
.config
;
173 run
.path($path
).default_condition($default_cond
)
176 fn make_run(run
: RunConfig
<'_
>) {
177 run
.builder
.ensure($name
{
178 stage
: run
.builder
.top_stage
,
180 host
: run
.builder
.config
.build
,
184 fn run($sel
, $builder
: &Builder
<'_
>) {
191 install
!((self, builder
, _config
),
192 Docs
, "src/doc", _config
.docs
, only_hosts
: false, {
193 builder
.ensure(dist
::Docs { stage: self.stage, host: self.target }
);
194 install_docs(builder
, self.stage
, self.target
);
196 Std
, "src/libstd", true, only_hosts
: true, {
197 for target
in &builder
.targets
{
198 builder
.ensure(dist
::Std
{
199 compiler
: builder
.compiler(self.stage
, self.host
),
202 install_std(builder
, self.stage
, *target
);
205 Cargo
, "cargo", Self::should_build(_config
), only_hosts
: true, {
206 builder
.ensure(dist
::Cargo { stage: self.stage, target: self.target }
);
207 install_cargo(builder
, self.stage
, self.target
);
209 Rls
, "rls", Self::should_build(_config
), only_hosts
: true, {
210 if builder
.ensure(dist
::Rls { stage: self.stage, target: self.target }
).is_some() ||
211 Self::should_install(builder
) {
212 install_rls(builder
, self.stage
, self.target
);
214 builder
.info(&format
!("skipping Install RLS stage{} ({})", self.stage
, self.target
));
217 Clippy
, "clippy", Self::should_build(_config
), only_hosts
: true, {
218 if builder
.ensure(dist
::Clippy { stage: self.stage, target: self.target }
).is_some() ||
219 Self::should_install(builder
) {
220 install_clippy(builder
, self.stage
, self.target
);
222 builder
.info(&format
!("skipping Install clippy stage{} ({})", self.stage
, self.target
));
225 Miri
, "miri", Self::should_build(_config
), only_hosts
: true, {
226 if builder
.ensure(dist
::Miri { stage: self.stage, target: self.target }
).is_some() ||
227 Self::should_install(builder
) {
228 install_miri(builder
, self.stage
, self.target
);
230 builder
.info(&format
!("skipping Install miri stage{} ({})", self.stage
, self.target
));
233 Rustfmt
, "rustfmt", Self::should_build(_config
), only_hosts
: true, {
234 if builder
.ensure(dist
::Rustfmt { stage: self.stage, target: self.target }
).is_some() ||
235 Self::should_install(builder
) {
236 install_rustfmt(builder
, self.stage
, self.target
);
239 &format
!("skipping Install Rustfmt stage{} ({})", self.stage
, self.target
));
242 Analysis
, "analysis", Self::should_build(_config
), only_hosts
: false, {
243 builder
.ensure(dist
::Analysis
{
244 compiler
: builder
.compiler(self.stage
, self.host
),
247 install_analysis(builder
, self.stage
, self.target
);
249 Rustc
, "src/librustc", true, only_hosts
: true, {
250 builder
.ensure(dist
::Rustc
{
251 compiler
: builder
.compiler(self.stage
, self.target
),
253 install_rustc(builder
, self.stage
, self.target
);
257 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
264 const DEFAULT
: bool
= true;
265 const ONLY_HOSTS
: bool
= true;
267 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
268 let config
= &run
.builder
.config
;
269 let cond
= config
.extended
&&
270 config
.tools
.as_ref().map_or(true, |t
| t
.contains("src"));
271 run
.path("src").default_condition(cond
)
274 fn make_run(run
: RunConfig
<'_
>) {
275 run
.builder
.ensure(Src
{
276 stage
: run
.builder
.top_stage
,
280 fn run(self, builder
: &Builder
<'_
>) {
281 builder
.ensure(dist
::Src
);
282 install_src(builder
, self.stage
);