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

Let CompileOptions create a BuildConfig directly #5358

Merged
merged 13 commits into from
May 5, 2018
Merged
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