Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add xargo-check command #267

Merged
merged 17 commits into from
Dec 31, 2019
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ license = "MIT OR Apache-2.0"
name = "xargo"
repository = "https://github.com/japaric/xargo"
version = "0.3.18"
default-run = "xargo"

[dependencies]
error-chain = "0.7.2"
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,18 @@ git = "https://github.com/japaric/steed"
stage = 2
```

## Check-only sysroot build

Xargo supports performing a 'check build' of the syroot
via the `xargo-check` command. This command is invoked exactly
like `xargo`, but will invoke `cargo check` instead of `cargo build`
when building the sysroot.

This is only useful for very specialized applicationsm like Miri.
The resulting libstd will *not* be useable in a normal build, since codegen
will not be performed. You should almost always run `xargo check` (note the space),
which will perform a normal sysroot build, followed by a 'check' build of *your application*

## Caveats / gotchas

- Xargo won't build a sysroot when used with stable or beta Rust. This is
Expand Down
3 changes: 3 additions & 0 deletions src/bin/xargo-check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
xargo::main_inner(xargo::CargoMode::Check);
}
3 changes: 3 additions & 0 deletions src/bin/xargo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
xargo::main_inner(xargo::CargoMode::Build);
}
10 changes: 8 additions & 2 deletions src/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use cli::Args;
use errors::*;
use extensions::CommandExt;
use util;
use sysroot::CargoMode;
use xargo::Home;

pub struct Rustflags {
Expand Down Expand Up @@ -247,10 +248,15 @@ impl Root {
}
}

pub fn root() -> Result<Option<Root>> {
pub fn root(mode: CargoMode) -> Result<Option<Root>> {
// Don't require a 'Cargo.toml' to exist when 'xargo-check' is used
let name = match mode {
CargoMode::Build => "Cargo.toml",
CargoMode::Check => "Xargo.toml"
};
let cd = env::current_dir().chain_err(|| "couldn't get the current directory")?;

Ok(util::search(&cd, "Cargo.toml").map(|p| Root { path: p.to_owned() }))
Ok(util::search(&cd, name).map(|p| Root { path: p.to_owned() }))
}

#[derive(Clone, Copy, PartialEq)]
Expand Down
13 changes: 8 additions & 5 deletions src/main.rs → src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ mod sysroot;
mod util;
mod xargo;

pub use sysroot::CargoMode;

// We use a different sysroot for Native compilation to avoid file locking
//
// Cross compilation requires `lib/rustlib/$HOST` to match `rustc`'s sysroot,
Expand Down Expand Up @@ -72,12 +74,12 @@ impl CompilationMode {
}
}

pub fn main() {
pub fn main_inner(cargo_mode: CargoMode) {
fn show_backtrace() -> bool {
env::var("RUST_BACKTRACE").as_ref().map(|s| &s[..]) == Ok("1")
}

match run() {
match run(cargo_mode) {
Err(e) => {
let stderr = io::stderr();
let mut stderr = stderr.lock();
Expand All @@ -104,7 +106,7 @@ pub fn main() {
}
}

fn run() -> Result<ExitStatus> {
fn run(cargo_mode: CargoMode) -> Result<ExitStatus> {
let args = cli::args();
let verbose = args.verbose();

Expand All @@ -127,7 +129,7 @@ fn run() -> Result<ExitStatus> {
let cd = CurrentDirectory::get()?;

let config = cargo::config()?;
if let Some(root) = cargo::root()? {
if let Some(root) = cargo::root(cargo_mode)? {
// We can't build sysroot with stable or beta due to unstable features
let sysroot = rustc::sysroot(verbose)?;
let src = match meta.channel {
Expand Down Expand Up @@ -187,7 +189,8 @@ fn run() -> Result<ExitStatus> {
&src,
&sysroot,
verbose,
args.message_format()
args.message_format(),
cargo_mode,
)?;
return xargo::run(
&args,
Expand Down
48 changes: 38 additions & 10 deletions src/sysroot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ fn profile() -> &'static str {
fn build(
cmode: &CompilationMode,
blueprint: Blueprint,
ctoml: &cargo::Toml,
ctoml: &Option<cargo::Toml>,
home: &Home,
rustflags: &Rustflags,
src: &Src,
sysroot: &Sysroot,
hash: u64,
verbose: bool,
message_format: Option<&str>
message_format: Option<&str>,
cargo_mode: CargoMode,
) -> Result<()> {
const TOML: &'static str = r#"
[package]
Expand Down Expand Up @@ -96,8 +97,10 @@ version = "0.0.0"
stoml.push_str(&Value::Table(map).to_string());
}

if let Some(profile) = ctoml.profile() {
stoml.push_str(&profile.to_string())
if let Some(ctoml) = ctoml {
if let Some(profile) = ctoml.profile() {
stoml.push_str(&profile.to_string())
}
}

// rust-src comes with a lockfile for libstd. Use it.
Expand Down Expand Up @@ -165,7 +168,10 @@ version = "0.0.0"
}
}

cmd.arg("build");
match cargo_mode {
CargoMode::Build => cmd.arg("build"),
CargoMode::Check => cmd.arg("check")
};

match () {
#[cfg(feature = "dev")]
Expand Down Expand Up @@ -234,7 +240,7 @@ fn hash(
cmode: &CompilationMode,
blueprint: &Blueprint,
rustflags: &Rustflags,
ctoml: &cargo::Toml,
ctoml: &Option<cargo::Toml>,
meta: &VersionMeta,
) -> Result<u64> {
let mut hasher = DefaultHasher::new();
Expand All @@ -245,8 +251,10 @@ fn hash(

cmode.hash(&mut hasher)?;

if let Some(profile) = ctoml.profile() {
profile.hash(&mut hasher);
if let Some(ctoml) = ctoml {
if let Some(profile) = ctoml.profile() {
profile.hash(&mut hasher);
}
}

if let Some(ref hash) = meta.commit_hash {
Expand All @@ -265,9 +273,20 @@ pub fn update(
src: &Src,
sysroot: &Sysroot,
verbose: bool,
message_format: Option<&str>
message_format: Option<&str>,
cargo_mode: CargoMode,
) -> Result<()> {
let ctoml = cargo::toml(root)?;
let ctoml = match cargo_mode {
CargoMode::Build => Some(cargo::toml(root)?),
CargoMode::Check => {
if root.path().join("Cargo.toml").exists() {
Some(cargo::toml(root)?)
} else {
None
}
}
};

let (xtoml_parent, xtoml) = xargo::toml(root)?;

// As paths in the 'Xargo.toml' can be relative to the directory containing
Expand All @@ -292,6 +311,7 @@ pub fn update(
hash,
verbose,
message_format,
cargo_mode,
)?;
}

Expand Down Expand Up @@ -344,6 +364,14 @@ pub struct Stage {
patch: Table,
}

/// Which mode to invoke `cargo` in when building the sysroot
/// Can be either `cargo build` or `cargo check`
#[derive(Copy, Clone, Debug)]
pub enum CargoMode {
Aaron1011 marked this conversation as resolved.
Show resolved Hide resolved
Build,
Check,
}

/// A sysroot that will be built in "stages"
#[derive(Debug)]
pub struct Blueprint {
Expand Down
62 changes: 62 additions & 0 deletions tests/smoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ fn xargo() -> Result<Command> {
Ok(Command::new(p))
}

fn xargo_check() -> Result<Command> {
let mut p = env::current_exe().chain_err(|| "couldn't get path to current executable")?;
p.pop();
p.pop();
p.push("xargo-check");
Ok(Command::new(p))
}

trait CommandExt {
fn run(&mut self) -> Result<()>;
fn run_and_get_stderr(&mut self) -> Result<String>;
Expand Down Expand Up @@ -254,6 +262,7 @@ impl Project {
Ok(())
}


/// Adds a `Xargo.toml` to the project
fn xargo_toml(&self, toml: &str) -> Result<()> {
write(&self.td.path().join("Xargo.toml"), false, toml)
Expand Down Expand Up @@ -336,6 +345,18 @@ impl HProject {
fn xargo_toml(&self, toml: &str) -> Result<()> {
write(&self.td.path().join("Xargo.toml"), false, toml)
}

/// Runs `xargo-check` with the specified subcommand
fn xargo_check_subcommand(&self, subcommand: Option<&str>) -> Result<String> {
let mut cmd = xargo_check()?;
if let Some(subcommand) = subcommand {
cmd.args(&[subcommand]);
}
cmd
.current_dir(self.td.path())
.run_and_get_stderr()
}

}

impl Drop for HProject {
Expand Down Expand Up @@ -887,3 +908,44 @@ tag = "1.0.25"
run!()
}
}

#[cfg(feature = "dev")]
#[test]
fn cargo_check_plain() {
fn run() -> Result<()> {
let project = HProject::new(false)?;
project.xargo_check_subcommand(None)?;
Aaron1011 marked this conversation as resolved.
Show resolved Hide resolved

Ok(())
}
run!()
}

#[cfg(feature = "dev")]
#[test]
fn cargo_check_check() {
fn run() -> Result<()> {
let project = HProject::new(false)?;
project.xargo_check_subcommand(Some("check"))?;

Ok(())
}
run!()
}

#[cfg(feature = "dev")]
#[test]
fn cargo_check_check_no_ctoml() {
fn run() -> Result<()> {
let project = HProject::new(false)?;
project.xargo_toml("")?;
Aaron1011 marked this conversation as resolved.
Show resolved Hide resolved
std::fs::remove_file(project.td.path().join("Cargo.toml"))
.chain_err(|| format!("Could not remove Cargo.toml"))?;

let stderr = project.xargo_check_subcommand(None)?;
assert!(stderr.contains("Checking core"));

Ok(())
}
run!()
}