mirror of
https://github.com/rust-lang/cargo
synced 2024-10-14 19:52:45 +00:00
Auto merge of #4559 - derekdreery:add_docs, r=alexcrichton
Add some more docs Add some more docs for various parts of cargo, and add/improve a few debug implementations.
This commit is contained in:
commit
873a081019
|
@ -20,12 +20,13 @@ use util::errors::{CargoResult, CargoResultExt};
|
|||
// TODO: Is manifest_path a relic?
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Package {
|
||||
// The package's manifest
|
||||
/// The package's manifest
|
||||
manifest: Manifest,
|
||||
// The root of the package
|
||||
/// The root of the package
|
||||
manifest_path: PathBuf,
|
||||
}
|
||||
|
||||
/// A Package in a form where `Serialize` can be derived.
|
||||
#[derive(Serialize)]
|
||||
struct SerializedPackage<'a> {
|
||||
name: &'a str,
|
||||
|
@ -69,6 +70,7 @@ impl ser::Serialize for Package {
|
|||
}
|
||||
|
||||
impl Package {
|
||||
/// Create a package from a manifest and its location
|
||||
pub fn new(manifest: Manifest,
|
||||
manifest_path: &Path) -> Package {
|
||||
Package {
|
||||
|
@ -77,6 +79,7 @@ impl Package {
|
|||
}
|
||||
}
|
||||
|
||||
/// Calculate the Package from the manifest path (and cargo configuration).
|
||||
pub fn for_path(manifest_path: &Path, config: &Config) -> CargoResult<Package> {
|
||||
let path = manifest_path.parent().unwrap();
|
||||
let source_id = SourceId::for_path(path)?;
|
||||
|
@ -84,18 +87,30 @@ impl Package {
|
|||
Ok(pkg)
|
||||
}
|
||||
|
||||
/// Get the manifest dependencies
|
||||
pub fn dependencies(&self) -> &[Dependency] { self.manifest.dependencies() }
|
||||
/// Get the manifest
|
||||
pub fn manifest(&self) -> &Manifest { &self.manifest }
|
||||
/// Get the path to the manifest
|
||||
pub fn manifest_path(&self) -> &Path { &self.manifest_path }
|
||||
/// Get the name of the package
|
||||
pub fn name(&self) -> &str { self.package_id().name() }
|
||||
/// Get the PackageId object for the package (fully defines a packge)
|
||||
pub fn package_id(&self) -> &PackageId { self.manifest.package_id() }
|
||||
/// Get the root folder of the package
|
||||
pub fn root(&self) -> &Path { self.manifest_path.parent().unwrap() }
|
||||
/// Get the summary for the package
|
||||
pub fn summary(&self) -> &Summary { self.manifest.summary() }
|
||||
/// Get the targets specified in the manifest
|
||||
pub fn targets(&self) -> &[Target] { self.manifest.targets() }
|
||||
/// Get the current package version
|
||||
pub fn version(&self) -> &Version { self.package_id().version() }
|
||||
/// Get the package authors
|
||||
pub fn authors(&self) -> &Vec<String> { &self.manifest.metadata().authors }
|
||||
/// Whether the package is set to publish
|
||||
pub fn publish(&self) -> bool { self.manifest.publish() }
|
||||
|
||||
/// Whether the package uses a custom build script for any target
|
||||
pub fn has_custom_build(&self) -> bool {
|
||||
self.targets().iter().any(|t| t.is_custom_build())
|
||||
}
|
||||
|
|
|
@ -7,37 +7,60 @@ use termcolor::{self, StandardStream, Color, ColorSpec, WriteColor};
|
|||
|
||||
use util::errors::CargoResult;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
/// The requested verbosity of output
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Verbosity {
|
||||
Verbose,
|
||||
Normal,
|
||||
Quiet
|
||||
}
|
||||
|
||||
/// An abstraction around a `Write`able object that remembers preferences for output verbosity and
|
||||
/// color.
|
||||
pub struct Shell {
|
||||
/// the `Write`able object, either with or without color support (represented by different enum
|
||||
/// variants)
|
||||
err: ShellOut,
|
||||
/// How verbose messages should be
|
||||
verbosity: Verbosity,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Shell {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Shell")
|
||||
match &self.err {
|
||||
&ShellOut::Write(_) => f.debug_struct("Shell")
|
||||
.field("verbosity", &self.verbosity)
|
||||
.finish(),
|
||||
&ShellOut::Stream(_, color_choice) => f.debug_struct("Shell")
|
||||
.field("verbosity", &self.verbosity)
|
||||
.field("color_choice", &color_choice)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A `Write`able object, either with or without color support
|
||||
enum ShellOut {
|
||||
/// A plain write object without color support
|
||||
Write(Box<Write>),
|
||||
/// Color-enabled stdio, with information on whether color should be used
|
||||
Stream(StandardStream, ColorChoice),
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Copy)]
|
||||
/// Whether messages should use color output
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub enum ColorChoice {
|
||||
/// Force color output
|
||||
Always,
|
||||
/// Force disable color output
|
||||
Never,
|
||||
/// Intelligently guess whether to use color output
|
||||
CargoAuto,
|
||||
}
|
||||
|
||||
impl Shell {
|
||||
/// Create a new shell (color choice and verbosity), defaulting to 'auto' color and verbose
|
||||
/// output.
|
||||
pub fn new() -> Shell {
|
||||
Shell {
|
||||
err: ShellOut::Stream(
|
||||
|
@ -48,6 +71,7 @@ impl Shell {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a shell from a plain writable object, with no color, and max verbosity.
|
||||
pub fn from_write(out: Box<Write>) -> Shell {
|
||||
Shell {
|
||||
err: ShellOut::Write(out),
|
||||
|
@ -55,6 +79,8 @@ impl Shell {
|
|||
}
|
||||
}
|
||||
|
||||
/// Print a message, where the status will have `color` color, and can be justified. The
|
||||
/// messages follows without color.
|
||||
fn print(&mut self,
|
||||
status: &fmt::Display,
|
||||
message: &fmt::Display,
|
||||
|
@ -68,16 +94,19 @@ impl Shell {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get a reference to the underlying writer
|
||||
pub fn err(&mut self) -> &mut Write {
|
||||
self.err.as_write()
|
||||
}
|
||||
|
||||
/// Shortcut to right-align and color green a status message.
|
||||
pub fn status<T, U>(&mut self, status: T, message: U) -> CargoResult<()>
|
||||
where T: fmt::Display, U: fmt::Display
|
||||
{
|
||||
self.print(&status, &message, Green, true)
|
||||
}
|
||||
|
||||
/// Shortcut to right-align a status message.
|
||||
pub fn status_with_color<T, U>(&mut self,
|
||||
status: T,
|
||||
message: U,
|
||||
|
@ -87,6 +116,7 @@ impl Shell {
|
|||
self.print(&status, &message, color, true)
|
||||
}
|
||||
|
||||
/// Run the callback only if we are in verbose mode
|
||||
pub fn verbose<F>(&mut self, mut callback: F) -> CargoResult<()>
|
||||
where F: FnMut(&mut Shell) -> CargoResult<()>
|
||||
{
|
||||
|
@ -96,6 +126,7 @@ impl Shell {
|
|||
}
|
||||
}
|
||||
|
||||
/// Run the callback if we are not in verbose mode.
|
||||
pub fn concise<F>(&mut self, mut callback: F) -> CargoResult<()>
|
||||
where F: FnMut(&mut Shell) -> CargoResult<()>
|
||||
{
|
||||
|
@ -105,10 +136,12 @@ impl Shell {
|
|||
}
|
||||
}
|
||||
|
||||
/// Print a red 'error' message
|
||||
pub fn error<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
|
||||
self.print(&"error:", &message, Red, false)
|
||||
}
|
||||
|
||||
/// Print an amber 'warning' message
|
||||
pub fn warn<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
|
||||
match self.verbosity {
|
||||
Verbosity::Quiet => Ok(()),
|
||||
|
@ -116,14 +149,17 @@ impl Shell {
|
|||
}
|
||||
}
|
||||
|
||||
/// Update the verbosity of the shell
|
||||
pub fn set_verbosity(&mut self, verbosity: Verbosity) {
|
||||
self.verbosity = verbosity;
|
||||
}
|
||||
|
||||
/// Get the verbosity of the shell
|
||||
pub fn verbosity(&self) -> Verbosity {
|
||||
self.verbosity
|
||||
}
|
||||
|
||||
/// Update the color choice (always, never, or auto) from a string.
|
||||
pub fn set_color_choice(&mut self, color: Option<&str>) -> CargoResult<()> {
|
||||
if let ShellOut::Stream(ref mut err, ref mut cc) = self.err {
|
||||
let cfg = match color {
|
||||
|
@ -142,6 +178,10 @@ impl Shell {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Get the current color choice
|
||||
///
|
||||
/// If we are not using a color stream, this will always return Never, even if the color choice
|
||||
/// has been set to something else.
|
||||
pub fn color_choice(&self) -> ColorChoice {
|
||||
match self.err {
|
||||
ShellOut::Stream(_, cc) => cc,
|
||||
|
@ -151,6 +191,8 @@ impl Shell {
|
|||
}
|
||||
|
||||
impl ShellOut {
|
||||
/// Print out a message with a status. The status comes first and is bold + the given color.
|
||||
/// The status can be justified, in which case the max width that will right align is 12 chars.
|
||||
fn print(&mut self,
|
||||
status: &fmt::Display,
|
||||
message: &fmt::Display,
|
||||
|
@ -182,6 +224,7 @@ impl ShellOut {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Get this object as a `io::Write`.
|
||||
fn as_write(&mut self) -> &mut Write {
|
||||
match *self {
|
||||
ShellOut::Stream(ref mut err, _) => err,
|
||||
|
@ -191,6 +234,7 @@ impl ShellOut {
|
|||
}
|
||||
|
||||
impl ColorChoice {
|
||||
/// Convert our color choice to termcolor's version
|
||||
fn to_termcolor_color_choice(&self) -> termcolor::ColorChoice {
|
||||
match *self {
|
||||
ColorChoice::Always => termcolor::ColorChoice::Always,
|
||||
|
|
|
@ -21,6 +21,7 @@ use util::{Config, CargoResult, ToUrl};
|
|||
/// A Source finds and downloads remote packages based on names and
|
||||
/// versions.
|
||||
pub trait Source: Registry {
|
||||
/// Returns the `SourceId` corresponding to this source
|
||||
fn source_id(&self) -> &SourceId;
|
||||
|
||||
/// The update method performs any network operations required to
|
||||
|
@ -56,27 +57,34 @@ pub trait Source: Registry {
|
|||
}
|
||||
|
||||
impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
|
||||
/// Forwards to `Source::source_id`
|
||||
fn source_id(&self) -> &SourceId {
|
||||
(**self).source_id()
|
||||
}
|
||||
|
||||
/// Forwards to `Source::update`
|
||||
fn update(&mut self) -> CargoResult<()> {
|
||||
(**self).update()
|
||||
}
|
||||
|
||||
/// Forwards to `Source::download`
|
||||
fn download(&mut self, id: &PackageId) -> CargoResult<Package> {
|
||||
(**self).download(id)
|
||||
}
|
||||
|
||||
/// Forwards to `Source::fingerprint`
|
||||
fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {
|
||||
(**self).fingerprint(pkg)
|
||||
}
|
||||
|
||||
/// Forwards to `Source::verify`
|
||||
fn verify(&self, pkg: &PackageId) -> CargoResult<()> {
|
||||
(**self).verify(pkg)
|
||||
}
|
||||
}
|
||||
|
||||
/// The possible kinds of code source. Along with a URL, this fully defines the
|
||||
/// source
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
enum Kind {
|
||||
/// Kind::Git(<git reference>) represents a git repository
|
||||
|
@ -91,10 +99,14 @@ enum Kind {
|
|||
Directory,
|
||||
}
|
||||
|
||||
/// Information to find a specific commit in a git repository
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum GitReference {
|
||||
/// from a tag
|
||||
Tag(String),
|
||||
/// from the HEAD of a branch
|
||||
Branch(String),
|
||||
/// from a specific revision
|
||||
Rev(String),
|
||||
}
|
||||
|
||||
|
@ -104,16 +116,23 @@ pub struct SourceId {
|
|||
inner: Arc<SourceIdInner>,
|
||||
}
|
||||
|
||||
/// Unique identifier for a source of packages.
|
||||
#[derive(Eq, Clone, Debug)]
|
||||
struct SourceIdInner {
|
||||
/// The source URL
|
||||
url: Url,
|
||||
/// `git::canonicalize_url(url)` for the url field
|
||||
canonical_url: Url,
|
||||
/// The source kind
|
||||
kind: Kind,
|
||||
// e.g. the exact git revision of the specified branch for a Git Source
|
||||
precise: Option<String>,
|
||||
}
|
||||
|
||||
impl SourceId {
|
||||
/// Create a SourceId object from the kind and url.
|
||||
///
|
||||
/// The canonical url will be calculated, but the precise field will not
|
||||
fn new(kind: Kind, url: Url) -> CargoResult<SourceId> {
|
||||
let source_id = SourceId {
|
||||
inner: Arc::new(SourceIdInner {
|
||||
|
@ -174,29 +193,36 @@ impl SourceId {
|
|||
}
|
||||
}
|
||||
|
||||
/// A view of the `SourceId` that can be `Display`ed as a URL
|
||||
pub fn to_url(&self) -> SourceIdToUrl {
|
||||
SourceIdToUrl { inner: &*self.inner }
|
||||
}
|
||||
|
||||
// Pass absolute path
|
||||
/// Create a SourceId from a filesystem path.
|
||||
///
|
||||
/// Pass absolute path
|
||||
pub fn for_path(path: &Path) -> CargoResult<SourceId> {
|
||||
let url = path.to_url()?;
|
||||
SourceId::new(Kind::Path, url)
|
||||
}
|
||||
|
||||
/// Crate a SourceId from a git reference
|
||||
pub fn for_git(url: &Url, reference: GitReference) -> CargoResult<SourceId> {
|
||||
SourceId::new(Kind::Git(reference), url.clone())
|
||||
}
|
||||
|
||||
/// Create a SourceId from a registry url
|
||||
pub fn for_registry(url: &Url) -> CargoResult<SourceId> {
|
||||
SourceId::new(Kind::Registry, url.clone())
|
||||
}
|
||||
|
||||
/// Create a SourceId from a local registry path
|
||||
pub fn for_local_registry(path: &Path) -> CargoResult<SourceId> {
|
||||
let url = path.to_url()?;
|
||||
SourceId::new(Kind::LocalRegistry, url)
|
||||
}
|
||||
|
||||
/// Create a SourceId from a directory path
|
||||
pub fn for_directory(path: &Path) -> CargoResult<SourceId> {
|
||||
let url = path.to_url()?;
|
||||
SourceId::new(Kind::Directory, url)
|
||||
|
@ -212,9 +238,9 @@ impl SourceId {
|
|||
static WARNED: AtomicBool = ATOMIC_BOOL_INIT;
|
||||
if !WARNED.swap(true, SeqCst) {
|
||||
config.shell().warn("custom registry support via \
|
||||
the `registry.index` configuration is \
|
||||
being removed, this functionality \
|
||||
will not work in the future")?;
|
||||
the `registry.index` configuration is \
|
||||
being removed, this functionality \
|
||||
will not work in the future")?;
|
||||
}
|
||||
&index[..]
|
||||
} else {
|
||||
|
@ -224,16 +250,22 @@ impl SourceId {
|
|||
SourceId::for_registry(&url)
|
||||
}
|
||||
|
||||
/// Get this source URL
|
||||
pub fn url(&self) -> &Url {
|
||||
&self.inner.url
|
||||
}
|
||||
|
||||
/// Is this source from a filesystem path
|
||||
pub fn is_path(&self) -> bool {
|
||||
self.inner.kind == Kind::Path
|
||||
}
|
||||
|
||||
/// Is this source from a registry (either local or not)
|
||||
pub fn is_registry(&self) -> bool {
|
||||
self.inner.kind == Kind::Registry || self.inner.kind == Kind::LocalRegistry
|
||||
}
|
||||
|
||||
/// Is this source from a git repository
|
||||
pub fn is_git(&self) -> bool {
|
||||
match self.inner.kind {
|
||||
Kind::Git(_) => true,
|
||||
|
@ -271,10 +303,12 @@ impl SourceId {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the value of the precise field
|
||||
pub fn precise(&self) -> Option<&str> {
|
||||
self.inner.precise.as_ref().map(|s| &s[..])
|
||||
}
|
||||
|
||||
/// Get the git reference if this is a git source, otherwise None.
|
||||
pub fn git_reference(&self) -> Option<&GitReference> {
|
||||
match self.inner.kind {
|
||||
Kind::Git(ref s) => Some(s),
|
||||
|
@ -282,6 +316,7 @@ impl SourceId {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a new SourceId from this source with the given `precise`
|
||||
pub fn with_precise(&self, v: Option<String>) -> SourceId {
|
||||
SourceId {
|
||||
inner: Arc::new(SourceIdInner {
|
||||
|
@ -291,6 +326,7 @@ impl SourceId {
|
|||
}
|
||||
}
|
||||
|
||||
/// Whether the remote registry is the standard https://crates.io
|
||||
pub fn is_default_registry(&self) -> bool {
|
||||
match self.inner.kind {
|
||||
Kind::Registry => {}
|
||||
|
@ -299,6 +335,10 @@ impl SourceId {
|
|||
self.inner.url.to_string() == CRATES_IO
|
||||
}
|
||||
|
||||
/// Hash `self`
|
||||
///
|
||||
/// For paths, remove the workspace prefix so the same source will give the
|
||||
/// same hash in different locations.
|
||||
pub fn stable_hash<S: hash::Hasher>(&self, workspace: &Path, into: &mut S) {
|
||||
if self.is_path() {
|
||||
if let Ok(p) = self.inner.url.to_file_path().unwrap().strip_prefix(workspace) {
|
||||
|
@ -383,6 +423,9 @@ impl fmt::Display for SourceId {
|
|||
// This custom implementation handles situations such as when two git sources
|
||||
// point at *almost* the same URL, but not quite, even when they actually point
|
||||
// to the same repository.
|
||||
/// This method tests for self and other values to be equal, and is used by ==.
|
||||
///
|
||||
/// For git repositories, the canonical url is checked.
|
||||
impl PartialEq for SourceIdInner {
|
||||
fn eq(&self, other: &SourceIdInner) -> bool {
|
||||
if self.kind != other.kind {
|
||||
|
@ -441,6 +484,7 @@ impl Hash for SourceId {
|
|||
}
|
||||
}
|
||||
|
||||
/// A `Display`able view into a SourceId that will write it as a url
|
||||
pub struct SourceIdToUrl<'a> {
|
||||
inner: &'a SourceIdInner,
|
||||
}
|
||||
|
@ -477,6 +521,8 @@ impl<'a> fmt::Display for SourceIdToUrl<'a> {
|
|||
}
|
||||
|
||||
impl GitReference {
|
||||
/// Returns a `Display`able view of this git reference, or None if using
|
||||
/// the head of the "master" branch
|
||||
pub fn pretty_ref(&self) -> Option<PrettyRef> {
|
||||
match *self {
|
||||
GitReference::Branch(ref s) if *s == "master" => None,
|
||||
|
@ -485,6 +531,7 @@ impl GitReference {
|
|||
}
|
||||
}
|
||||
|
||||
/// A git reference that can be `Display`ed
|
||||
pub struct PrettyRef<'a> {
|
||||
inner: &'a GitReference,
|
||||
}
|
||||
|
@ -499,26 +546,32 @@ impl<'a> fmt::Display for PrettyRef<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A `HashMap` of `SourceId` -> `Box<Source>`
|
||||
#[derive(Default)]
|
||||
pub struct SourceMap<'src> {
|
||||
map: HashMap<SourceId, Box<Source + 'src>>,
|
||||
}
|
||||
|
||||
/// A `std::collection::hash_map::Values` for `SourceMap`
|
||||
pub type Sources<'a, 'src> = Values<'a, SourceId, Box<Source + 'src>>;
|
||||
|
||||
/// A `std::collection::hash_map::IterMut` for `SourceMap`
|
||||
pub struct SourcesMut<'a, 'src: 'a> {
|
||||
inner: IterMut<'a, SourceId, Box<Source + 'src>>,
|
||||
}
|
||||
|
||||
impl<'src> SourceMap<'src> {
|
||||
/// Create an empty map
|
||||
pub fn new() -> SourceMap<'src> {
|
||||
SourceMap { map: HashMap::new() }
|
||||
}
|
||||
|
||||
/// Like `HashMap::contains_key`
|
||||
pub fn contains(&self, id: &SourceId) -> bool {
|
||||
self.map.contains_key(id)
|
||||
}
|
||||
|
||||
/// Like `HashMap::get`
|
||||
pub fn get(&self, id: &SourceId) -> Option<&(Source + 'src)> {
|
||||
let source = self.map.get(id);
|
||||
|
||||
|
@ -528,6 +581,7 @@ impl<'src> SourceMap<'src> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Like `HashMap::get_mut`
|
||||
pub fn get_mut(&mut self, id: &SourceId) -> Option<&mut (Source + 'src)> {
|
||||
self.map.get_mut(id).map(|s| {
|
||||
let s: &mut (Source + 'src) = &mut **s;
|
||||
|
@ -535,27 +589,34 @@ impl<'src> SourceMap<'src> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Like `HashMap::get`, but first calculates the `SourceId` from a
|
||||
/// `PackageId`
|
||||
pub fn get_by_package_id(&self, pkg_id: &PackageId) -> Option<&(Source + 'src)> {
|
||||
self.get(pkg_id.source_id())
|
||||
}
|
||||
|
||||
/// Like `HashMap::insert`, but derives the SourceId key from the Source
|
||||
pub fn insert(&mut self, source: Box<Source + 'src>) {
|
||||
let id = source.source_id().clone();
|
||||
self.map.insert(id, source);
|
||||
}
|
||||
|
||||
/// Like `HashMap::is_empty`
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.map.is_empty()
|
||||
}
|
||||
|
||||
/// Like `HashMap::len`
|
||||
pub fn len(&self) -> usize {
|
||||
self.map.len()
|
||||
}
|
||||
|
||||
/// Like `HashMap::values`
|
||||
pub fn sources<'a>(&'a self) -> Sources<'a, 'src> {
|
||||
self.map.values()
|
||||
}
|
||||
|
||||
/// Like `HashMap::iter_mut`
|
||||
pub fn sources_mut<'a>(&'a mut self) -> SourcesMut<'a, 'src> {
|
||||
SourcesMut { inner: self.map.iter_mut() }
|
||||
}
|
||||
|
|
|
@ -25,18 +25,50 @@ use super::layout::Layout;
|
|||
use super::links::Links;
|
||||
use super::{Kind, Compilation, BuildConfig};
|
||||
|
||||
/// All information needed to define a Unit.
|
||||
///
|
||||
/// A unit is an object that has enough information so that cargo knows how to build it.
|
||||
/// For example, if your project has dependencies, then every dependency will be built as a library
|
||||
/// unit. If your project is a library, then it will be built as a library unit as well, or if it
|
||||
/// is a binary with `main.rs`, then a binary will be output. There are also separate unit types
|
||||
/// for `test`ing and `check`ing, amongst others.
|
||||
///
|
||||
/// The unit also holds information about all possible metadata about the package in `pkg`.
|
||||
///
|
||||
/// A unit needs to know extra information in addition to the type and root source file. For
|
||||
/// example, it needs to know the target architecture (OS, chip arch etc.) and it needs to know
|
||||
/// whether you want a debug or release build. There is enough information in this struct to figure
|
||||
/// all that out.
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub struct Unit<'a> {
|
||||
/// Information about avaiable targets, which files to include/exclude, etc. Basically stuff in
|
||||
/// `Cargo.toml`.
|
||||
pub pkg: &'a Package,
|
||||
/// Information about the specific target to build, out of the possible targets in `pkg`. Not
|
||||
/// to be confused with *target-triple* (or *target architecture* ...), the target arch for a
|
||||
/// build.
|
||||
pub target: &'a Target,
|
||||
/// The profile contains information about *how* the build should be run, including debug
|
||||
/// level, extra args to pass to rustc, etc.
|
||||
pub profile: &'a Profile,
|
||||
/// Whether this compilation unit is for the host or target architecture.
|
||||
///
|
||||
/// For example, when
|
||||
/// cross compiling and using a custom build script, the build script needs to be compiled for
|
||||
/// the host architecture so the host rustc can use it (when compiling to the target
|
||||
/// architecture).
|
||||
pub kind: Kind,
|
||||
}
|
||||
|
||||
/// The build context, containing all information about a build task
|
||||
pub struct Context<'a, 'cfg: 'a> {
|
||||
/// The workspace the build is for
|
||||
pub ws: &'a Workspace<'cfg>,
|
||||
/// The cargo configuration
|
||||
pub config: &'cfg Config,
|
||||
/// The dependency graph for our build
|
||||
pub resolve: &'a Resolve,
|
||||
/// Information on the compilation output
|
||||
pub compilation: Compilation<'cfg>,
|
||||
pub packages: &'a PackageSet<'cfg>,
|
||||
pub build_state: Arc<BuildState>,
|
||||
|
@ -50,13 +82,21 @@ pub struct Context<'a, 'cfg: 'a> {
|
|||
pub used_in_plugin: HashSet<Unit<'a>>,
|
||||
pub jobserver: Client,
|
||||
|
||||
/// The target directory layout for the host (and target if it is the same as host)
|
||||
host: Layout,
|
||||
/// The target directory layout for the target (if different from then host)
|
||||
target: Option<Layout>,
|
||||
target_info: TargetInfo,
|
||||
host_info: TargetInfo,
|
||||
profiles: &'a Profiles,
|
||||
incremental_enabled: bool,
|
||||
|
||||
/// For each Unit, a list all files produced as a triple of
|
||||
///
|
||||
/// - File name that will be produced by the build process (in `deps`)
|
||||
/// - If it should be linked into `target`, and what it should be called (e.g. without
|
||||
/// metadata).
|
||||
/// - Whether it is something you can link against (e.g. a library)
|
||||
target_filenames: HashMap<Unit<'a>, Arc<Vec<(PathBuf, Option<PathBuf>, bool)>>>,
|
||||
target_metadatas: HashMap<Unit<'a>, Option<Metadata>>,
|
||||
}
|
||||
|
@ -210,6 +250,10 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// A recursive function that checks all crate types (`rlib`, ...) are in `crate_types`
|
||||
/// for this unit and its dependencies.
|
||||
///
|
||||
/// Tracks visited units to avoid unnecessary work.
|
||||
fn visit_crate_type(&self,
|
||||
unit: &Unit<'a>,
|
||||
crate_types: &mut BTreeSet<String>,
|
||||
|
@ -660,7 +704,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
//info!("{:?}", unit);
|
||||
match *unit.target.kind() {
|
||||
TargetKind::Bin |
|
||||
TargetKind::CustomBuild |
|
||||
|
@ -1038,8 +1082,23 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
|
|||
}
|
||||
}
|
||||
|
||||
// Acquire extra flags to pass to the compiler from the
|
||||
// RUSTFLAGS environment variable and similar config values
|
||||
/// Acquire extra flags to pass to the compiler from various locations.
|
||||
///
|
||||
/// The locations are:
|
||||
///
|
||||
/// - the `RUSTFLAGS` environment variable
|
||||
///
|
||||
/// then if this was not found
|
||||
///
|
||||
/// - `target.*.rustflags` from the manifest (Cargo.toml)
|
||||
/// - `target.cfg(..).rustflags` from the manifest
|
||||
///
|
||||
/// then if neither of these were found
|
||||
///
|
||||
/// - `build.rustflags` from the manifest
|
||||
///
|
||||
/// Note that if a `target` is specified, no args will be passed to host code (plugins, build
|
||||
/// scripts, ...), even if it is the same as the target.
|
||||
fn env_args(config: &Config,
|
||||
build_config: &BuildConfig,
|
||||
target_info: &TargetInfo,
|
||||
|
@ -1136,6 +1195,14 @@ impl fmt::Display for Metadata {
|
|||
}
|
||||
}
|
||||
|
||||
/// Takes rustc output (using specialized command line args), and calculates the file prefix and
|
||||
/// suffix for the given crate type, or returns None if the type is not supported. (e.g. for a
|
||||
/// rust library like libcargo.rlib, prefix = "lib", suffix = "rlib").
|
||||
///
|
||||
/// The caller needs to ensure that the lines object is at the correct line for the given crate
|
||||
/// type: this is not checked.
|
||||
// This function can not handle more than 1 file per type (with wasm32-unknown-emscripten, there
|
||||
// are 2 files for bin (.wasm and .js))
|
||||
fn parse_crate_type(
|
||||
crate_type: &str,
|
||||
error: &str,
|
||||
|
|
|
@ -56,6 +56,9 @@ use std::path::{PathBuf, Path};
|
|||
use core::Workspace;
|
||||
use util::{Config, FileLock, CargoResult, Filesystem};
|
||||
|
||||
/// Contains the paths of all target output locations.
|
||||
///
|
||||
/// See module docs for more information.
|
||||
pub struct Layout {
|
||||
root: PathBuf,
|
||||
deps: PathBuf,
|
||||
|
@ -64,6 +67,7 @@ pub struct Layout {
|
|||
incremental: PathBuf,
|
||||
fingerprint: PathBuf,
|
||||
examples: PathBuf,
|
||||
/// The lockfile for a build, will be unlocked when this struct is `drop`ped.
|
||||
_lock: FileLock,
|
||||
}
|
||||
|
||||
|
@ -74,6 +78,12 @@ pub fn is_bad_artifact_name(name: &str) -> bool {
|
|||
}
|
||||
|
||||
impl Layout {
|
||||
/// Calcuate the paths for build output, lock the build directory, and return as a Layout.
|
||||
///
|
||||
/// This function will block if the directory is already locked.
|
||||
///
|
||||
/// Differs from `at` in that it calculates the root path from the workspace target directory,
|
||||
/// adding the target triple and the profile (debug, release, ...).
|
||||
pub fn new(ws: &Workspace,
|
||||
triple: Option<&str>,
|
||||
dest: &str) -> CargoResult<Layout> {
|
||||
|
@ -88,6 +98,9 @@ impl Layout {
|
|||
Layout::at(ws.config(), path)
|
||||
}
|
||||
|
||||
/// Calcuate the paths for build output, lock the build directory, and return as a Layout.
|
||||
///
|
||||
/// This function will block if the directory is already locked.
|
||||
pub fn at(config: &Config, root: Filesystem) -> CargoResult<Layout> {
|
||||
// For now we don't do any more finer-grained locking on the artifact
|
||||
// directory, so just lock the entire thing for the duration of this
|
||||
|
@ -136,6 +149,7 @@ impl Layout {
|
|||
}
|
||||
}
|
||||
|
||||
/// Make sure all directories stored in the Layout exist on the filesystem.
|
||||
pub fn prepare(&mut self) -> io::Result<()> {
|
||||
if fs::metadata(&self.root).is_err() {
|
||||
fs::create_dir_all(&self.root)?;
|
||||
|
@ -160,11 +174,18 @@ impl Layout {
|
|||
}
|
||||
}
|
||||
|
||||
/// Fetch the root path.
|
||||
pub fn dest(&self) -> &Path { &self.root }
|
||||
/// Fetch the deps path.
|
||||
pub fn deps(&self) -> &Path { &self.deps }
|
||||
/// Fetch the examples path.
|
||||
pub fn examples(&self) -> &Path { &self.examples }
|
||||
/// Fetch the root path.
|
||||
pub fn root(&self) -> &Path { &self.root }
|
||||
/// Fetch the incremental path.
|
||||
pub fn incremental(&self) -> &Path { &self.incremental }
|
||||
/// Fetch the fingerprint path.
|
||||
pub fn fingerprint(&self) -> &Path { &self.fingerprint }
|
||||
/// Fetch the build path.
|
||||
pub fn build(&self) -> &Path { &self.build }
|
||||
}
|
||||
|
|
|
@ -28,15 +28,27 @@ use util::{Filesystem, LazyCell};
|
|||
|
||||
use self::ConfigValue as CV;
|
||||
|
||||
/// Configuration information for cargo. This is not specific to a build, it is information
|
||||
/// relating to cargo itself.
|
||||
///
|
||||
/// This struct implements `Default`: all fields can be inferred.
|
||||
#[derive(Debug)]
|
||||
pub struct Config {
|
||||
/// The location of the users's 'home' directory. OS-dependent.
|
||||
home_path: Filesystem,
|
||||
/// Information about how to write messages to the shell
|
||||
shell: RefCell<Shell>,
|
||||
/// Information on how to invoke the compiler (rustc)
|
||||
rustc: LazyCell<Rustc>,
|
||||
/// A collection of configuration options
|
||||
values: LazyCell<HashMap<String, ConfigValue>>,
|
||||
/// The current working directory of cargo
|
||||
cwd: PathBuf,
|
||||
/// The location of the cargo executable (path to current process)
|
||||
cargo_exe: LazyCell<PathBuf>,
|
||||
/// The location of the rustdoc executable
|
||||
rustdoc: LazyCell<PathBuf>,
|
||||
/// Whether we are printing extra verbose messages
|
||||
extra_verbose: Cell<bool>,
|
||||
frozen: Cell<bool>,
|
||||
locked: Cell<bool>,
|
||||
|
|
|
@ -2,17 +2,23 @@ use std::path::PathBuf;
|
|||
|
||||
use util::{self, CargoResult, internal, ProcessBuilder};
|
||||
|
||||
/// Information on the `rustc` executable
|
||||
#[derive(Debug)]
|
||||
pub struct Rustc {
|
||||
/// The location of the exe
|
||||
pub path: PathBuf,
|
||||
/// An optional program that will be passed the path of the rust exe as its first argument, and
|
||||
/// rustc args following this.
|
||||
pub wrapper: Option<PathBuf>,
|
||||
/// Verbose version information (the output of `rustc -vV`)
|
||||
pub verbose_version: String,
|
||||
/// The host triple (arch-platform-OS), this comes from verbose_version.
|
||||
pub host: String,
|
||||
}
|
||||
|
||||
impl Rustc {
|
||||
/// Run the compiler at `path` to learn various pieces of information about
|
||||
/// it.
|
||||
/// it, with an optional wrapper.
|
||||
///
|
||||
/// If successful this function returns a description of the compiler along
|
||||
/// with a list of its capabilities.
|
||||
|
@ -41,6 +47,7 @@ impl Rustc {
|
|||
})
|
||||
}
|
||||
|
||||
/// Get a process builder set up to use the found rustc version, with a wrapper if Some
|
||||
pub fn process(&self) -> ProcessBuilder {
|
||||
if let Some(ref wrapper) = self.wrapper {
|
||||
let mut cmd = util::process(wrapper);
|
||||
|
|
|
@ -4,7 +4,9 @@ use url::Url;
|
|||
|
||||
use util::CargoResult;
|
||||
|
||||
/// A type that can be converted to a Url
|
||||
pub trait ToUrl {
|
||||
/// Performs the conversion
|
||||
fn to_url(self) -> CargoResult<Url>;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue