diff --git a/src/bin/cargo/commands/bench.rs b/src/bin/cargo/commands/bench.rs index b84c8160b..cdfd624cd 100644 --- a/src/bin/cargo/commands/bench.rs +++ b/src/bin/cargo/commands/bench.rs @@ -44,6 +44,7 @@ pub fn cli() -> App { "no-fail-fast", "Run all benchmarks regardless of failure", )) + .arg_unit_graph() .after_help( "\ The benchmark filtering argument BENCHNAME and all the arguments following the diff --git a/src/bin/cargo/commands/build.rs b/src/bin/cargo/commands/build.rs index 1ab83848b..991c7c0f3 100644 --- a/src/bin/cargo/commands/build.rs +++ b/src/bin/cargo/commands/build.rs @@ -41,6 +41,7 @@ pub fn cli() -> App { .arg_manifest_path() .arg_message_format() .arg_build_plan() + .arg_unit_graph() .after_help( "\ All packages in the workspace are built if the `--workspace` flag is supplied. The diff --git a/src/bin/cargo/commands/check.rs b/src/bin/cargo/commands/check.rs index 880b0d91d..e9c0dbda3 100644 --- a/src/bin/cargo/commands/check.rs +++ b/src/bin/cargo/commands/check.rs @@ -33,6 +33,7 @@ pub fn cli() -> App { .arg_target_dir() .arg_manifest_path() .arg_message_format() + .arg_unit_graph() .after_help( "\ If the `--package` argument is given, then SPEC is a package ID specification diff --git a/src/bin/cargo/commands/doc.rs b/src/bin/cargo/commands/doc.rs index 08e6d783b..a3f612fbb 100644 --- a/src/bin/cargo/commands/doc.rs +++ b/src/bin/cargo/commands/doc.rs @@ -30,6 +30,7 @@ pub fn cli() -> App { .arg_target_dir() .arg_manifest_path() .arg_message_format() + .arg_unit_graph() .after_help( "\ By default the documentation for the local package and all dependencies is diff --git a/src/bin/cargo/commands/run.rs b/src/bin/cargo/commands/run.rs index 29478d2a3..7a4981a7a 100644 --- a/src/bin/cargo/commands/run.rs +++ b/src/bin/cargo/commands/run.rs @@ -24,6 +24,7 @@ pub fn cli() -> App { .arg_target_dir() .arg_manifest_path() .arg_message_format() + .arg_unit_graph() .after_help( "\ If neither `--bin` nor `--example` are given, then if the package only has one diff --git a/src/bin/cargo/commands/rustc.rs b/src/bin/cargo/commands/rustc.rs index ec528ff45..d24e0c9b6 100644 --- a/src/bin/cargo/commands/rustc.rs +++ b/src/bin/cargo/commands/rustc.rs @@ -29,6 +29,7 @@ pub fn cli() -> App { .arg_target_dir() .arg_manifest_path() .arg_message_format() + .arg_unit_graph() .after_help( "\ The specified target for the current package (or package specified by SPEC if diff --git a/src/bin/cargo/commands/rustdoc.rs b/src/bin/cargo/commands/rustdoc.rs index f3c691658..775ad05e3 100644 --- a/src/bin/cargo/commands/rustdoc.rs +++ b/src/bin/cargo/commands/rustdoc.rs @@ -33,6 +33,7 @@ pub fn cli() -> App { .arg_target_dir() .arg_manifest_path() .arg_message_format() + .arg_unit_graph() .after_help( "\ The specified target for the current package (or package specified by SPEC if diff --git a/src/bin/cargo/commands/test.rs b/src/bin/cargo/commands/test.rs index 932cf308a..209926c73 100644 --- a/src/bin/cargo/commands/test.rs +++ b/src/bin/cargo/commands/test.rs @@ -54,6 +54,7 @@ pub fn cli() -> App { .arg_target_dir() .arg_manifest_path() .arg_message_format() + .arg_unit_graph() .after_help( "\ The test filtering argument TESTNAME and all the arguments following the diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index 26050e5db..8df5db2f7 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -22,6 +22,8 @@ pub struct BuildConfig { pub force_rebuild: bool, /// Output a build plan to stdout instead of actually compiling. pub build_plan: bool, + /// Output the unit graph to stdout instead of actually compiling. + pub unit_graph: bool, /// An optional override of the rustc process for primary units pub primary_unit_rustc: Option, pub rustfix_diagnostic_server: RefCell>, @@ -79,6 +81,7 @@ impl BuildConfig { message_format: MessageFormat::Human, force_rebuild: false, build_plan: false, + unit_graph: false, primary_unit_rustc: None, rustfix_diagnostic_server: RefCell::new(None), }) diff --git a/src/cargo/core/compiler/compile_kind.rs b/src/cargo/core/compiler/compile_kind.rs index ef23dbfa1..4ef30039d 100644 --- a/src/cargo/core/compiler/compile_kind.rs +++ b/src/cargo/core/compiler/compile_kind.rs @@ -9,7 +9,7 @@ use std::path::Path; /// compilations, where cross compilations happen at the request of `--target` /// and host compilations happen for things like build scripts and procedural /// macros. -#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord, Serialize)] +#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord)] pub enum CompileKind { /// Attached to a unit that is compiled for the "host" system or otherwise /// is compiled without a `--target` flag. This is used for procedural @@ -41,6 +41,18 @@ impl CompileKind { } } +impl serde::ser::Serialize for CompileKind { + fn serialize(&self, s: S) -> Result + where + S: serde::ser::Serializer, + { + match self { + CompileKind::Host => None::<&str>.serialize(s), + CompileKind::Target(t) => Some(t.name).serialize(s), + } + } +} + /// Abstraction for the representation of a compilation target that Cargo has. /// /// Compilation targets are one of two things right now: diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs index fdc002d35..29f39f3b7 100644 --- a/src/cargo/core/compiler/context/mod.rs +++ b/src/cargo/core/compiler/context/mod.rs @@ -16,7 +16,7 @@ use super::custom_build::{self, BuildDeps, BuildScriptOutputs, BuildScripts}; use super::fingerprint::Fingerprint; use super::job_queue::JobQueue; use super::layout::Layout; -use super::unit_dependencies::{UnitDep, UnitGraph}; +use super::unit_graph::{UnitDep, UnitGraph}; use super::{BuildContext, Compilation, CompileKind, CompileMode, Executor, FileFlavor}; mod compilation_files; diff --git a/src/cargo/core/compiler/fingerprint.rs b/src/cargo/core/compiler/fingerprint.rs index 48f134dbb..6acb67f63 100644 --- a/src/cargo/core/compiler/fingerprint.rs +++ b/src/cargo/core/compiler/fingerprint.rs @@ -202,7 +202,7 @@ use serde::de; use serde::ser; use serde::{Deserialize, Serialize}; -use crate::core::compiler::unit_dependencies::UnitDep; +use crate::core::compiler::unit_graph::UnitDep; use crate::core::{InternedString, Package}; use crate::util; use crate::util::errors::{CargoResult, CargoResultExt}; diff --git a/src/cargo/core/compiler/links.rs b/src/cargo/core/compiler/links.rs index 89fe2b292..2fc1d4d28 100644 --- a/src/cargo/core/compiler/links.rs +++ b/src/cargo/core/compiler/links.rs @@ -1,4 +1,4 @@ -use super::unit_dependencies::UnitGraph; +use super::unit_graph::UnitGraph; use crate::core::{PackageId, Resolve}; use crate::util::errors::CargoResult; use std::collections::{HashMap, HashSet}; diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 1505e2f09..49d3a9664 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -15,6 +15,7 @@ pub mod standard_lib; mod timings; mod unit; pub mod unit_dependencies; +pub mod unit_graph; use std::env; use std::ffi::{OsStr, OsString}; @@ -38,7 +39,7 @@ pub use self::job::Freshness; use self::job::{Job, Work}; use self::job_queue::{JobQueue, JobState}; use self::output_depinfo::output_depinfo; -use self::unit_dependencies::UnitDep; +use self::unit_graph::UnitDep; pub use crate::core::compiler::unit::{Unit, UnitInterner}; use crate::core::manifest::TargetSourcePath; use crate::core::profiles::{Lto, PanicStrategy, Profile}; diff --git a/src/cargo/core/compiler/unit_dependencies.rs b/src/cargo/core/compiler/unit_dependencies.rs index 1dd7f233c..05178a44d 100644 --- a/src/cargo/core/compiler/unit_dependencies.rs +++ b/src/cargo/core/compiler/unit_dependencies.rs @@ -15,6 +15,7 @@ //! (for example, with and without tests), so we actually build a dependency //! graph of `Unit`s, which capture these properties. +use crate::core::compiler::unit_graph::{UnitDep, UnitGraph}; use crate::core::compiler::Unit; use crate::core::compiler::{BuildContext, CompileKind, CompileMode}; use crate::core::dependency::DepKind; @@ -27,25 +28,6 @@ use crate::CargoResult; use log::trace; use std::collections::{HashMap, HashSet}; -/// The dependency graph of Units. -pub type UnitGraph<'a> = HashMap, Vec>>; - -/// A unit dependency. -#[derive(Debug, Clone, Hash, Eq, PartialEq, PartialOrd, Ord)] -pub struct UnitDep<'a> { - /// The dependency unit. - pub unit: Unit<'a>, - /// The purpose of this dependency (a dependency for a test, or a build - /// script, etc.). - pub unit_for: UnitFor, - /// The name the parent uses to refer to this dependency. - pub extern_crate_name: InternedString, - /// Whether or not this is a public dependency. - pub public: bool, - /// If `true`, the dependency should not be added to Rust's prelude. - pub noprelude: bool, -} - /// Collection of stuff used while creating the `UnitGraph`. struct State<'a, 'cfg> { bcx: &'a BuildContext<'a, 'cfg>, diff --git a/src/cargo/core/compiler/unit_graph.rs b/src/cargo/core/compiler/unit_graph.rs new file mode 100644 index 000000000..6119c439e --- /dev/null +++ b/src/cargo/core/compiler/unit_graph.rs @@ -0,0 +1,121 @@ +use crate::core::compiler::Unit; +use crate::core::compiler::{CompileKind, CompileMode}; +use crate::core::profiles::{Profile, UnitFor}; +use crate::core::{nightly_features_allowed, InternedString, PackageId, Target}; +use crate::util::CargoResult; +use std::collections::HashMap; +use std::io::Write; + +/// The dependency graph of Units. +pub type UnitGraph<'a> = HashMap, Vec>>; + +/// A unit dependency. +#[derive(Debug, Clone, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub struct UnitDep<'a> { + /// The dependency unit. + pub unit: Unit<'a>, + /// The purpose of this dependency (a dependency for a test, or a build + /// script, etc.). + pub unit_for: UnitFor, + /// The name the parent uses to refer to this dependency. + pub extern_crate_name: InternedString, + /// Whether or not this is a public dependency. + pub public: bool, + /// If `true`, the dependency should not be added to Rust's prelude. + pub noprelude: bool, +} + +const VERSION: u32 = 1; + +#[derive(serde::Serialize)] +struct SerializedUnitGraph<'a> { + version: u32, + units: Vec>, + roots: Vec, +} + +#[derive(serde::Serialize)] +struct SerializedUnit<'a> { + pkg_id: PackageId, + target: &'a Target, + profile: &'a Profile, + platform: CompileKind, + mode: CompileMode, + features: &'a Vec, + #[serde(skip_serializing_if = "std::ops::Not::not")] // hide for unstable build-std + is_std: bool, + dependencies: Vec, +} + +#[derive(serde::Serialize)] +struct SerializedUnitDep { + index: usize, + extern_crate_name: InternedString, + // This is only set on nightly since it is unstable. + #[serde(skip_serializing_if = "Option::is_none")] + public: Option, + // This is only set on nightly since it is unstable. + #[serde(skip_serializing_if = "Option::is_none")] + noprelude: Option, + // Intentionally not including `unit_for` because it is a low-level + // internal detail that is mostly used for building the graph. +} + +pub fn emit_serialized_unit_graph( + root_units: &[Unit<'_>], + unit_graph: &UnitGraph<'_>, +) -> CargoResult<()> { + let is_nightly = nightly_features_allowed(); + let mut units: Vec<(&Unit<'_>, &Vec>)> = unit_graph.iter().collect(); + units.sort_unstable(); + // Create a map for quick lookup for dependencies. + let indices: HashMap<&Unit<'_>, usize> = units + .iter() + .enumerate() + .map(|(i, val)| (val.0, i)) + .collect(); + let roots = root_units.iter().map(|root| indices[root]).collect(); + let ser_units = units + .iter() + .map(|(unit, unit_deps)| { + let dependencies = unit_deps + .iter() + .map(|unit_dep| { + // https://github.com/rust-lang/rust/issues/64260 when stabilized. + let (public, noprelude) = if is_nightly { + (Some(unit_dep.public), Some(unit_dep.noprelude)) + } else { + (None, None) + }; + SerializedUnitDep { + index: indices[&unit_dep.unit], + extern_crate_name: unit_dep.extern_crate_name, + public, + noprelude, + } + }) + .collect(); + SerializedUnit { + pkg_id: unit.pkg.package_id(), + target: unit.target, + profile: &unit.profile, + platform: unit.kind, + mode: unit.mode, + features: &unit.features, + is_std: unit.is_std, + dependencies, + } + }) + .collect(); + let s = SerializedUnitGraph { + version: VERSION, + units: ser_units, + roots, + }; + + let stdout = std::io::stdout(); + let mut lock = stdout.lock(); + serde_json::to_writer(&mut lock, &s)?; + write!(lock, "\n")?; + Ok(()) +} diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index 562bf1b3e..e9bca095a 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -374,6 +374,7 @@ impl Profiles { /// times). pub fn get_profile_run_custom_build(&self, for_unit_profile: &Profile) -> Profile { let mut result = Profile::default(); + result.name = for_unit_profile.name; result.root = for_unit_profile.root; result.debuginfo = for_unit_profile.debuginfo; result.opt_level = for_unit_profile.opt_level; @@ -578,10 +579,11 @@ pub enum ProfileRoot { /// Profile settings used to determine which compiler flags to use for a /// target. -#[derive(Clone, Copy, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, Eq, PartialOrd, Ord, serde::Serialize)] pub struct Profile { pub name: InternedString, pub opt_level: InternedString, + #[serde(skip)] // named profiles are unstable pub root: ProfileRoot, pub lto: Lto, // `None` means use rustc default. @@ -743,8 +745,21 @@ pub enum Lto { Named(InternedString), } +impl serde::ser::Serialize for Lto { + fn serialize(&self, s: S) -> Result + where + S: serde::ser::Serializer, + { + match self { + Lto::Bool(b) => b.to_string().serialize(s), + Lto::Named(n) => n.serialize(s), + } + } +} + /// The `panic` setting. -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord, serde::Serialize)] +#[serde(rename_all = "lowercase")] pub enum PanicStrategy { Unwind, Abort, diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 474919159..694710318 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -30,6 +30,7 @@ use std::sync::Arc; use crate::core::compiler::standard_lib; use crate::core::compiler::unit_dependencies::build_unit_dependencies; +use crate::core::compiler::unit_graph; use crate::core::compiler::{BuildConfig, BuildContext, Compilation, Context}; use crate::core::compiler::{CompileKind, CompileMode, RustcTargetData, Unit}; use crate::core::compiler::{DefaultExecutor, Executor, UnitInterner}; @@ -490,6 +491,11 @@ pub fn compile_ws<'a>( &std_roots, )?; + if bcx.build_config.unit_graph { + unit_graph::emit_serialized_unit_graph(&units, &unit_dependencies)?; + return Ok(Compilation::new(&bcx, build_config.requested_kind)?); + } + let ret = { let _p = profile::start("compiling"); let cx = Context::new(config, &bcx, unit_dependencies, build_config.requested_kind)?; diff --git a/src/cargo/util/command_prelude.rs b/src/cargo/util/command_prelude.rs index a3477b457..0b5dca3a2 100644 --- a/src/cargo/util/command_prelude.rs +++ b/src/cargo/util/command_prelude.rs @@ -150,6 +150,10 @@ pub trait AppExt: Sized { )) } + fn arg_unit_graph(self) -> Self { + self._arg(opt("unit-graph", "Output build graph in JSON (unstable)").hidden(true)) + } + fn arg_new_opts(self) -> Self { self._arg( opt( @@ -438,11 +442,17 @@ pub trait ArgMatchesExt { build_config.message_format = message_format.unwrap_or(MessageFormat::Human); build_config.requested_profile = self.get_profile_name(config, "dev", profile_checking)?; build_config.build_plan = self._is_present("build-plan"); + build_config.unit_graph = self._is_present("unit-graph"); if build_config.build_plan { config .cli_unstable() .fail_if_stable_opt("--build-plan", 5579)?; }; + if build_config.unit_graph { + config + .cli_unstable() + .fail_if_stable_opt("--unit-graph", 0)?; + } let opts = CompileOptions { config, diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index a5a8293ca..307e84ace 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -552,3 +552,127 @@ The available options are: The `-Z crate-versions` flag will make `cargo doc` include appropriate crate versions for the current crate and all of its dependencies (unless `--no-deps` was provided) in the compiled documentation. You can find an example screenshot for the cargo itself in the tracking issue. + +### unit-graph +* Tracking Issue: TODO + +The `--unit-graph` flag can be passed to any build command (`build`, `check`, +`run`, `test`, `bench`, `doc`, etc.) to emit a JSON object to stdout which +represents Cargo's internal unit graph. Nothing is actually built, and the +command returns immediately after printing. Each "unit" corresponds to an +execution of the compiler. These objects also include which unit each unit +depends on. + +``` +cargo +nightly build --unit-graph -Z unstable-options +``` + +The following is a description of the JSON structure: + +```javascript +{ + /* Version of the JSON output structure. If any backwards incompatible + changes are made, this value will be increased. + */ + "version": 1, + /* Array of all build units. */ + "units": [ + { + /* An opaque string which indicates the package. + Information about the package can be obtained from `cargo metadata`. + */ + "pkg_id": "my-package 0.1.0 (path+file:///path/to/my-package)", + /* The Cargo target. See the `cargo metadata` documentation for more + information about these fields. + https://doc.rust-lang.org/cargo/commands/cargo-metadata.html + */ + "target": { + "kind": ["lib"], + "crate_types": ["lib"], + "name": "my-package", + "src_path": "/path/to/my-package/src/lib.rs", + "edition": "2018", + "doctest": true + }, + /* The profile settings for this unit. + These values may not match the profile defined in the manifest. + Units can use modified profile settings. For example, the "panic" + setting can be overridden for tests to force it to "unwind". + */ + "profile": { + /* The profile name these settings are derived from. */ + "name": "dev", + /* The optimization level as a string. */ + "opt_level": "0", + /* The LTO setting as a string. */ + "lto": "false", + /* The codegen units as an integer. + `null` if it should use the compiler's default. + */ + "codegen_units": null, + /* The debug information level as an integer. + `null` if it should use the compiler's default (0). + */ + "debuginfo": 2, + /* Whether or not debug-assertions are enabled. */ + "debug_assertions": true, + /* Whether or not overflow-checks are enabled. */ + "overflow_checks": true, + /* Whether or not rpath is enabled. */ + "rpath": false, + /* Whether or not incremental is enabled. */ + "incremental": true, + /* The panic strategy, "unwind" or "abort". */ + "panic": "unwind" + }, + /* Which platform this target is being built for. + A value of `null` indicates it is for the host. + Otherwise it is a string of the target triple (such as + "x86_64-unknown-linux-gnu"). + */ + "platform": null, + /* The "mode" for this unit. Valid values: + + * "test" — Build using `rustc` as a test. + * "build" — Build using `rustc`. + * "check" — Build using `rustc` in "check" mode. + * "doc" — Build using `rustdoc`. + * "doctest" — Test using `rustdoc`. + * "run-custom-build" — Represents the execution of a build script. + */ + "mode": "build", + /* Array of features enabled on this unit as strings. */ + "features": ["somefeat"], + /* Whether or not this is a standard-library unit, + part of the unstable build-std feature. + If not set, treat as `false`. + */ + "is_std": false, + /* Array of dependencies of this unit. */ + "dependencies": [ + { + /* Index in the "units" array for the dependency. */ + "index": 1, + /* The name that this dependency will be referred as. */ + "extern_crate_name": "unicode_xid", + /* Whether or not this dependency is "public", + part of the unstable public-dependency feature. + If not set, the public-dependency feature is not enabled. + */ + "public": false, + /* Whether or not this dependency is injected into the prelude, + currently used by the build-std feature. + If not set, treat as `false`. + */ + "noprelude": false + } + ] + }, + // ... + ], + /* Array of indices in the "units" array that are the "roots" of the + dependency graph. + */ + "roots": [0], +} +``` diff --git a/tests/testsuite/build_plan.rs b/tests/testsuite/build_plan.rs index 6161dd83c..092ff90e6 100644 --- a/tests/testsuite/build_plan.rs +++ b/tests/testsuite/build_plan.rs @@ -24,7 +24,7 @@ fn cargo_build_plan_simple() { "cwd": "[..]/cit/[..]/foo", "deps": [], "env": "{...}", - "kind": "Host", + "kind": null, "links": "{...}", "outputs": "{...}", "package_name": "foo", @@ -84,7 +84,7 @@ fn cargo_build_plan_single_dep() { "cwd": "[..]/cit/[..]/foo", "deps": [], "env": "{...}", - "kind": "Host", + "kind": null, "links": "{...}", "outputs": [ "[..]/foo/target/debug/deps/libbar-[..].rlib", @@ -101,7 +101,7 @@ fn cargo_build_plan_single_dep() { "cwd": "[..]/cit/[..]/foo", "deps": [0], "env": "{...}", - "kind": "Host", + "kind": null, "links": "{...}", "outputs": [ "[..]/foo/target/debug/deps/libfoo-[..].rlib", @@ -152,7 +152,7 @@ fn cargo_build_plan_build_script() { "cwd": "[..]/cit/[..]/foo", "deps": [], "env": "{...}", - "kind": "Host", + "kind": null, "links": "{...}", "outputs": [ "[..]/foo/target/debug/build/[..]/build_script_build-[..]" @@ -168,7 +168,7 @@ fn cargo_build_plan_build_script() { "cwd": "[..]/cit/[..]/foo", "deps": [0], "env": "{...}", - "kind": "Host", + "kind": null, "links": "{...}", "outputs": [], "package_name": "foo", @@ -182,7 +182,7 @@ fn cargo_build_plan_build_script() { "cwd": "[..]/cit/[..]/foo", "deps": [1], "env": "{...}", - "kind": "Host", + "kind": null, "links": "{...}", "outputs": "{...}", "package_name": "foo", diff --git a/tests/testsuite/main.rs b/tests/testsuite/main.rs index d01d30fde..c5dd78020 100644 --- a/tests/testsuite/main.rs +++ b/tests/testsuite/main.rs @@ -103,6 +103,7 @@ mod standard_lib; mod test; mod timings; mod tool_paths; +mod unit_graph; mod update; mod vendor; mod verify_project; diff --git a/tests/testsuite/metabuild.rs b/tests/testsuite/metabuild.rs index 4d9fdc23f..ece3c7aec 100644 --- a/tests/testsuite/metabuild.rs +++ b/tests/testsuite/metabuild.rs @@ -461,7 +461,7 @@ fn metabuild_build_plan() { "package_version": "0.5.0", "target_kind": ["lib"], "compile_mode": "build", - "kind": "Host", + "kind": null, "deps": [], "outputs": [ "[..]/target/debug/deps/libmb-[..].rlib", @@ -478,7 +478,7 @@ fn metabuild_build_plan() { "package_version": "0.0.1", "target_kind": ["lib"], "compile_mode": "build", - "kind": "Host", + "kind": null, "deps": [], "outputs": [ "[..]/target/debug/deps/libmb_other-[..].rlib", @@ -495,7 +495,7 @@ fn metabuild_build_plan() { "package_version": "0.0.1", "target_kind": ["custom-build"], "compile_mode": "build", - "kind": "Host", + "kind": null, "deps": [0, 1], "outputs": ["[..]/target/debug/build/foo-[..]/metabuild_foo-[..][EXE]"], "links": "{...}", @@ -509,7 +509,7 @@ fn metabuild_build_plan() { "package_version": "0.0.1", "target_kind": ["custom-build"], "compile_mode": "run-custom-build", - "kind": "Host", + "kind": null, "deps": [2], "outputs": [], "links": {}, @@ -523,7 +523,7 @@ fn metabuild_build_plan() { "package_version": "0.0.1", "target_kind": ["lib"], "compile_mode": "build", - "kind": "Host", + "kind": null, "deps": [3], "outputs": [ "[..]/foo/target/debug/deps/libfoo-[..].rlib", diff --git a/tests/testsuite/unit_graph.rs b/tests/testsuite/unit_graph.rs new file mode 100644 index 000000000..878e7c3b4 --- /dev/null +++ b/tests/testsuite/unit_graph.rs @@ -0,0 +1,211 @@ +//! Tests for --unit-graph option. + +use cargo_test_support::project; +use cargo_test_support::registry::Package; + +#[cargo_test] +fn gated() { + let p = project().file("src/lib.rs", "").build(); + p.cargo("build --unit-graph") + .with_status(101) + .with_stderr( + "\ +[ERROR] the `--unit-graph` flag is unstable[..] +See [..] +See [..] +", + ) + .run(); +} + +#[cargo_test] +fn simple() { + Package::new("a", "1.0.0") + .dep("b", "1.0") + .feature("feata", &["b/featb"]) + .publish(); + Package::new("b", "1.0.0") + .dep("c", "1.0") + .feature("featb", &["c/featc"]) + .publish(); + Package::new("c", "1.0.0").feature("featc", &[]).publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build --features a/feata --unit-graph -Zunstable-options") + .masquerade_as_nightly_cargo() + .with_json( + r#"{ + "version": 1, + "units": [ + { + "pkg_id": "a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target": { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "a", + "src_path": "[..]/a-1.0.0/src/lib.rs", + "edition": "2015", + "doctest": true + }, + "profile": { + "name": "dev", + "opt_level": "0", + "lto": "false", + "codegen_units": null, + "debuginfo": 2, + "debug_assertions": true, + "overflow_checks": true, + "rpath": false, + "incremental": false, + "panic": "unwind" + }, + "platform": null, + "mode": "build", + "features": [ + "feata" + ], + "dependencies": [ + { + "index": 1, + "extern_crate_name": "b", + "public": false, + "noprelude": false + } + ] + }, + { + "pkg_id": "b 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target": { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "b", + "src_path": "[..]/b-1.0.0/src/lib.rs", + "edition": "2015", + "doctest": true + }, + "profile": { + "name": "dev", + "opt_level": "0", + "lto": "false", + "codegen_units": null, + "debuginfo": 2, + "debug_assertions": true, + "overflow_checks": true, + "rpath": false, + "incremental": false, + "panic": "unwind" + }, + "platform": null, + "mode": "build", + "features": [ + "featb" + ], + "dependencies": [ + { + "index": 2, + "extern_crate_name": "c", + "public": false, + "noprelude": false + } + ] + }, + { + "pkg_id": "c 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target": { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "c", + "src_path": "[..]/c-1.0.0/src/lib.rs", + "edition": "2015", + "doctest": true + }, + "profile": { + "name": "dev", + "opt_level": "0", + "lto": "false", + "codegen_units": null, + "debuginfo": 2, + "debug_assertions": true, + "overflow_checks": true, + "rpath": false, + "incremental": false, + "panic": "unwind" + }, + "platform": null, + "mode": "build", + "features": [ + "featc" + ], + "dependencies": [] + }, + { + "pkg_id": "foo 0.1.0 (path+file://[..]/foo)", + "target": { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "foo", + "src_path": "[..]/foo/src/lib.rs", + "edition": "2015", + "doctest": true + }, + "profile": { + "name": "dev", + "opt_level": "0", + "lto": "false", + "codegen_units": null, + "debuginfo": 2, + "debug_assertions": true, + "overflow_checks": true, + "rpath": false, + "incremental": false, + "panic": "unwind" + }, + "platform": null, + "mode": "build", + "features": [], + "dependencies": [ + { + "index": 0, + "extern_crate_name": "a", + "public": false, + "noprelude": false + } + ] + } + ], + "roots": [3] +} +"#, + ) + .run(); +}