Skip to content

Add --build-plan for 'cargo build' #4734

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all 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
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: &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 @@ -122,6 +124,7 @@ pub fn execute(options: Options, config: &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 @@ -37,6 +37,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 @@ -64,6 +65,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 @@ -119,6 +121,7 @@ pub fn execute(options: Options, config: &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 @@ -111,6 +113,7 @@ pub fn execute(options: Options, config: &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 @@ -126,6 +126,7 @@ pub fn execute(options: Options, config: &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: &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: &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: &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: &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 @@ -60,6 +60,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 @@ -82,6 +84,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 @@ -204,6 +207,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 @@ -306,6 +310,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 @@ -306,6 +306,7 @@ fn run_verify(ws: &Workspace, tar: &File, 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
108 changes: 108 additions & 0 deletions src/cargo/ops/cargo_rustc/build_plan.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//! 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 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>, bool)>>,
) -> 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