Skip to content

Commit

Permalink
Merge #267
Browse files Browse the repository at this point in the history
267: Add `xargo-check` command r=RalfJung a=Aaron1011

This allows configuring Xargo to run `cargo check`
instead of `cargo build`

Needed to support rust-lang/miri#1048

Co-authored-by: Aaron Hill <[email protected]>
  • Loading branch information
bors[bot] and Aaron1011 authored Dec 31, 2019
2 parents d1d7606 + 3d63a18 commit 77e33ae
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 32 deletions.
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
8 changes: 7 additions & 1 deletion ci/script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@ set -euxo pipefail
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }

main() {
# We test against Cargo versions that don't support 'default-run'
# As a workaround, we remove 'default-run' from the Cargo.toml
# on CI
# Unfortunately, we can't use 'sed -i', as this doesn't work on OS X
sed 's/default-run = "xargo"//g' Cargo.toml > Cargo.toml.new
mv Cargo.toml.new Cargo.toml
cross build --target $TARGET --locked
cross run --target $TARGET -- -V
cross run --bin xargo --target $TARGET -- -V

if beginswith nightly $TRAVIS_RUST_VERSION; then
cargo test --features dev --target $TARGET
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::XargoMode::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::XargoMode::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::XargoMode;
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: XargoMode) -> Result<Option<Root>> {
// Don't require a 'Cargo.toml' to exist when 'xargo-check' is used
let name = match mode {
XargoMode::Build => "Cargo.toml",
XargoMode::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
47 changes: 28 additions & 19 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::XargoMode;

// 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(xargo_mode: XargoMode) {
fn show_backtrace() -> bool {
env::var("RUST_BACKTRACE").as_ref().map(|s| &s[..]) == Ok("1")
}

match run() {
match run(xargo_mode) {
Err(e) => {
let stderr = io::stderr();
let mut stderr = stderr.lock();
Expand All @@ -98,21 +100,22 @@ pub fn main() {

process::exit(1)
}
Ok(status) => if !status.success() {
Ok(Some(status)) => if !status.success() {
process::exit(status.code().unwrap_or(1))
},
Ok(None) => {}
}
}

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

let meta = rustc::version();

if let Some(sc) = args.subcommand() {
if !sc.needs_sysroot() {
return cargo::run(&args, verbose);
return cargo::run(&args, verbose).map(Some);
}
} else if args.version() {
writeln!(
Expand All @@ -121,13 +124,13 @@ fn run() -> Result<ExitStatus> {
include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))
).ok();

return cargo::run(&args, verbose);
return cargo::run(&args, verbose).map(Some);
}

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 All @@ -147,7 +150,7 @@ fn run() -> Result<ExitStatus> {
Switch to nightly.",
meta.channel
).ok();
return cargo::run(&args, verbose);
return cargo::run(&args, verbose).map(Some);
}
};

Expand Down Expand Up @@ -187,21 +190,27 @@ fn run() -> Result<ExitStatus> {
&src,
&sysroot,
verbose,
args.message_format()
args.message_format(),
cargo_mode,
)?;
return xargo::run(
&args,
&cmode,
rustflags,
&home,
&meta,
config.as_ref(),
verbose,
);

if args.subcommand().is_some() || cargo_mode == XargoMode::Build {
return xargo::run(
&args,
&cmode,
rustflags,
&home,
&meta,
config.as_ref(),
verbose,
).map(Some);
} else {
return Ok(None)
}
}
}

cargo::run(&args, verbose)
cargo::run(&args, verbose).map(Some)
}

pub struct CurrentDirectory {
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: XargoMode,
) -> 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 {
XargoMode::Build => cmd.arg("build"),
XargoMode::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: XargoMode,
) -> Result<()> {
let ctoml = cargo::toml(root)?;
let ctoml = match cargo_mode {
XargoMode::Build => Some(cargo::toml(root)?),
XargoMode::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, Eq, PartialEq)]
pub enum XargoMode {
Build,
Check,
}

/// A sysroot that will be built in "stages"
#[derive(Debug)]
pub struct Blueprint {
Expand Down
51 changes: 51 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,33 @@ tag = "1.0.25"
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)?;
// Make sure that 'Xargo.toml` exists
project.xargo_toml("")?;
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!()
}

0 comments on commit 77e33ae

Please sign in to comment.