]> git.proxmox.com Git - cargo.git/blob - src/cargo/core/manifest.rs
Auto merge of #6883 - alexcrichton:pipelining-v2, r=ehuss
[cargo.git] / src / cargo / core / manifest.rs
1 use std::collections::{BTreeMap, HashMap};
2 use std::fmt;
3 use std::hash::{Hash, Hasher};
4 use std::path::{Path, PathBuf};
5 use std::rc::Rc;
6
7 use semver::Version;
8 use serde::ser;
9 use serde::Serialize;
10 use url::Url;
11
12 use crate::core::interning::InternedString;
13 use crate::core::profiles::Profiles;
14 use crate::core::{Dependency, PackageId, PackageIdSpec, SourceId, Summary};
15 use crate::core::{Edition, Feature, Features, WorkspaceConfig};
16 use crate::util::errors::*;
17 use crate::util::toml::TomlManifest;
18 use crate::util::{short_hash, Config, Filesystem};
19
20 pub enum EitherManifest {
21 Real(Manifest),
22 Virtual(VirtualManifest),
23 }
24
25 /// Contains all the information about a package, as loaded from a `Cargo.toml`.
26 #[derive(Clone, Debug)]
27 pub struct Manifest {
28 summary: Summary,
29 targets: Vec<Target>,
30 links: Option<String>,
31 warnings: Warnings,
32 exclude: Vec<String>,
33 include: Vec<String>,
34 metadata: ManifestMetadata,
35 custom_metadata: Option<toml::Value>,
36 profiles: Profiles,
37 publish: Option<Vec<String>>,
38 publish_lockfile: bool,
39 replace: Vec<(PackageIdSpec, Dependency)>,
40 patch: HashMap<Url, Vec<Dependency>>,
41 workspace: WorkspaceConfig,
42 original: Rc<TomlManifest>,
43 features: Features,
44 edition: Edition,
45 im_a_teapot: Option<bool>,
46 default_run: Option<String>,
47 metabuild: Option<Vec<String>>,
48 }
49
50 /// When parsing `Cargo.toml`, some warnings should silenced
51 /// if the manifest comes from a dependency. `ManifestWarning`
52 /// allows this delayed emission of warnings.
53 #[derive(Clone, Debug)]
54 pub struct DelayedWarning {
55 pub message: String,
56 pub is_critical: bool,
57 }
58
59 #[derive(Clone, Debug)]
60 pub struct Warnings(Vec<DelayedWarning>);
61
62 #[derive(Clone, Debug)]
63 pub struct VirtualManifest {
64 replace: Vec<(PackageIdSpec, Dependency)>,
65 patch: HashMap<Url, Vec<Dependency>>,
66 workspace: WorkspaceConfig,
67 profiles: Profiles,
68 warnings: Warnings,
69 features: Features,
70 }
71
72 /// General metadata about a package which is just blindly uploaded to the
73 /// registry.
74 ///
75 /// Note that many of these fields can contain invalid values such as the
76 /// homepage, repository, documentation, or license. These fields are not
77 /// validated by cargo itself, but rather it is up to the registry when uploaded
78 /// to validate these fields. Cargo will itself accept any valid TOML
79 /// specification for these values.
80 #[derive(PartialEq, Clone, Debug)]
81 pub struct ManifestMetadata {
82 pub authors: Vec<String>,
83 pub keywords: Vec<String>,
84 pub categories: Vec<String>,
85 pub license: Option<String>,
86 pub license_file: Option<String>,
87 pub description: Option<String>, // Not in Markdown
88 pub readme: Option<String>, // File, not contents
89 pub homepage: Option<String>, // URL
90 pub repository: Option<String>, // URL
91 pub documentation: Option<String>, // URL
92 pub badges: BTreeMap<String, BTreeMap<String, String>>,
93 pub links: Option<String>,
94 }
95
96 #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
97 pub enum LibKind {
98 Lib,
99 Rlib,
100 Dylib,
101 ProcMacro,
102 Other(String),
103 }
104
105 impl LibKind {
106 /// Returns the argument suitable for `--crate-type` to pass to rustc.
107 pub fn crate_type(&self) -> &str {
108 match *self {
109 LibKind::Lib => "lib",
110 LibKind::Rlib => "rlib",
111 LibKind::Dylib => "dylib",
112 LibKind::ProcMacro => "proc-macro",
113 LibKind::Other(ref s) => s,
114 }
115 }
116
117 pub fn linkable(&self) -> bool {
118 match *self {
119 LibKind::Lib | LibKind::Rlib | LibKind::Dylib | LibKind::ProcMacro => true,
120 LibKind::Other(..) => false,
121 }
122 }
123
124 pub fn requires_upstream_objects(&self) -> bool {
125 match *self {
126 // "lib" == "rlib" and is a compilation that doesn't actually
127 // require upstream object files to exist, only upstream metadata
128 // files. As a result, it doesn't require upstream artifacts
129 LibKind::Lib | LibKind::Rlib => false,
130
131 // Everything else, however, is some form of "linkable output" or
132 // something that requires upstream object files.
133 _ => true,
134 }
135 }
136 }
137
138 impl fmt::Debug for LibKind {
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 self.crate_type().fmt(f)
141 }
142 }
143
144 impl<'a> From<&'a String> for LibKind {
145 fn from(string: &'a String) -> Self {
146 match string.as_ref() {
147 "lib" => LibKind::Lib,
148 "rlib" => LibKind::Rlib,
149 "dylib" => LibKind::Dylib,
150 "proc-macro" => LibKind::ProcMacro,
151 s => LibKind::Other(s.to_string()),
152 }
153 }
154 }
155
156 #[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
157 pub enum TargetKind {
158 Lib(Vec<LibKind>),
159 Bin,
160 Test,
161 Bench,
162 ExampleLib(Vec<LibKind>),
163 ExampleBin,
164 CustomBuild,
165 }
166
167 impl ser::Serialize for TargetKind {
168 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
169 where
170 S: ser::Serializer,
171 {
172 use self::TargetKind::*;
173 match *self {
174 Lib(ref kinds) => s.collect_seq(kinds.iter().map(LibKind::crate_type)),
175 Bin => ["bin"].serialize(s),
176 ExampleBin | ExampleLib(_) => ["example"].serialize(s),
177 Test => ["test"].serialize(s),
178 CustomBuild => ["custom-build"].serialize(s),
179 Bench => ["bench"].serialize(s),
180 }
181 }
182 }
183
184 impl fmt::Debug for TargetKind {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 use self::TargetKind::*;
187 match *self {
188 Lib(ref kinds) => kinds.fmt(f),
189 Bin => "bin".fmt(f),
190 ExampleBin | ExampleLib(_) => "example".fmt(f),
191 Test => "test".fmt(f),
192 CustomBuild => "custom-build".fmt(f),
193 Bench => "bench".fmt(f),
194 }
195 }
196 }
197
198 impl TargetKind {
199 pub fn description(&self) -> &'static str {
200 match self {
201 TargetKind::Lib(..) => "lib",
202 TargetKind::Bin => "bin",
203 TargetKind::Test => "integration-test",
204 TargetKind::ExampleBin | TargetKind::ExampleLib(..) => "example",
205 TargetKind::Bench => "bench",
206 TargetKind::CustomBuild => "build-script",
207 }
208 }
209 }
210
211 /// Information about a binary, a library, an example, etc. that is part of the
212 /// package.
213 #[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
214 pub struct Target {
215 kind: TargetKind,
216 name: String,
217 // Note that the `src_path` here is excluded from the `Hash` implementation
218 // as it's absolute currently and is otherwise a little too brittle for
219 // causing rebuilds. Instead the hash for the path that we send to the
220 // compiler is handled elsewhere.
221 src_path: TargetSourcePath,
222 required_features: Option<Vec<String>>,
223 tested: bool,
224 benched: bool,
225 doc: bool,
226 doctest: bool,
227 harness: bool, // whether to use the test harness (--test)
228 for_host: bool,
229 proc_macro: bool,
230 edition: Edition,
231 }
232
233 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
234 pub enum TargetSourcePath {
235 Path(PathBuf),
236 Metabuild,
237 }
238
239 impl TargetSourcePath {
240 pub fn path(&self) -> Option<&Path> {
241 match self {
242 TargetSourcePath::Path(path) => Some(path.as_ref()),
243 TargetSourcePath::Metabuild => None,
244 }
245 }
246
247 pub fn is_path(&self) -> bool {
248 match self {
249 TargetSourcePath::Path(_) => true,
250 _ => false,
251 }
252 }
253 }
254
255 impl Hash for TargetSourcePath {
256 fn hash<H: Hasher>(&self, _: &mut H) {
257 // ...
258 }
259 }
260
261 impl fmt::Debug for TargetSourcePath {
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 match self {
264 TargetSourcePath::Path(path) => path.fmt(f),
265 TargetSourcePath::Metabuild => "metabuild".fmt(f),
266 }
267 }
268 }
269
270 impl From<PathBuf> for TargetSourcePath {
271 fn from(path: PathBuf) -> Self {
272 assert!(path.is_absolute(), "`{}` is not absolute", path.display());
273 TargetSourcePath::Path(path)
274 }
275 }
276
277 #[derive(Serialize)]
278 struct SerializedTarget<'a> {
279 /// Is this a `--bin bin`, `--lib`, `--example ex`?
280 /// Serialized as a list of strings for historical reasons.
281 kind: &'a TargetKind,
282 /// Corresponds to `--crate-type` compiler attribute.
283 /// See https://doc.rust-lang.org/reference/linkage.html
284 crate_types: Vec<&'a str>,
285 name: &'a str,
286 src_path: Option<&'a PathBuf>,
287 edition: &'a str,
288 #[serde(rename = "required-features", skip_serializing_if = "Option::is_none")]
289 required_features: Option<Vec<&'a str>>,
290 }
291
292 impl ser::Serialize for Target {
293 fn serialize<S: ser::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
294 let src_path = match &self.src_path {
295 TargetSourcePath::Path(p) => Some(p),
296 // Unfortunately getting the correct path would require access to
297 // target_dir, which is not available here.
298 TargetSourcePath::Metabuild => None,
299 };
300 SerializedTarget {
301 kind: &self.kind,
302 crate_types: self.rustc_crate_types(),
303 name: &self.name,
304 src_path,
305 edition: &self.edition.to_string(),
306 required_features: self
307 .required_features
308 .as_ref()
309 .map(|rf| rf.iter().map(|s| &**s).collect()),
310 }
311 .serialize(s)
312 }
313 }
314
315 compact_debug! {
316 impl fmt::Debug for Target {
317 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
318 let (default, default_name) = {
319 match &self.kind {
320 TargetKind::Lib(kinds) => {
321 (
322 Target::lib_target(
323 &self.name,
324 kinds.clone(),
325 self.src_path().path().unwrap().to_path_buf(),
326 self.edition,
327 ),
328 format!("lib_target({:?}, {:?}, {:?}, {:?})",
329 self.name, kinds, self.src_path, self.edition),
330 )
331 }
332 TargetKind::CustomBuild => {
333 match self.src_path {
334 TargetSourcePath::Path(ref path) => {
335 (
336 Target::custom_build_target(
337 &self.name,
338 path.to_path_buf(),
339 self.edition,
340 ),
341 format!("custom_build_target({:?}, {:?}, {:?})",
342 self.name, path, self.edition),
343 )
344 }
345 TargetSourcePath::Metabuild => {
346 (
347 Target::metabuild_target(&self.name),
348 format!("metabuild_target({:?})", self.name),
349 )
350 }
351 }
352 }
353 _ => (
354 Target::new(self.src_path.clone(), self.edition),
355 format!("with_path({:?}, {:?})", self.src_path, self.edition),
356 ),
357 }
358 };
359 [debug_the_fields(
360 kind
361 name
362 src_path
363 required_features
364 tested
365 benched
366 doc
367 doctest
368 harness
369 for_host
370 proc_macro
371 edition
372 )]
373 }
374 }
375 }
376
377 impl Manifest {
378 pub fn new(
379 summary: Summary,
380 targets: Vec<Target>,
381 exclude: Vec<String>,
382 include: Vec<String>,
383 links: Option<String>,
384 metadata: ManifestMetadata,
385 custom_metadata: Option<toml::Value>,
386 profiles: Profiles,
387 publish: Option<Vec<String>>,
388 publish_lockfile: bool,
389 replace: Vec<(PackageIdSpec, Dependency)>,
390 patch: HashMap<Url, Vec<Dependency>>,
391 workspace: WorkspaceConfig,
392 features: Features,
393 edition: Edition,
394 im_a_teapot: Option<bool>,
395 default_run: Option<String>,
396 original: Rc<TomlManifest>,
397 metabuild: Option<Vec<String>>,
398 ) -> Manifest {
399 Manifest {
400 summary,
401 targets,
402 warnings: Warnings::new(),
403 exclude,
404 include,
405 links,
406 metadata,
407 custom_metadata,
408 profiles,
409 publish,
410 replace,
411 patch,
412 workspace,
413 features,
414 edition,
415 original,
416 im_a_teapot,
417 default_run,
418 publish_lockfile,
419 metabuild,
420 }
421 }
422
423 pub fn dependencies(&self) -> &[Dependency] {
424 self.summary.dependencies()
425 }
426 pub fn exclude(&self) -> &[String] {
427 &self.exclude
428 }
429 pub fn include(&self) -> &[String] {
430 &self.include
431 }
432 pub fn metadata(&self) -> &ManifestMetadata {
433 &self.metadata
434 }
435 pub fn name(&self) -> InternedString {
436 self.package_id().name()
437 }
438 pub fn package_id(&self) -> PackageId {
439 self.summary.package_id()
440 }
441 pub fn summary(&self) -> &Summary {
442 &self.summary
443 }
444 pub fn summary_mut(&mut self) -> &mut Summary {
445 &mut self.summary
446 }
447 pub fn targets(&self) -> &[Target] {
448 &self.targets
449 }
450 pub fn version(&self) -> &Version {
451 self.package_id().version()
452 }
453 pub fn warnings_mut(&mut self) -> &mut Warnings {
454 &mut self.warnings
455 }
456 pub fn warnings(&self) -> &Warnings {
457 &self.warnings
458 }
459 pub fn profiles(&self) -> &Profiles {
460 &self.profiles
461 }
462 pub fn publish(&self) -> &Option<Vec<String>> {
463 &self.publish
464 }
465 pub fn publish_lockfile(&self) -> bool {
466 self.publish_lockfile
467 }
468 pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] {
469 &self.replace
470 }
471 pub fn original(&self) -> &TomlManifest {
472 &self.original
473 }
474 pub fn patch(&self) -> &HashMap<Url, Vec<Dependency>> {
475 &self.patch
476 }
477 pub fn links(&self) -> Option<&str> {
478 self.links.as_ref().map(|s| &s[..])
479 }
480
481 pub fn workspace_config(&self) -> &WorkspaceConfig {
482 &self.workspace
483 }
484
485 pub fn features(&self) -> &Features {
486 &self.features
487 }
488
489 pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Manifest {
490 Manifest {
491 summary: self.summary.map_source(to_replace, replace_with),
492 ..self
493 }
494 }
495
496 pub fn feature_gate(&self) -> CargoResult<()> {
497 if self.im_a_teapot.is_some() {
498 self.features
499 .require(Feature::test_dummy_unstable())
500 .chain_err(|| {
501 failure::format_err!(
502 "the `im-a-teapot` manifest key is unstable and may \
503 not work properly in England"
504 )
505 })?;
506 }
507
508 if self.default_run.is_some() {
509 self.features
510 .require(Feature::default_run())
511 .chain_err(|| failure::format_err!("the `default-run` manifest key is unstable"))?;
512 }
513
514 Ok(())
515 }
516
517 // Just a helper function to test out `-Z` flags on Cargo
518 pub fn print_teapot(&self, config: &Config) {
519 if let Some(teapot) = self.im_a_teapot {
520 if config.cli_unstable().print_im_a_teapot {
521 println!("im-a-teapot = {}", teapot);
522 }
523 }
524 }
525
526 pub fn edition(&self) -> Edition {
527 self.edition
528 }
529
530 pub fn custom_metadata(&self) -> Option<&toml::Value> {
531 self.custom_metadata.as_ref()
532 }
533
534 pub fn default_run(&self) -> Option<&str> {
535 self.default_run.as_ref().map(|s| &s[..])
536 }
537
538 pub fn metabuild(&self) -> Option<&Vec<String>> {
539 self.metabuild.as_ref()
540 }
541
542 pub fn metabuild_path(&self, target_dir: Filesystem) -> PathBuf {
543 let hash = short_hash(&self.package_id());
544 target_dir
545 .into_path_unlocked()
546 .join(".metabuild")
547 .join(format!("metabuild-{}-{}.rs", self.name(), hash))
548 }
549 }
550
551 impl VirtualManifest {
552 pub fn new(
553 replace: Vec<(PackageIdSpec, Dependency)>,
554 patch: HashMap<Url, Vec<Dependency>>,
555 workspace: WorkspaceConfig,
556 profiles: Profiles,
557 features: Features,
558 ) -> VirtualManifest {
559 VirtualManifest {
560 replace,
561 patch,
562 workspace,
563 profiles,
564 warnings: Warnings::new(),
565 features,
566 }
567 }
568
569 pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] {
570 &self.replace
571 }
572
573 pub fn patch(&self) -> &HashMap<Url, Vec<Dependency>> {
574 &self.patch
575 }
576
577 pub fn workspace_config(&self) -> &WorkspaceConfig {
578 &self.workspace
579 }
580
581 pub fn profiles(&self) -> &Profiles {
582 &self.profiles
583 }
584
585 pub fn warnings_mut(&mut self) -> &mut Warnings {
586 &mut self.warnings
587 }
588
589 pub fn warnings(&self) -> &Warnings {
590 &self.warnings
591 }
592
593 pub fn features(&self) -> &Features {
594 &self.features
595 }
596 }
597
598 impl Target {
599 fn new(src_path: TargetSourcePath, edition: Edition) -> Target {
600 Target {
601 kind: TargetKind::Bin,
602 name: String::new(),
603 src_path,
604 required_features: None,
605 doc: false,
606 doctest: false,
607 harness: true,
608 for_host: false,
609 proc_macro: false,
610 edition,
611 tested: true,
612 benched: true,
613 }
614 }
615
616 fn with_path(src_path: PathBuf, edition: Edition) -> Target {
617 Target::new(TargetSourcePath::from(src_path), edition)
618 }
619
620 pub fn lib_target(
621 name: &str,
622 crate_targets: Vec<LibKind>,
623 src_path: PathBuf,
624 edition: Edition,
625 ) -> Target {
626 Target {
627 kind: TargetKind::Lib(crate_targets),
628 name: name.to_string(),
629 doctest: true,
630 doc: true,
631 ..Target::with_path(src_path, edition)
632 }
633 }
634
635 pub fn bin_target(
636 name: &str,
637 src_path: PathBuf,
638 required_features: Option<Vec<String>>,
639 edition: Edition,
640 ) -> Target {
641 Target {
642 kind: TargetKind::Bin,
643 name: name.to_string(),
644 required_features,
645 doc: true,
646 ..Target::with_path(src_path, edition)
647 }
648 }
649
650 /// Builds a `Target` corresponding to the `build = "build.rs"` entry.
651 pub fn custom_build_target(name: &str, src_path: PathBuf, edition: Edition) -> Target {
652 Target {
653 kind: TargetKind::CustomBuild,
654 name: name.to_string(),
655 for_host: true,
656 benched: false,
657 tested: false,
658 ..Target::with_path(src_path, edition)
659 }
660 }
661
662 pub fn metabuild_target(name: &str) -> Target {
663 Target {
664 kind: TargetKind::CustomBuild,
665 name: name.to_string(),
666 for_host: true,
667 benched: false,
668 tested: false,
669 ..Target::new(TargetSourcePath::Metabuild, Edition::Edition2018)
670 }
671 }
672
673 pub fn example_target(
674 name: &str,
675 crate_targets: Vec<LibKind>,
676 src_path: PathBuf,
677 required_features: Option<Vec<String>>,
678 edition: Edition,
679 ) -> Target {
680 let kind = if crate_targets.is_empty()
681 || crate_targets
682 .iter()
683 .all(|t| *t == LibKind::Other("bin".into()))
684 {
685 TargetKind::ExampleBin
686 } else {
687 TargetKind::ExampleLib(crate_targets)
688 };
689
690 Target {
691 kind,
692 name: name.to_string(),
693 required_features,
694 tested: false,
695 benched: false,
696 ..Target::with_path(src_path, edition)
697 }
698 }
699
700 pub fn test_target(
701 name: &str,
702 src_path: PathBuf,
703 required_features: Option<Vec<String>>,
704 edition: Edition,
705 ) -> Target {
706 Target {
707 kind: TargetKind::Test,
708 name: name.to_string(),
709 required_features,
710 benched: false,
711 ..Target::with_path(src_path, edition)
712 }
713 }
714
715 pub fn bench_target(
716 name: &str,
717 src_path: PathBuf,
718 required_features: Option<Vec<String>>,
719 edition: Edition,
720 ) -> Target {
721 Target {
722 kind: TargetKind::Bench,
723 name: name.to_string(),
724 required_features,
725 tested: false,
726 ..Target::with_path(src_path, edition)
727 }
728 }
729
730 pub fn name(&self) -> &str {
731 &self.name
732 }
733 pub fn crate_name(&self) -> String {
734 self.name.replace("-", "_")
735 }
736 pub fn src_path(&self) -> &TargetSourcePath {
737 &self.src_path
738 }
739 pub fn set_src_path(&mut self, src_path: TargetSourcePath) {
740 self.src_path = src_path;
741 }
742 pub fn required_features(&self) -> Option<&Vec<String>> {
743 self.required_features.as_ref()
744 }
745 pub fn kind(&self) -> &TargetKind {
746 &self.kind
747 }
748 pub fn tested(&self) -> bool {
749 self.tested
750 }
751 pub fn harness(&self) -> bool {
752 self.harness
753 }
754 pub fn documented(&self) -> bool {
755 self.doc
756 }
757 pub fn for_host(&self) -> bool {
758 self.for_host
759 }
760 pub fn proc_macro(&self) -> bool {
761 self.proc_macro
762 }
763 pub fn edition(&self) -> Edition {
764 self.edition
765 }
766 pub fn benched(&self) -> bool {
767 self.benched
768 }
769 pub fn doctested(&self) -> bool {
770 self.doctest
771 }
772
773 pub fn doctestable(&self) -> bool {
774 match self.kind {
775 TargetKind::Lib(ref kinds) => kinds
776 .iter()
777 .any(|k| *k == LibKind::Rlib || *k == LibKind::Lib || *k == LibKind::ProcMacro),
778 _ => false,
779 }
780 }
781
782 pub fn allows_underscores(&self) -> bool {
783 self.is_bin() || self.is_example() || self.is_custom_build()
784 }
785
786 pub fn is_lib(&self) -> bool {
787 match self.kind {
788 TargetKind::Lib(_) => true,
789 _ => false,
790 }
791 }
792
793 pub fn is_dylib(&self) -> bool {
794 match self.kind {
795 TargetKind::Lib(ref libs) => libs.iter().any(|l| *l == LibKind::Dylib),
796 _ => false,
797 }
798 }
799
800 pub fn is_cdylib(&self) -> bool {
801 let libs = match self.kind {
802 TargetKind::Lib(ref libs) => libs,
803 _ => return false,
804 };
805 libs.iter().any(|l| match *l {
806 LibKind::Other(ref s) => s == "cdylib",
807 _ => false,
808 })
809 }
810
811 /// Returns whether this target produces an artifact which can be linked
812 /// into a Rust crate.
813 ///
814 /// This only returns true for certain kinds of libraries.
815 pub fn linkable(&self) -> bool {
816 match self.kind {
817 TargetKind::Lib(ref kinds) => kinds.iter().any(|k| k.linkable()),
818 _ => false,
819 }
820 }
821
822 /// Returns whether production of this artifact requires the object files
823 /// from dependencies to be available.
824 ///
825 /// This only returns `false` when all we're producing is an rlib, otherwise
826 /// it will return `true`.
827 pub fn requires_upstream_objects(&self) -> bool {
828 match &self.kind {
829 TargetKind::Lib(kinds) | TargetKind::ExampleLib(kinds) => {
830 kinds.iter().any(|k| k.requires_upstream_objects())
831 }
832 _ => true,
833 }
834 }
835
836 pub fn is_bin(&self) -> bool {
837 self.kind == TargetKind::Bin
838 }
839
840 pub fn is_example(&self) -> bool {
841 match self.kind {
842 TargetKind::ExampleBin | TargetKind::ExampleLib(..) => true,
843 _ => false,
844 }
845 }
846
847 /// Returns `true` if it is a binary or executable example.
848 /// NOTE: Tests are `false`!
849 pub fn is_executable(&self) -> bool {
850 self.is_bin() || self.is_exe_example()
851 }
852
853 /// Returns `true` if it is an executable example.
854 pub fn is_exe_example(&self) -> bool {
855 // Needed for --all-examples in contexts where only runnable examples make sense
856 match self.kind {
857 TargetKind::ExampleBin => true,
858 _ => false,
859 }
860 }
861
862 pub fn is_test(&self) -> bool {
863 self.kind == TargetKind::Test
864 }
865 pub fn is_bench(&self) -> bool {
866 self.kind == TargetKind::Bench
867 }
868 pub fn is_custom_build(&self) -> bool {
869 self.kind == TargetKind::CustomBuild
870 }
871
872 /// Returns the arguments suitable for `--crate-type` to pass to rustc.
873 pub fn rustc_crate_types(&self) -> Vec<&str> {
874 match self.kind {
875 TargetKind::Lib(ref kinds) | TargetKind::ExampleLib(ref kinds) => {
876 kinds.iter().map(LibKind::crate_type).collect()
877 }
878 TargetKind::CustomBuild
879 | TargetKind::Bench
880 | TargetKind::Test
881 | TargetKind::ExampleBin
882 | TargetKind::Bin => vec!["bin"],
883 }
884 }
885
886 pub fn can_lto(&self) -> bool {
887 match self.kind {
888 TargetKind::Lib(ref v) => {
889 !v.contains(&LibKind::Rlib)
890 && !v.contains(&LibKind::Dylib)
891 && !v.contains(&LibKind::Lib)
892 }
893 _ => true,
894 }
895 }
896
897 pub fn set_tested(&mut self, tested: bool) -> &mut Target {
898 self.tested = tested;
899 self
900 }
901 pub fn set_benched(&mut self, benched: bool) -> &mut Target {
902 self.benched = benched;
903 self
904 }
905 pub fn set_doctest(&mut self, doctest: bool) -> &mut Target {
906 self.doctest = doctest;
907 self
908 }
909 pub fn set_for_host(&mut self, for_host: bool) -> &mut Target {
910 self.for_host = for_host;
911 self
912 }
913 pub fn set_proc_macro(&mut self, proc_macro: bool) -> &mut Target {
914 self.proc_macro = proc_macro;
915 self
916 }
917 pub fn set_edition(&mut self, edition: Edition) -> &mut Target {
918 self.edition = edition;
919 self
920 }
921 pub fn set_harness(&mut self, harness: bool) -> &mut Target {
922 self.harness = harness;
923 self
924 }
925 pub fn set_doc(&mut self, doc: bool) -> &mut Target {
926 self.doc = doc;
927 self
928 }
929 }
930
931 impl fmt::Display for Target {
932 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
933 match self.kind {
934 TargetKind::Lib(..) => write!(f, "Target(lib)"),
935 TargetKind::Bin => write!(f, "Target(bin: {})", self.name),
936 TargetKind::Test => write!(f, "Target(test: {})", self.name),
937 TargetKind::Bench => write!(f, "Target(bench: {})", self.name),
938 TargetKind::ExampleBin | TargetKind::ExampleLib(..) => {
939 write!(f, "Target(example: {})", self.name)
940 }
941 TargetKind::CustomBuild => write!(f, "Target(script)"),
942 }
943 }
944 }
945
946 impl Warnings {
947 fn new() -> Warnings {
948 Warnings(Vec::new())
949 }
950
951 pub fn add_warning(&mut self, s: String) {
952 self.0.push(DelayedWarning {
953 message: s,
954 is_critical: false,
955 })
956 }
957
958 pub fn add_critical_warning(&mut self, s: String) {
959 self.0.push(DelayedWarning {
960 message: s,
961 is_critical: true,
962 })
963 }
964
965 pub fn warnings(&self) -> &[DelayedWarning] {
966 &self.0
967 }
968 }