Skip to content

Commit

Permalink
Add --build-plan for 'cargo build'
Browse files Browse the repository at this point in the history
With 'cargo build --build-plan', cargo does not actually run any
commands, but instead prints out what it would have done in the form of
a JSON data structure.

Fixes rust-lang#3815
  • Loading branch information
mshal committed Mar 23, 2018
1 parent 8c93e08 commit 333fe61
Show file tree
Hide file tree
Showing 15 changed files with 250 additions and 59 deletions.
3 changes: 3 additions & 0 deletions src/bin/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub struct Options {
flag_quiet: Option<bool>,
flag_color: Option<String>,
flag_message_format: MessageFormat,
flag_build_plan: bool,
flag_lib: bool,
flag_bin: Vec<String>,
flag_bins: bool,
Expand Down Expand Up @@ -72,6 +73,7 @@ Options:
--color WHEN Coloring: auto, always, never
--message-format FMT Error format: human, json [default: human]
--no-fail-fast Run all benchmarks regardless of failure
--build-plan Generate a build plan
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-Z FLAG ... Unstable (nightly-only) flags to Cargo
Expand Down Expand Up @@ -134,6 +136,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
&options.flag_bench, options.flag_benches,
options.flag_all_targets),
message_format: options.flag_message_format,
build_plan: options.flag_build_plan,
target_rustdoc_args: None,
target_rustc_args: None,
},
Expand Down
3 changes: 3 additions & 0 deletions src/bin/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub struct Options {
flag_quiet: Option<bool>,
flag_color: Option<String>,
flag_message_format: MessageFormat,
flag_build_plan: bool,
flag_release: bool,
flag_lib: bool,
flag_bin: Vec<String>,
Expand Down Expand Up @@ -69,6 +70,7 @@ Options:
-q, --quiet No output printed to stdout
--color WHEN Coloring: auto, always, never
--message-format FMT Error format: human, json [default: human]
--build-plan Generate a build plan
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-Z FLAG ... Unstable (nightly-only) flags to Cargo
Expand Down Expand Up @@ -121,6 +123,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
&options.flag_bench, options.flag_benches,
options.flag_all_targets),
message_format: options.flag_message_format,
build_plan: options.flag_build_plan,
target_rustdoc_args: None,
target_rustc_args: None,
};
Expand Down
3 changes: 3 additions & 0 deletions src/bin/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Options:
-q, --quiet No output printed to stdout
--color WHEN Coloring: auto, always, never
--message-format FMT Error format: human, json [default: human]
--build-plan Generate a build plan
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-Z FLAG ... Unstable (nightly-only) flags to Cargo
Expand Down Expand Up @@ -72,6 +73,7 @@ pub struct Options {
flag_quiet: Option<bool>,
flag_color: Option<String>,
flag_message_format: MessageFormat,
flag_build_plan: bool,
flag_release: bool,
flag_lib: bool,
flag_bin: Vec<String>,
Expand Down Expand Up @@ -137,6 +139,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
&options.flag_bench, options.flag_benches,
options.flag_all_targets),
message_format: options.flag_message_format,
build_plan: options.flag_build_plan,
target_rustdoc_args: None,
target_rustc_args: None,
};
Expand Down
3 changes: 3 additions & 0 deletions src/bin/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub struct Options {
flag_quiet: Option<bool>,
flag_color: Option<String>,
flag_message_format: MessageFormat,
flag_build_plan: bool,
flag_package: Vec<String>,
flag_lib: bool,
flag_bin: Vec<String>,
Expand Down Expand Up @@ -57,6 +58,7 @@ Options:
-q, --quiet No output printed to stdout
--color WHEN Coloring: auto, always, never
--message-format FMT Error format: human, json [default: human]
--build-plan Generate a build plan
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-Z FLAG ... Unstable (nightly-only) flags to Cargo
Expand Down Expand Up @@ -112,6 +114,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
&empty, false,
false),
message_format: options.flag_message_format,
build_plan: options.flag_build_plan,
release: options.flag_release,
mode: ops::CompileMode::Doc {
deps: !options.flag_no_deps,
Expand Down
1 change: 1 addition & 0 deletions src/bin/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
&[], false,
false),
message_format: ops::MessageFormat::Human,
build_plan: false,
target_rustc_args: None,
target_rustdoc_args: None,
};
Expand Down
3 changes: 3 additions & 0 deletions src/bin/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub struct Options {
flag_quiet: Option<bool>,
flag_color: Option<String>,
flag_message_format: MessageFormat,
flag_build_plan: bool,
flag_release: bool,
flag_frozen: bool,
flag_locked: bool,
Expand Down Expand Up @@ -50,6 +51,7 @@ Options:
-q, --quiet No output printed to stdout
--color WHEN Coloring: auto, always, never
--message-format FMT Error format: human, json [default: human]
--build-plan Generate a build plan
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-Z FLAG ... Unstable (nightly-only) flags to Cargo
Expand Down Expand Up @@ -106,6 +108,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
false)
},
message_format: options.flag_message_format,
build_plan: options.flag_build_plan,
target_rustdoc_args: None,
target_rustc_args: None,
};
Expand Down
3 changes: 3 additions & 0 deletions src/bin/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub struct Options {
flag_quiet: Option<bool>,
flag_color: Option<String>,
flag_message_format: MessageFormat,
flag_build_plan: bool,
flag_release: bool,
flag_lib: bool,
flag_bin: Vec<String>,
Expand Down Expand Up @@ -68,6 +69,7 @@ Options:
-q, --quiet No output printed to stdout
--color WHEN Coloring: auto, always, never
--message-format FMT Error format: human, json [default: human]
--build-plan Generate a build plan
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-Z FLAG ... Unstable (nightly-only) flags to Cargo
Expand Down Expand Up @@ -129,6 +131,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
&options.flag_bench, options.flag_benches,
options.flag_all_targets),
message_format: options.flag_message_format,
build_plan: options.flag_build_plan,
target_rustdoc_args: None,
target_rustc_args: options.arg_opts.as_ref().map(|a| &a[..]),
};
Expand Down
3 changes: 3 additions & 0 deletions src/bin/rustdoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub struct Options {
flag_quiet: Option<bool>,
flag_color: Option<String>,
flag_message_format: MessageFormat,
flag_build_plan: bool,
flag_package: Option<String>,
flag_lib: bool,
flag_bin: Vec<String>,
Expand Down Expand Up @@ -66,6 +67,7 @@ Options:
-q, --quiet No output printed to stdout
--color WHEN Coloring: auto, always, never
--message-format FMT Error format: human, json [default: human]
--build-plan Generate a build plan
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
-Z FLAG ... Unstable (nightly-only) flags to Cargo
Expand Down Expand Up @@ -114,6 +116,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
&options.flag_bench, options.flag_benches,
options.flag_all_targets),
message_format: options.flag_message_format,
build_plan: options.flag_build_plan,
mode: ops::CompileMode::Doc { deps: false },
target_rustdoc_args: Some(&options.arg_opts),
target_rustc_args: None,
Expand Down
3 changes: 3 additions & 0 deletions src/bin/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub struct Options {
flag_quiet: Option<bool>,
flag_color: Option<String>,
flag_message_format: MessageFormat,
flag_build_plan: bool,
flag_release: bool,
flag_no_fail_fast: bool,
flag_frozen: bool,
Expand Down Expand Up @@ -75,6 +76,7 @@ Options:
-q, --quiet No output printed to stdout
--color WHEN Coloring: auto, always, never
--message-format FMT Error format: human, json [default: human]
--build-plan Generate a build plan
--no-fail-fast Run all tests regardless of failure
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
Expand Down Expand Up @@ -167,6 +169,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
mode: mode,
filter: filter,
message_format: options.flag_message_format,
build_plan: options.flag_build_plan,
target_rustdoc_args: None,
target_rustc_args: None,
},
Expand Down
5 changes: 5 additions & 0 deletions src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ pub struct CompileOptions<'a> {
pub mode: CompileMode,
/// `--error_format` flag for the compiler.
pub message_format: MessageFormat,
/// Output a build plan to stdout instead of actually compiling.
pub build_plan: bool,
/// Extra arguments to be passed to rustdoc (for main crate and dependencies)
pub target_rustdoc_args: Option<&'a [String]>,
/// The specified target will be compiled with all the available arguments,
Expand All @@ -81,6 +83,7 @@ impl<'a> CompileOptions<'a> {
release: false,
filter: CompileFilter::Default { required_features_filterable: false },
message_format: MessageFormat::Human,
build_plan: false,
target_rustdoc_args: None,
target_rustc_args: None,
}
Expand Down Expand Up @@ -213,6 +216,7 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>,
let CompileOptions { config, jobs, target, spec, features,
all_features, no_default_features,
release, mode, message_format,
build_plan,
ref filter,
ref target_rustdoc_args,
ref target_rustc_args } = *options;
Expand Down Expand Up @@ -310,6 +314,7 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>,
build_config.release = release;
build_config.test = mode == CompileMode::Test || mode == CompileMode::Bench;
build_config.json_messages = message_format == MessageFormat::Json;
build_config.build_plan = build_plan;
if let CompileMode::Doc { deps } = mode {
build_config.doc_all = deps;
}
Expand Down
1 change: 1 addition & 0 deletions src/cargo/ops/cargo_package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ fn run_verify(ws: &Workspace, tar: &FileLock, opts: &PackageOpts) -> CargoResult
filter: ops::CompileFilter::Default { required_features_filterable: true },
release: false,
message_format: ops::MessageFormat::Human,
build_plan: false,
mode: ops::CompileMode::Build,
target_rustdoc_args: None,
target_rustc_args: None,
Expand Down
109 changes: 109 additions & 0 deletions src/cargo/ops/cargo_rustc/build_plan.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//! A graph-like structure used to represent the rustc commands to build the project and the
//! interdependencies between them.
//!
//! The BuildPlan structure is used to store the dependency graph of a dry run so that it can be
//! shared with an external build system. Each Module in the BuildPlan comprises a single
//! subprocess and defines the build environment, the outputs produced by the subprocess, and the
//! dependencies on other Modules.
use std::collections::{HashMap};

use super::{Context, Unit};
use super::context::TargetFileType;
use util::{internal, CargoResult, ProcessBuilder};
use std::sync::Arc;
use std::path::PathBuf;
use serde_json;

#[derive(Debug, Serialize)]
struct Module {
deps: Vec<String>,
outputs: Vec<PathBuf>,
links: HashMap<PathBuf, PathBuf>,
program: String,
args: Vec<String>,
env: HashMap<String, String>,
cwd: String,
}

#[derive(Debug, Serialize)]
pub struct BuildPlan {
modules: HashMap<String, Module>,
}

impl Module {
pub fn new(deps: Vec<Unit>) -> Module {
Module {
deps: deps.iter().map(|dep| buildkey(dep)).collect(),
outputs: Vec::new(),
links: HashMap::new(),
program: String::new(),
args: Vec::new(),
env: HashMap::new(),
cwd: String::new(),
}
}

pub fn add_output(&mut self, path: &PathBuf, link: &Option<PathBuf>) {
self.outputs.push(path.clone());
if link.is_some() {
self.links.insert(link.as_ref().unwrap().clone(), path.clone());
}
}

pub fn update_cmd(&mut self, cmd: ProcessBuilder) {
self.program = cmd.get_program().to_str().expect("unicode program string required").to_string().clone();
self.cwd = cmd.get_cwd().expect("cwd is required").to_str().expect("unicode cwd string required").to_string().clone();
for arg in cmd.get_args().iter() {
self.args.push(arg.to_str().expect("unicode argument string required").to_string().clone());
}
for (var, value) in cmd.get_envs() {
self.env.insert(var.clone(), value.as_ref().expect("environment value required").to_str().expect("unicode environment value required").to_string().clone());
}
}
}

pub fn buildkey(unit: &Unit) -> String {
format!("{} {} {} {:?}", unit.pkg, unit.target, unit.profile, unit.kind)
}

impl BuildPlan {
pub fn new() -> BuildPlan {
BuildPlan {
modules: HashMap::new(),
}
}

pub fn add(&mut self,
cx: &Context,
unit: &Unit,
) -> CargoResult<()> {
let k = buildkey(unit);
let deps = cx.dep_targets(&unit)?;
let module = Module::new(deps);
self.modules.insert(k, module);
Ok(())
}

pub fn update(&mut self,
module_name: String,
cmd: ProcessBuilder,
filenames: Arc<Vec<(PathBuf, Option<PathBuf>, TargetFileType)>>,
) -> CargoResult<()> {
let module = self.modules.get_mut(&module_name).ok_or_else(|| {
internal(format!("couldn't find module for {}", module_name))
})?;

module.update_cmd(cmd);
for &(ref dst, ref link_dst, _) in filenames.iter() {
module.add_output(dst, link_dst);
}

Ok(())
}

pub fn output_plan(self) {
let encoded = serde_json::to_string_pretty(&self).unwrap();
println!("{}", encoded);
}
}
Loading

0 comments on commit 333fe61

Please sign in to comment.