]> git.proxmox.com Git - cargo.git/blob - src/cargo/core/manifest.rs
Merge remote-tracking branch 'origin/master' into custom-profile-pr-rfc
[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 /// Returns whether production of this artifact requires the object files
211 /// from dependencies to be available.
212 ///
213 /// This only returns `false` when all we're producing is an rlib, otherwise
214 /// it will return `true`.
215 pub fn requires_upstream_objects(&self) -> bool {
216 match self {
217 TargetKind::Lib(kinds) | TargetKind::ExampleLib(kinds) => {
218 kinds.iter().any(|k| k.requires_upstream_objects())
219 }
220 _ => true,
221 }
222 }
223 }
224
225 /// Information about a binary, a library, an example, etc. that is part of the
226 /// package.
227 #[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
228 pub struct Target {
229 kind: TargetKind,
230 name: String,
231 // Note that the `src_path` here is excluded from the `Hash` implementation
232 // as it's absolute currently and is otherwise a little too brittle for
233 // causing rebuilds. Instead the hash for the path that we send to the
234 // compiler is handled elsewhere.
235 src_path: TargetSourcePath,
236 required_features: Option<Vec<String>>,
237 tested: bool,
238 benched: bool,
239 doc: bool,
240 doctest: bool,
241 harness: bool, // whether to use the test harness (--test)
242 for_host: bool,
243 proc_macro: bool,
244 edition: Edition,
245 }
246
247 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
248 pub enum TargetSourcePath {
249 Path(PathBuf),
250 Metabuild,
251 }
252
253 impl TargetSourcePath {
254 pub fn path(&self) -> Option<&Path> {
255 match self {
256 TargetSourcePath::Path(path) => Some(path.as_ref()),
257 TargetSourcePath::Metabuild => None,
258 }
259 }
260
261 pub fn is_path(&self) -> bool {
262 match self {
263 TargetSourcePath::Path(_) => true,
264 _ => false,
265 }
266 }
267 }
268
269 impl Hash for TargetSourcePath {
270 fn hash<H: Hasher>(&self, _: &mut H) {
271 // ...
272 }
273 }
274
275 impl fmt::Debug for TargetSourcePath {
276 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277 match self {
278 TargetSourcePath::Path(path) => path.fmt(f),
279 TargetSourcePath::Metabuild => "metabuild".fmt(f),
280 }
281 }
282 }
283
284 impl From<PathBuf> for TargetSourcePath {
285 fn from(path: PathBuf) -> Self {
286 assert!(path.is_absolute(), "`{}` is not absolute", path.display());
287 TargetSourcePath::Path(path)
288 }
289 }
290
291 #[derive(Serialize)]
292 struct SerializedTarget<'a> {
293 /// Is this a `--bin bin`, `--lib`, `--example ex`?
294 /// Serialized as a list of strings for historical reasons.
295 kind: &'a TargetKind,
296 /// Corresponds to `--crate-type` compiler attribute.
297 /// See https://doc.rust-lang.org/reference/linkage.html
298 crate_types: Vec<&'a str>,
299 name: &'a str,
300 src_path: Option<&'a PathBuf>,
301 edition: &'a str,
302 #[serde(rename = "required-features", skip_serializing_if = "Option::is_none")]
303 required_features: Option<Vec<&'a str>>,
304 doctest: bool,
305 }
306
307 impl ser::Serialize for Target {
308 fn serialize<S: ser::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
309 let src_path = match &self.src_path {
310 TargetSourcePath::Path(p) => Some(p),
311 // Unfortunately getting the correct path would require access to
312 // target_dir, which is not available here.
313 TargetSourcePath::Metabuild => None,
314 };
315 SerializedTarget {
316 kind: &self.kind,
317 crate_types: self.rustc_crate_types(),
318 name: &self.name,
319 src_path,
320 edition: &self.edition.to_string(),
321 required_features: self
322 .required_features
323 .as_ref()
324 .map(|rf| rf.iter().map(|s| &**s).collect()),
325 doctest: self.doctest && self.doctestable(),
326 }
327 .serialize(s)
328 }
329 }
330
331 compact_debug! {
332 impl fmt::Debug for Target {
333 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
334 let (default, default_name) = {
335 match &self.kind {
336 TargetKind::Lib(kinds) => {
337 (
338 Target::lib_target(
339 &self.name,
340 kinds.clone(),
341 self.src_path().path().unwrap().to_path_buf(),
342 self.edition,
343 ),
344 format!("lib_target({:?}, {:?}, {:?}, {:?})",
345 self.name, kinds, self.src_path, self.edition),
346 )
347 }
348 TargetKind::CustomBuild => {
349 match self.src_path {
350 TargetSourcePath::Path(ref path) => {
351 (
352 Target::custom_build_target(
353 &self.name,
354 path.to_path_buf(),
355 self.edition,
356 ),
357 format!("custom_build_target({:?}, {:?}, {:?})",
358 self.name, path, self.edition),
359 )
360 }
361 TargetSourcePath::Metabuild => {
362 (
363 Target::metabuild_target(&self.name),
364 format!("metabuild_target({:?})", self.name),
365 )
366 }
367 }
368 }
369 _ => (
370 Target::new(self.src_path.clone(), self.edition),
371 format!("with_path({:?}, {:?})", self.src_path, self.edition),
372 ),
373 }
374 };
375 [debug_the_fields(
376 kind
377 name
378 src_path
379 required_features
380 tested
381 benched
382 doc
383 doctest
384 harness
385 for_host
386 proc_macro
387 edition
388 )]
389 }
390 }
391 }
392
393 impl Manifest {
394 pub fn new(
395 summary: Summary,
396 targets: Vec<Target>,
397 exclude: Vec<String>,
398 include: Vec<String>,
399 links: Option<String>,
400 metadata: ManifestMetadata,
401 custom_metadata: Option<toml::Value>,
402 profiles: Profiles,
403 publish: Option<Vec<String>>,
404 publish_lockfile: bool,
405 replace: Vec<(PackageIdSpec, Dependency)>,
406 patch: HashMap<Url, Vec<Dependency>>,
407 workspace: WorkspaceConfig,
408 features: Features,
409 edition: Edition,
410 im_a_teapot: Option<bool>,
411 default_run: Option<String>,
412 original: Rc<TomlManifest>,
413 metabuild: Option<Vec<String>>,
414 ) -> Manifest {
415 Manifest {
416 summary,
417 targets,
418 warnings: Warnings::new(),
419 exclude,
420 include,
421 links,
422 metadata,
423 custom_metadata,
424 profiles,
425 publish,
426 replace,
427 patch,
428 workspace,
429 features,
430 edition,
431 original,
432 im_a_teapot,
433 default_run,
434 publish_lockfile,
435 metabuild,
436 }
437 }
438
439 pub fn dependencies(&self) -> &[Dependency] {
440 self.summary.dependencies()
441 }
442 pub fn exclude(&self) -> &[String] {
443 &self.exclude
444 }
445 pub fn include(&self) -> &[String] {
446 &self.include
447 }
448 pub fn metadata(&self) -> &ManifestMetadata {
449 &self.metadata
450 }
451 pub fn name(&self) -> InternedString {
452 self.package_id().name()
453 }
454 pub fn package_id(&self) -> PackageId {
455 self.summary.package_id()
456 }
457 pub fn summary(&self) -> &Summary {
458 &self.summary
459 }
460 pub fn summary_mut(&mut self) -> &mut Summary {
461 &mut self.summary
462 }
463 pub fn targets(&self) -> &[Target] {
464 &self.targets
465 }
466 pub fn version(&self) -> &Version {
467 self.package_id().version()
468 }
469 pub fn warnings_mut(&mut self) -> &mut Warnings {
470 &mut self.warnings
471 }
472 pub fn warnings(&self) -> &Warnings {
473 &self.warnings
474 }
475 pub fn profiles(&self) -> &Profiles {
476 &self.profiles
477 }
478 pub fn publish(&self) -> &Option<Vec<String>> {
479 &self.publish
480 }
481 pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] {
482 &self.replace
483 }
484 pub fn original(&self) -> &TomlManifest {
485 &self.original
486 }
487 pub fn patch(&self) -> &HashMap<Url, Vec<Dependency>> {
488 &self.patch
489 }
490 pub fn links(&self) -> Option<&str> {
491 self.links.as_ref().map(|s| &s[..])
492 }
493
494 pub fn workspace_config(&self) -> &WorkspaceConfig {
495 &self.workspace
496 }
497
498 pub fn features(&self) -> &Features {
499 &self.features
500 }
501
502 pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Manifest {
503 Manifest {
504 summary: self.summary.map_source(to_replace, replace_with),
505 ..self
506 }
507 }
508
509 pub fn feature_gate(&self) -> CargoResult<()> {
510 if self.im_a_teapot.is_some() {
511 self.features
512 .require(Feature::test_dummy_unstable())
513 .chain_err(|| {
514 failure::format_err!(
515 "the `im-a-teapot` manifest key is unstable and may \
516 not work properly in England"
517 )
518 })?;
519 }
520
521 Ok(())
522 }
523
524 // Just a helper function to test out `-Z` flags on Cargo
525 pub fn print_teapot(&self, config: &Config) {
526 if let Some(teapot) = self.im_a_teapot {
527 if config.cli_unstable().print_im_a_teapot {
528 println!("im-a-teapot = {}", teapot);
529 }
530 }
531 }
532
533 pub fn edition(&self) -> Edition {
534 self.edition
535 }
536
537 pub fn custom_metadata(&self) -> Option<&toml::Value> {
538 self.custom_metadata.as_ref()
539 }
540
541 pub fn default_run(&self) -> Option<&str> {
542 self.default_run.as_ref().map(|s| &s[..])
543 }
544
545 pub fn metabuild(&self) -> Option<&Vec<String>> {
546 self.metabuild.as_ref()
547 }
548
549 pub fn metabuild_path(&self, target_dir: Filesystem) -> PathBuf {
550 let hash = short_hash(&self.package_id());
551 target_dir
552 .into_path_unlocked()
553 .join(".metabuild")
554 .join(format!("metabuild-{}-{}.rs", self.name(), hash))
555 }
556 }
557
558 impl VirtualManifest {
559 pub fn new(
560 replace: Vec<(PackageIdSpec, Dependency)>,
561 patch: HashMap<Url, Vec<Dependency>>,
562 workspace: WorkspaceConfig,
563 profiles: Profiles,
564 features: Features,
565 ) -> VirtualManifest {
566 VirtualManifest {
567 replace,
568 patch,
569 workspace,
570 profiles,
571 warnings: Warnings::new(),
572 features,
573 }
574 }
575
576 pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] {
577 &self.replace
578 }
579
580 pub fn patch(&self) -> &HashMap<Url, Vec<Dependency>> {
581 &self.patch
582 }
583
584 pub fn workspace_config(&self) -> &WorkspaceConfig {
585 &self.workspace
586 }
587
588 pub fn profiles(&self) -> &Profiles {
589 &self.profiles
590 }
591
592 pub fn warnings_mut(&mut self) -> &mut Warnings {
593 &mut self.warnings
594 }
595
596 pub fn warnings(&self) -> &Warnings {
597 &self.warnings
598 }
599
600 pub fn features(&self) -> &Features {
601 &self.features
602 }
603 }
604
605 impl Target {
606 fn new(src_path: TargetSourcePath, edition: Edition) -> Target {
607 Target {
608 kind: TargetKind::Bin,
609 name: String::new(),
610 src_path,
611 required_features: None,
612 doc: false,
613 doctest: false,
614 harness: true,
615 for_host: false,
616 proc_macro: false,
617 edition,
618 tested: true,
619 benched: true,
620 }
621 }
622
623 fn with_path(src_path: PathBuf, edition: Edition) -> Target {
624 Target::new(TargetSourcePath::from(src_path), edition)
625 }
626
627 pub fn lib_target(
628 name: &str,
629 crate_targets: Vec<LibKind>,
630 src_path: PathBuf,
631 edition: Edition,
632 ) -> Target {
633 Target {
634 kind: TargetKind::Lib(crate_targets),
635 name: name.to_string(),
636 doctest: true,
637 doc: true,
638 ..Target::with_path(src_path, edition)
639 }
640 }
641
642 pub fn bin_target(
643 name: &str,
644 src_path: PathBuf,
645 required_features: Option<Vec<String>>,
646 edition: Edition,
647 ) -> Target {
648 Target {
649 kind: TargetKind::Bin,
650 name: name.to_string(),
651 required_features,
652 doc: true,
653 ..Target::with_path(src_path, edition)
654 }
655 }
656
657 /// Builds a `Target` corresponding to the `build = "build.rs"` entry.
658 pub fn custom_build_target(name: &str, src_path: PathBuf, edition: Edition) -> Target {
659 Target {
660 kind: TargetKind::CustomBuild,
661 name: name.to_string(),
662 for_host: true,
663 benched: false,
664 tested: false,
665 ..Target::with_path(src_path, edition)
666 }
667 }
668
669 pub fn metabuild_target(name: &str) -> Target {
670 Target {
671 kind: TargetKind::CustomBuild,
672 name: name.to_string(),
673 for_host: true,
674 benched: false,
675 tested: false,
676 ..Target::new(TargetSourcePath::Metabuild, Edition::Edition2018)
677 }
678 }
679
680 pub fn example_target(
681 name: &str,
682 crate_targets: Vec<LibKind>,
683 src_path: PathBuf,
684 required_features: Option<Vec<String>>,
685 edition: Edition,
686 ) -> Target {
687 let kind = if crate_targets.is_empty()
688 || crate_targets
689 .iter()
690 .all(|t| *t == LibKind::Other("bin".into()))
691 {
692 TargetKind::ExampleBin
693 } else {
694 TargetKind::ExampleLib(crate_targets)
695 };
696
697 Target {
698 kind,
699 name: name.to_string(),
700 required_features,
701 tested: false,
702 benched: false,
703 ..Target::with_path(src_path, edition)
704 }
705 }
706
707 pub fn test_target(
708 name: &str,
709 src_path: PathBuf,
710 required_features: Option<Vec<String>>,
711 edition: Edition,
712 ) -> Target {
713 Target {
714 kind: TargetKind::Test,
715 name: name.to_string(),
716 required_features,
717 benched: false,
718 ..Target::with_path(src_path, edition)
719 }
720 }
721
722 pub fn bench_target(
723 name: &str,
724 src_path: PathBuf,
725 required_features: Option<Vec<String>>,
726 edition: Edition,
727 ) -> Target {
728 Target {
729 kind: TargetKind::Bench,
730 name: name.to_string(),
731 required_features,
732 tested: false,
733 ..Target::with_path(src_path, edition)
734 }
735 }
736
737 pub fn name(&self) -> &str {
738 &self.name
739 }
740 pub fn crate_name(&self) -> String {
741 self.name.replace("-", "_")
742 }
743 pub fn src_path(&self) -> &TargetSourcePath {
744 &self.src_path
745 }
746 pub fn set_src_path(&mut self, src_path: TargetSourcePath) {
747 self.src_path = src_path;
748 }
749 pub fn required_features(&self) -> Option<&Vec<String>> {
750 self.required_features.as_ref()
751 }
752 pub fn kind(&self) -> &TargetKind {
753 &self.kind
754 }
755 pub fn tested(&self) -> bool {
756 self.tested
757 }
758 pub fn harness(&self) -> bool {
759 self.harness
760 }
761 pub fn documented(&self) -> bool {
762 self.doc
763 }
764 pub fn for_host(&self) -> bool {
765 self.for_host
766 }
767 pub fn proc_macro(&self) -> bool {
768 self.proc_macro
769 }
770 pub fn edition(&self) -> Edition {
771 self.edition
772 }
773 pub fn benched(&self) -> bool {
774 self.benched
775 }
776 pub fn doctested(&self) -> bool {
777 self.doctest
778 }
779
780 pub fn doctestable(&self) -> bool {
781 match self.kind {
782 TargetKind::Lib(ref kinds) => kinds
783 .iter()
784 .any(|k| *k == LibKind::Rlib || *k == LibKind::Lib || *k == LibKind::ProcMacro),
785 _ => false,
786 }
787 }
788
789 pub fn allows_underscores(&self) -> bool {
790 self.is_bin() || self.is_example() || self.is_custom_build()
791 }
792
793 pub fn is_lib(&self) -> bool {
794 match self.kind {
795 TargetKind::Lib(_) => true,
796 _ => false,
797 }
798 }
799
800 pub fn is_dylib(&self) -> bool {
801 match self.kind {
802 TargetKind::Lib(ref libs) => libs.iter().any(|l| *l == LibKind::Dylib),
803 _ => false,
804 }
805 }
806
807 pub fn is_cdylib(&self) -> bool {
808 let libs = match self.kind {
809 TargetKind::Lib(ref libs) => libs,
810 _ => return false,
811 };
812 libs.iter().any(|l| match *l {
813 LibKind::Other(ref s) => s == "cdylib",
814 _ => false,
815 })
816 }
817
818 /// Returns whether this target produces an artifact which can be linked
819 /// into a Rust crate.
820 ///
821 /// This only returns true for certain kinds of libraries.
822 pub fn linkable(&self) -> bool {
823 match self.kind {
824 TargetKind::Lib(ref kinds) => kinds.iter().any(|k| k.linkable()),
825 _ => false,
826 }
827 }
828
829 pub fn is_bin(&self) -> bool {
830 self.kind == TargetKind::Bin
831 }
832
833 pub fn is_example(&self) -> bool {
834 match self.kind {
835 TargetKind::ExampleBin | TargetKind::ExampleLib(..) => true,
836 _ => false,
837 }
838 }
839
840 /// Returns `true` if it is a binary or executable example.
841 /// NOTE: Tests are `false`!
842 pub fn is_executable(&self) -> bool {
843 self.is_bin() || self.is_exe_example()
844 }
845
846 /// Returns `true` if it is an executable example.
847 pub fn is_exe_example(&self) -> bool {
848 // Needed for --all-examples in contexts where only runnable examples make sense
849 match self.kind {
850 TargetKind::ExampleBin => true,
851 _ => false,
852 }
853 }
854
855 pub fn is_test(&self) -> bool {
856 self.kind == TargetKind::Test
857 }
858 pub fn is_bench(&self) -> bool {
859 self.kind == TargetKind::Bench
860 }
861 pub fn is_custom_build(&self) -> bool {
862 self.kind == TargetKind::CustomBuild
863 }
864
865 /// Returns the arguments suitable for `--crate-type` to pass to rustc.
866 pub fn rustc_crate_types(&self) -> Vec<&str> {
867 match self.kind {
868 TargetKind::Lib(ref kinds) | TargetKind::ExampleLib(ref kinds) => {
869 kinds.iter().map(LibKind::crate_type).collect()
870 }
871 TargetKind::CustomBuild
872 | TargetKind::Bench
873 | TargetKind::Test
874 | TargetKind::ExampleBin
875 | TargetKind::Bin => vec!["bin"],
876 }
877 }
878
879 pub fn can_lto(&self) -> bool {
880 match self.kind {
881 TargetKind::Lib(ref v) => {
882 !v.contains(&LibKind::Rlib)
883 && !v.contains(&LibKind::Dylib)
884 && !v.contains(&LibKind::Lib)
885 }
886 _ => true,
887 }
888 }
889
890 pub fn set_tested(&mut self, tested: bool) -> &mut Target {
891 self.tested = tested;
892 self
893 }
894 pub fn set_benched(&mut self, benched: bool) -> &mut Target {
895 self.benched = benched;
896 self
897 }
898 pub fn set_doctest(&mut self, doctest: bool) -> &mut Target {
899 self.doctest = doctest;
900 self
901 }
902 pub fn set_for_host(&mut self, for_host: bool) -> &mut Target {
903 self.for_host = for_host;
904 self
905 }
906 pub fn set_proc_macro(&mut self, proc_macro: bool) -> &mut Target {
907 self.proc_macro = proc_macro;
908 self
909 }
910 pub fn set_edition(&mut self, edition: Edition) -> &mut Target {
911 self.edition = edition;
912 self
913 }
914 pub fn set_harness(&mut self, harness: bool) -> &mut Target {
915 self.harness = harness;
916 self
917 }
918 pub fn set_doc(&mut self, doc: bool) -> &mut Target {
919 self.doc = doc;
920 self
921 }
922 }
923
924 impl fmt::Display for Target {
925 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
926 match self.kind {
927 TargetKind::Lib(..) => write!(f, "Target(lib)"),
928 TargetKind::Bin => write!(f, "Target(bin: {})", self.name),
929 TargetKind::Test => write!(f, "Target(test: {})", self.name),
930 TargetKind::Bench => write!(f, "Target(bench: {})", self.name),
931 TargetKind::ExampleBin | TargetKind::ExampleLib(..) => {
932 write!(f, "Target(example: {})", self.name)
933 }
934 TargetKind::CustomBuild => write!(f, "Target(script)"),
935 }
936 }
937 }
938
939 impl Warnings {
940 fn new() -> Warnings {
941 Warnings(Vec::new())
942 }
943
944 pub fn add_warning(&mut self, s: String) {
945 self.0.push(DelayedWarning {
946 message: s,
947 is_critical: false,
948 })
949 }
950
951 pub fn add_critical_warning(&mut self, s: String) {
952 self.0.push(DelayedWarning {
953 message: s,
954 is_critical: true,
955 })
956 }
957
958 pub fn warnings(&self) -> &[DelayedWarning] {
959 &self.0
960 }
961 }