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