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