1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use std::io::{self, Write};
use std::mem;
use std::path::Path;
use std::path::{Display, PathBuf};
use std::process::{Command, ExitStatus};
use std::env;

use rustc_version::VersionMeta;

use cargo::Rustflags;
use cli::Args;
use config::Config;
use errors::*;
use extensions::CommandExt;
use flock::{FileLock, Filesystem};
use CompilationMode;

pub fn run(
    args: &Args,
    cmode: &CompilationMode,
    rustflags: Rustflags,
    home: &Home,
    meta: &VersionMeta,
    command_name: &str,
    verbose: bool,
) -> Result<ExitStatus> {
    let cargo = std::env::var("CARGO").unwrap_or("cargo".to_string());
    let mut cmd = Command::new(cargo);
    cmd.arg(command_name);
    cmd.args(args.all());

    let flags = rustflags.for_xargo(home)?;
    if verbose {
        writeln!(io::stderr(), "+ RUSTFLAGS={:?}", flags).ok();
        writeln!(io::stderr(), "+ RUSTDOCFLAGS={:?}", flags).ok();
    }
    cmd.env("RUSTFLAGS", &flags);
    cmd.env("RUSTDOCFLAGS", &flags);

    let locks = (home.lock_ro(&meta.host), home.lock_ro(cmode.triple()));

    let status = cmd.run_and_get_status(verbose)?;

    mem::drop(locks);

    Ok(status)
}

pub struct Home {
    path: Filesystem,
}

impl Home {
    pub fn display(&self) -> Display {
        self.path.display()
    }

    fn path(&self, triple: &str) -> Filesystem {
        self.path.join("lib").join("rustlib").join(triple)
    }

    pub fn lock_ro(&self, triple: &str) -> Result<FileLock> {
        let fs = self.path(triple);

        fs.open_ro(".sentinel", &format!("{}'s sysroot", triple))
            .chain_err(|| format!("couldn't lock {}'s sysroot as read-only", triple))
    }

    pub fn lock_rw(&self, triple: &str) -> Result<FileLock> {
        let fs = self.path(triple);

        fs.open_rw(".sentinel", &format!("{}'s sysroot", triple))
            .chain_err(|| format!("couldn't lock {}'s sysroot in {} as read-write", triple, fs.display()))
    }
}

pub fn home(root: &Path, config: &Config) -> Result<Home> {
    let path = if let Ok(path) = env::var("XBUILD_SYSROOT_PATH") {
        PathBuf::from(path)
    } else {
        let mut path = PathBuf::from(root);
        path.push(&config.sysroot_path);
        path
    };

    Ok(Home {
        path: Filesystem::new(path),
    })
}