1use std::env;
2use std::mem;
3use std::path::Path;
4use std::path::{Display, PathBuf};
5use std::process::{Command, ExitStatus};
6
7use anyhow::{Context, Result};
8use rustc_version::VersionMeta;
9
10use crate::cargo::Rustflags;
11use crate::cli::Args;
12use crate::config::Config;
13use crate::extensions::CommandExt;
14use crate::flock::{FileLock, Filesystem};
15use crate::CompilationMode;
16
17pub fn run(
18 args: &Args,
19 cmode: &CompilationMode,
20 rustflags: Rustflags,
21 home: &Home,
22 meta: &VersionMeta,
23 command_name: &str,
24 verbose: bool,
25) -> Result<ExitStatus> {
26 let cargo = std::env::var("CARGO").unwrap_or("cargo".to_string());
27 let mut cmd = Command::new(cargo);
28 cmd.arg(command_name);
29 cmd.args(args.all());
30
31 let flags = rustflags.for_xargo(home)?;
32 if verbose {
33 eprintln!("+ RUSTFLAGS={:?}", flags);
34 eprintln!("+ RUSTDOCFLAGS={:?}", flags);
35 }
36 cmd.env("RUSTFLAGS", &flags);
37 cmd.env("RUSTDOCFLAGS", &flags);
38
39 let locks = (home.lock_ro(&meta.host), home.lock_ro(cmode.triple()));
40
41 let status = cmd.run_and_get_status(verbose)?;
42
43 mem::drop(locks);
44
45 Ok(status)
46}
47
48pub struct Home {
49 path: Filesystem,
50}
51
52impl Home {
53 pub fn display(&self) -> Display {
54 self.path.display()
55 }
56
57 fn path(&self, triple: &str) -> Filesystem {
58 self.path.join("lib").join("rustlib").join(triple)
59 }
60
61 pub fn lock_ro(&self, triple: &str) -> Result<FileLock> {
62 let fs = self.path(triple);
63
64 fs.open_ro(".sentinel", &format!("{}'s sysroot", triple))
65 .with_context(|| format!("couldn't lock {}'s sysroot as read-only", triple))
66 }
67
68 pub fn lock_rw(&self, triple: &str) -> Result<FileLock> {
69 let fs = self.path(triple);
70
71 fs.open_rw(".sentinel", &format!("{}'s sysroot", triple))
72 .with_context(|| {
73 format!(
74 "couldn't lock {}'s sysroot in {} as read-write",
75 triple,
76 fs.display()
77 )
78 })
79 }
80}
81
82pub fn home(root: &Path, config: &Config, quiet: bool) -> Result<Home> {
83 let path = if let Ok(path) = env::var("XBUILD_SYSROOT_PATH") {
84 PathBuf::from(path)
85 } else {
86 let mut path = PathBuf::from(root);
87 path.push(&config.sysroot_path);
88 path
89 };
90
91 Ok(Home {
92 path: Filesystem::new(path, quiet),
93 })
94}