Skip to content

Commit

Permalink
Auto merge of #5358 - djc:options-build-config, r=matklad
Browse files Browse the repository at this point in the history
Let CompileOptions create a BuildConfig directly

This puts input validation in a more central place and prevents copying/moving stuff around as separate values.
  • Loading branch information
bors committed May 5, 2018
2 parents 07c0784 + 072254c commit d19e295
Show file tree
Hide file tree
Showing 29 changed files with 472 additions and 463 deletions.
15 changes: 8 additions & 7 deletions src/bin/cargo/command_prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ use std::fs;
use clap::{self, SubCommand};
use cargo::CargoResult;
use cargo::core::Workspace;
use cargo::ops::{CompileFilter, CompileMode, CompileOptions, MessageFormat, NewOptions, Packages,
VersionControl};
use cargo::core::compiler::{BuildConfig, MessageFormat};
use cargo::ops::{CompileFilter, CompileOptions, NewOptions, Packages, VersionControl};
use cargo::util::paths;
use cargo::util::important_paths::find_root_manifest_for_wd;

pub use clap::{AppSettings, Arg, ArgMatches};
pub use cargo::{CliError, CliResult, Config};
pub use cargo::core::compiler::CompileMode;

pub type App = clap::App<'static, 'static>;

Expand Down Expand Up @@ -271,16 +272,17 @@ pub trait ArgMatchesExt {
}
};

let mut build_config = BuildConfig::new(config, self.jobs()?, &self.target(), mode)?;
build_config.message_format = message_format;
build_config.release = self._is_present("release");

let opts = CompileOptions {
config,
jobs: self.jobs()?,
target: self.target(),
build_config,
features: self._values_of("features"),
all_features: self._is_present("all-features"),
no_default_features: self._is_present("no-default-features"),
spec,
mode,
release: self._is_present("release"),
filter: CompileFilter::new(
self._is_present("lib"),
self._values_of("bin"),
Expand All @@ -293,7 +295,6 @@ pub trait ArgMatchesExt {
self._is_present("benches"),
self._is_present("all-targets"),
),
message_format,
target_rustdoc_args: None,
target_rustc_args: None,
export_dir: None,
Expand Down
4 changes: 2 additions & 2 deletions src/bin/cargo/commands/bench.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use command_prelude::*;

use cargo::ops::{self, CompileMode, TestOptions};
use cargo::ops::{self, TestOptions};

pub fn cli() -> App {
subcommand("bench")
Expand Down Expand Up @@ -73,7 +73,7 @@ Compilation can be customized with the `bench` profile in the manifest.
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let ws = args.workspace(config)?;
let mut compile_opts = args.compile_options(config, CompileMode::Bench)?;
compile_opts.release = true;
compile_opts.build_config.release = true;

let ops = TestOptions {
no_run: args.is_present("no-run"),
Expand Down
2 changes: 1 addition & 1 deletion src/bin/cargo/commands/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use command_prelude::*;

use cargo::ops::{self, CompileMode};
use cargo::ops;

pub fn cli() -> App {
subcommand("build")
Expand Down
2 changes: 1 addition & 1 deletion src/bin/cargo/commands/check.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use command_prelude::*;

use cargo::ops::{self, CompileMode};
use cargo::ops;

pub fn cli() -> App {
subcommand("check")
Expand Down
2 changes: 1 addition & 1 deletion src/bin/cargo/commands/doc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use command_prelude::*;

use cargo::ops::{self, CompileMode, DocOptions};
use cargo::ops::{self, DocOptions};

pub fn cli() -> App {
subcommand("doc")
Expand Down
4 changes: 2 additions & 2 deletions src/bin/cargo/commands/install.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use command_prelude::*;

use cargo::core::{GitReference, SourceId};
use cargo::ops::{self, CompileMode};
use cargo::ops;
use cargo::util::ToUrl;

pub fn cli() -> App {
Expand Down Expand Up @@ -73,7 +73,7 @@ continuous integration systems.",

pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let mut compile_opts = args.compile_options(config, CompileMode::Build)?;
compile_opts.release = !args.is_present("debug");
compile_opts.build_config.release = !args.is_present("debug");

let krates = args.values_of("crate")
.unwrap_or_default()
Expand Down
2 changes: 1 addition & 1 deletion src/bin/cargo/commands/run.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use command_prelude::*;

use cargo::core::Verbosity;
use cargo::ops::{self, CompileFilter, CompileMode};
use cargo::ops::{self, CompileFilter};

pub fn cli() -> App {
subcommand("run")
Expand Down
2 changes: 1 addition & 1 deletion src/bin/cargo/commands/rustc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use command_prelude::*;

use cargo::ops::{self, CompileMode};
use cargo::ops;

pub fn cli() -> App {
subcommand("rustc")
Expand Down
2 changes: 1 addition & 1 deletion src/bin/cargo/commands/rustdoc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use command_prelude::*;

use cargo::ops::{self, CompileMode, DocOptions};
use cargo::ops::{self, DocOptions};

pub fn cli() -> App {
subcommand("rustdoc")
Expand Down
4 changes: 2 additions & 2 deletions src/bin/cargo/commands/test.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use command_prelude::*;

use cargo::ops::{self, CompileMode};
use cargo::ops;

pub fn cli() -> App {
subcommand("test")
Expand Down Expand Up @@ -94,7 +94,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let mut compile_opts = args.compile_options(config, CompileMode::Test)?;
let doc = args.is_present("doc");
if doc {
compile_opts.mode = ops::CompileMode::Doctest;
compile_opts.build_config.mode = CompileMode::Doctest;
compile_opts.filter = ops::CompileFilter::new(
true,
Vec::new(),
Expand Down
190 changes: 190 additions & 0 deletions src/cargo/core/compiler/build_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
use std::path::Path;
use util::{CargoResult, CargoResultExt, Config};

/// Configuration information for a rustc build.
#[derive(Debug)]
pub struct BuildConfig {
/// The target arch triple, defaults to host arch
pub requested_target: Option<String>,
/// How many rustc jobs to run in parallel
pub jobs: u32,
/// Whether we are building for release
pub release: bool,
/// In what mode we are compiling
pub mode: CompileMode,
/// Whether to print std output in json format (for machine reading)
pub message_format: MessageFormat,
}

impl BuildConfig {
/// Parse all config files to learn about build configuration. Currently
/// configured options are:
///
/// * build.jobs
/// * build.target
/// * target.$target.ar
/// * target.$target.linker
/// * target.$target.libfoo.metadata
pub fn new(
config: &Config,
jobs: Option<u32>,
requested_target: &Option<String>,
mode: CompileMode,
) -> CargoResult<BuildConfig> {
let requested_target = match requested_target {
&Some(ref target) if target.ends_with(".json") => {
let path = Path::new(target)
.canonicalize()
.chain_err(|| format_err!("Target path {:?} is not a valid file", target))?;
Some(path.into_os_string()
.into_string()
.map_err(|_| format_err!("Target path is not valid unicode"))?)
}
other => other.clone(),
};
if let Some(ref s) = requested_target {
if s.trim().is_empty() {
bail!("target was empty")
}
}
let cfg_target = config.get_string("build.target")?.map(|s| s.val);
let target = requested_target.clone().or(cfg_target);

if jobs == Some(0) {
bail!("jobs must be at least 1")
}
if jobs.is_some() && config.jobserver_from_env().is_some() {
config.shell().warn(
"a `-j` argument was passed to Cargo but Cargo is \
also configured with an external jobserver in \
its environment, ignoring the `-j` parameter",
)?;
}
let cfg_jobs = match config.get_i64("build.jobs")? {
Some(v) => {
if v.val <= 0 {
bail!(
"build.jobs must be positive, but found {} in {}",
v.val,
v.definition
)
} else if v.val >= i64::from(u32::max_value()) {
bail!(
"build.jobs is too large: found {} in {}",
v.val,
v.definition
)
} else {
Some(v.val as u32)
}
}
None => None,
};
let jobs = jobs.or(cfg_jobs).unwrap_or(::num_cpus::get() as u32);
Ok(BuildConfig {
requested_target: target,
jobs,
release: false,
mode,
message_format: MessageFormat::Human,
})
}

pub fn json_messages(&self) -> bool {
self.message_format == MessageFormat::Json
}

pub fn test(&self) -> bool {
self.mode == CompileMode::Test || self.mode == CompileMode::Bench
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MessageFormat {
Human,
Json,
}

/// The general "mode" of what to do.
/// This is used for two purposes. The commands themselves pass this in to
/// `compile_ws` to tell it the general execution strategy. This influences
/// the default targets selected. The other use is in the `Unit` struct
/// to indicate what is being done with a specific target.
#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash)]
pub enum CompileMode {
/// A target being built for a test.
Test,
/// Building a target with `rustc` (lib or bin).
Build,
/// Building a target with `rustc` to emit `rmeta` metadata only. If
/// `test` is true, then it is also compiled with `--test` to check it like
/// a test.
Check { test: bool },
/// Used to indicate benchmarks should be built. This is not used in
/// `Target` because it is essentially the same as `Test` (indicating
/// `--test` should be passed to rustc) and by using `Test` instead it
/// allows some de-duping of Units to occur.
Bench,
/// A target that will be documented with `rustdoc`.
/// If `deps` is true, then it will also document all dependencies.
Doc { deps: bool },
/// A target that will be tested with `rustdoc`.
Doctest,
/// A marker for Units that represent the execution of a `build.rs`
/// script.
RunCustomBuild,
}

impl CompileMode {
/// Returns true if the unit is being checked.
pub fn is_check(&self) -> bool {
match *self {
CompileMode::Check { .. } => true,
_ => false,
}
}

/// Returns true if this is a doc or doctest. Be careful using this.
/// Although both run rustdoc, the dependencies for those two modes are
/// very different.
pub fn is_doc(&self) -> bool {
match *self {
CompileMode::Doc { .. } | CompileMode::Doctest => true,
_ => false,
}
}

/// Returns true if this is any type of test (test, benchmark, doctest, or
/// check-test).
pub fn is_any_test(&self) -> bool {
match *self {
CompileMode::Test
| CompileMode::Bench
| CompileMode::Check { test: true }
| CompileMode::Doctest => true,
_ => false,
}
}

/// Returns true if this is the *execution* of a `build.rs` script.
pub fn is_run_custom_build(&self) -> bool {
*self == CompileMode::RunCustomBuild
}

/// List of all modes (currently used by `cargo clean -p` for computing
/// all possible outputs).
pub fn all_modes() -> &'static [CompileMode] {
static ALL: [CompileMode; 9] = [
CompileMode::Test,
CompileMode::Build,
CompileMode::Check { test: true },
CompileMode::Check { test: false },
CompileMode::Bench,
CompileMode::Doc { deps: true },
CompileMode::Doc { deps: false },
CompileMode::Doctest,
CompileMode::RunCustomBuild,
];
&ALL
}
}
Loading

0 comments on commit d19e295

Please sign in to comment.