build_plan/
lib.rs

1//! A parser for Cargo's `--build-plan` output.
2//!
3//! The main type is [`BuildPlan`]. To parse Cargo's output into a `BuildPlan`, call
4//! [`BuildPlan::from_cargo_output`].
5//!
6//! [`BuildPlan`]: struct.BuildPlan.html
7//! [`BuildPlan::from_cargo_output`]: struct.BuildPlan.html#method.from_cargo_output
8
9#![doc(html_root_url = "https://docs.rs/build-plan/0.1.1")]
10#![warn(missing_debug_implementations)]
11
12#[macro_use]
13extern crate serde_derive;
14extern crate serde;
15extern crate serde_json;
16extern crate semver;
17
18use serde::de::{self, Error};
19use std::collections::BTreeMap;
20use std::path::PathBuf;
21
22/// Whether an object is for the host arch, or the target arch.
23///
24/// These will be the same unless cross-compiling.
25#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord, Serialize, Deserialize)]
26pub enum Kind {
27    Host,
28    Target,
29}
30
31/// Kinds of libraries that can be created.
32#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
33pub enum LibKind {
34    Lib,
35    Rlib,
36    Dylib,
37    ProcMacro,
38    Other(String),
39}
40
41impl LibKind {
42    pub fn from_str(string: &str) -> LibKind {
43        match string {
44            "lib" => LibKind::Lib,
45            "rlib" => LibKind::Rlib,
46            "dylib" => LibKind::Dylib,
47            "proc-macro" => LibKind::ProcMacro,
48            s => LibKind::Other(s.to_string()),
49        }
50    }
51
52    /// Returns the argument suitable for `--crate-type` to pass to rustc.
53    pub fn crate_type(&self) -> &str {
54        match *self {
55            LibKind::Lib => "lib",
56            LibKind::Rlib => "rlib",
57            LibKind::Dylib => "dylib",
58            LibKind::ProcMacro => "proc-macro",
59            LibKind::Other(ref s) => s,
60        }
61    }
62
63    pub fn linkable(&self) -> bool {
64        match *self {
65            LibKind::Lib | LibKind::Rlib | LibKind::Dylib | LibKind::ProcMacro => true,
66            LibKind::Other(..) => false,
67        }
68    }
69}
70
71/// Describes artifacts that can be produced using `cargo build`.
72#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
73pub enum TargetKind {
74    Lib(Vec<LibKind>),
75    Bin,
76    Test,
77    Bench,
78    ExampleLib(Vec<LibKind>),
79    ExampleBin,
80    CustomBuild,
81}
82
83impl<'de> de::Deserialize<'de> for TargetKind {
84    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where
85        D: de::Deserializer<'de> {
86        use self::TargetKind::*;
87
88        let raw = Vec::<&str>::deserialize(deserializer)?;
89        Ok(match *raw {
90            [] => return Err(D::Error::invalid_length(0, &"at least one target kind")),
91            ["bin"] => Bin,
92            ["example"] => ExampleBin,  // FIXME ExampleLib is never created this way
93            ["test"] => Test,
94            ["custom-build"] => CustomBuild,
95            ["bench"] => Bench,
96            ref lib_kinds => Lib(lib_kinds.iter().cloned().map(LibKind::from_str).collect()),
97        })
98    }
99}
100
101/// A tool invocation.
102#[derive(Debug, Deserialize)]
103pub struct Invocation {
104    /// The package this invocation is building a part of.
105    pub package_name: String,
106    /// Version of the package that is being built.
107    pub package_version: semver::Version,
108    /// The kind of artifact this invocation creates.
109    pub target_kind: TargetKind,
110    /// Whether the files created by this invocation are for the host or target system.
111    pub kind: Kind,
112    /// List of invocations this invocation depends on.
113    ///
114    /// The vector contains indices into the [`BuildPlan::invocations`] list.
115    ///
116    /// [`BuildPlan::invocations`]: struct.BuildPlan.html#structfield.invocations
117    pub deps: Vec<usize>,
118    /// List of output artifacts (binaries/libraries) created by this invocation.
119    pub outputs: Vec<PathBuf>,
120    /// Hardlinks of output files that should be placed.
121    pub links: BTreeMap<PathBuf, PathBuf>,
122    /// The program to invoke.
123    pub program: String,
124    /// Arguments to pass to the program.
125    pub args: Vec<String>,
126    /// Map of environment variables.
127    pub env: BTreeMap<String, String>,
128    /// The working directory in which to execute the program.
129    pub cwd: Option<PathBuf>,
130}
131
132/// A build plan output by `cargo build --build-plan`.
133#[derive(Debug, Deserialize)]
134pub struct BuildPlan {
135    /// Program invocations needed to build the target (along with dependency information).
136    pub invocations: Vec<Invocation>,
137    /// List of Cargo manifests involved in the build.
138    pub inputs: Vec<PathBuf>,
139}
140
141impl BuildPlan {
142    /// Parses a `BuildPlan` from Cargo's JSON output.
143    ///
144    /// Build plan output can be obtained by running `cargo build --build-plan`. Generating build
145    /// plans for individual targets (tests, examples, etc.) also works.
146    pub fn from_cargo_output<S: AsRef<[u8]>>(output: S) -> serde_json::Result<Self> {
147        serde_json::from_slice(output.as_ref())
148    }
149}