1use crate::util::data_structures::HashMap;
2use std::borrow::Cow;
3use std::collections::BTreeMap;
4use std::fmt;
5use std::hash::{Hash, Hasher};
6use std::path::{Path, PathBuf};
7use std::rc::Rc;
8use std::sync::Arc;
9
10use anyhow::Context as _;
11use cargo_util_schemas::manifest::RustVersion;
12use cargo_util_schemas::manifest::{Hints, TomlManifest, TomlProfiles};
13use semver::Version;
14use serde::Serialize;
15use serde::ser;
16use url::Url;
17
18use crate::core::compiler::rustdoc::RustdocScrapeExamples;
19use crate::core::compiler::{CompileKind, CrateType};
20use crate::core::resolver::ResolveBehavior;
21use crate::core::{Dependency, PackageId, PackageIdSpec, Patch, SourceId, Summary};
22use crate::core::{Edition, Feature, Features, WorkspaceConfig};
23use crate::util::errors::*;
24use crate::util::interning::InternedString;
25use crate::util::{Filesystem, GlobalContext, short_hash};
26
27pub const MANIFEST_PREAMBLE: &str = "\
28# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
29#
30# When uploading crates to the registry Cargo will automatically
31# \"normalize\" Cargo.toml files for maximal compatibility
32# with all versions of Cargo and also rewrite `path` dependencies
33# to registry (e.g., crates.io) dependencies.
34#
35# If you are reading this file be aware that the original Cargo.toml
36# will likely look very different (and much more reasonable).
37# See Cargo.toml.orig for the original contents.
38";
39
40pub enum EitherManifest {
41 Real(Manifest),
42 Virtual(VirtualManifest),
43}
44
45impl EitherManifest {
46 pub fn warnings_mut(&mut self) -> &mut Warnings {
47 match self {
48 EitherManifest::Real(r) => r.warnings_mut(),
49 EitherManifest::Virtual(v) => v.warnings_mut(),
50 }
51 }
52 pub(crate) fn workspace_config(&self) -> &WorkspaceConfig {
53 match *self {
54 EitherManifest::Real(ref r) => r.workspace_config(),
55 EitherManifest::Virtual(ref v) => v.workspace_config(),
56 }
57 }
58}
59
60#[derive(Clone, Debug)]
64pub struct Manifest {
65 contents: Option<Rc<String>>,
67 document: Option<Arc<toml::Spanned<toml::de::DeTable<'static>>>>,
68 original_toml: Option<Rc<TomlManifest>>,
69 normalized_toml: Rc<TomlManifest>,
70 summary: Summary,
71
72 targets: Vec<Target>,
74 default_kind: Option<CompileKind>,
75 forced_kind: Option<CompileKind>,
76 links: Option<String>,
77 warnings: Warnings,
78 exclude: Vec<String>,
79 include: Vec<String>,
80 metadata: ManifestMetadata,
81 custom_metadata: Option<toml::Value>,
82 publish: Option<Vec<String>>,
83 replace: Vec<(PackageIdSpec, Dependency)>,
84 patch: HashMap<Url, Vec<Patch>>,
85 workspace: WorkspaceConfig,
86 unstable_features: Features,
87 edition: Edition,
88 rust_version: Option<RustVersion>,
89 im_a_teapot: Option<bool>,
90 default_run: Option<String>,
91 metabuild: Option<Vec<String>>,
92 resolve_behavior: Option<ResolveBehavior>,
93 lint_rustflags: Vec<String>,
94 hints: Option<Hints>,
95 embedded: bool,
96}
97
98#[derive(Clone, Debug)]
102pub struct DelayedWarning {
103 pub message: String,
104 pub is_critical: bool,
105}
106
107#[derive(Clone, Debug)]
108pub struct Warnings(Vec<DelayedWarning>);
109
110#[derive(Clone, Debug)]
111pub struct VirtualManifest {
112 contents: Option<Rc<String>>,
114 document: Option<Rc<toml::Spanned<toml::de::DeTable<'static>>>>,
115 original_toml: Option<Rc<TomlManifest>>,
116 normalized_toml: Rc<TomlManifest>,
117
118 replace: Vec<(PackageIdSpec, Dependency)>,
120 patch: HashMap<Url, Vec<Patch>>,
121 workspace: WorkspaceConfig,
122 warnings: Warnings,
123 features: Features,
124 resolve_behavior: Option<ResolveBehavior>,
125}
126
127#[derive(PartialEq, Clone, Debug)]
136pub struct ManifestMetadata {
137 pub authors: Vec<String>,
138 pub keywords: Vec<String>,
139 pub categories: Vec<String>,
140 pub license: Option<String>,
141 pub license_file: Option<String>,
142 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>>,
148 pub links: Option<String>,
149 pub rust_version: Option<RustVersion>,
150}
151
152impl ManifestMetadata {
153 pub fn should_track(env_key: &str) -> bool {
155 let keys = MetadataEnvs::keys();
156 keys.contains(&env_key)
157 }
158
159 pub fn env_var<'a>(&'a self, env_key: &str) -> Option<Cow<'a, str>> {
160 MetadataEnvs::var(self, env_key)
161 }
162
163 pub fn env_vars(&self) -> impl Iterator<Item = (&'static str, Cow<'_, str>)> {
164 MetadataEnvs::keys()
165 .iter()
166 .map(|k| (*k, MetadataEnvs::var(self, k).unwrap()))
167 }
168}
169
170macro_rules! get_metadata_env {
171 ($meta:ident, $field:ident) => {
172 $meta.$field.as_deref().unwrap_or_default().into()
173 };
174 ($meta:ident, $field:ident, $to_var:expr) => {
175 $to_var($meta).into()
176 };
177}
178
179struct MetadataEnvs;
180
181macro_rules! metadata_envs {
182 (
183 $(
184 ($field:ident, $key:literal$(, $to_var:expr)?),
185 )*
186 ) => {
187 impl MetadataEnvs {
188 fn keys() -> &'static [&'static str] {
189 &[$($key),*]
190 }
191
192 fn var<'a>(meta: &'a ManifestMetadata, key: &str) -> Option<Cow<'a, str>> {
193 match key {
194 $($key => Some(get_metadata_env!(meta, $field$(, $to_var)?)),)*
195 _ => None,
196 }
197 }
198 }
199 }
200}
201
202metadata_envs! {
206 (description, "CARGO_PKG_DESCRIPTION"),
207 (homepage, "CARGO_PKG_HOMEPAGE"),
208 (repository, "CARGO_PKG_REPOSITORY"),
209 (license, "CARGO_PKG_LICENSE"),
210 (license_file, "CARGO_PKG_LICENSE_FILE"),
211 (authors, "CARGO_PKG_AUTHORS", |m: &ManifestMetadata| m.authors.join(":")),
212 (rust_version, "CARGO_PKG_RUST_VERSION", |m: &ManifestMetadata| m.rust_version.as_ref().map(ToString::to_string).unwrap_or_default()),
213 (readme, "CARGO_PKG_README"),
214}
215
216#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
217pub enum TargetKind {
218 Lib(Vec<CrateType>),
219 Bin,
220 Test,
221 Bench,
222 ExampleLib(Vec<CrateType>),
223 ExampleBin,
224 CustomBuild,
225}
226
227impl ser::Serialize for TargetKind {
228 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
229 where
230 S: ser::Serializer,
231 {
232 use self::TargetKind::*;
233 match self {
234 Lib(kinds) => s.collect_seq(kinds.iter().map(|t| t.to_string())),
235 Bin => ["bin"].serialize(s),
236 ExampleBin | ExampleLib(_) => ["example"].serialize(s),
237 Test => ["test"].serialize(s),
238 CustomBuild => ["custom-build"].serialize(s),
239 Bench => ["bench"].serialize(s),
240 }
241 }
242}
243
244impl fmt::Debug for TargetKind {
245 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246 use self::TargetKind::*;
247 match *self {
248 Lib(ref kinds) => kinds.fmt(f),
249 Bin => "bin".fmt(f),
250 ExampleBin | ExampleLib(_) => "example".fmt(f),
251 Test => "test".fmt(f),
252 CustomBuild => "custom-build".fmt(f),
253 Bench => "bench".fmt(f),
254 }
255 }
256}
257
258impl TargetKind {
259 pub fn description(&self) -> &'static str {
260 match self {
261 TargetKind::Lib(..) => "lib",
262 TargetKind::Bin => "bin",
263 TargetKind::Test => "integration-test",
264 TargetKind::ExampleBin | TargetKind::ExampleLib(..) => "example",
265 TargetKind::Bench => "bench",
266 TargetKind::CustomBuild => "build-script",
267 }
268 }
269
270 pub fn requires_upstream_objects(&self) -> bool {
276 match self {
277 TargetKind::Lib(kinds) | TargetKind::ExampleLib(kinds) => {
278 kinds.iter().any(|k| k.requires_upstream_objects())
279 }
280 _ => true,
281 }
282 }
283
284 pub fn benefits_from_no_embed_metadata(&self) -> bool {
287 match self {
288 TargetKind::Lib(kinds) | TargetKind::ExampleLib(kinds) => {
289 kinds.iter().any(|k| k.benefits_from_no_embed_metadata())
290 }
291 _ => false,
292 }
293 }
294
295 pub fn rustc_crate_types(&self) -> Vec<CrateType> {
297 match self {
298 TargetKind::Lib(kinds) | TargetKind::ExampleLib(kinds) => kinds.clone(),
299 TargetKind::CustomBuild
300 | TargetKind::Bench
301 | TargetKind::Test
302 | TargetKind::ExampleBin
303 | TargetKind::Bin => vec![CrateType::Bin],
304 }
305 }
306}
307
308#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
311pub struct Target {
312 inner: Arc<TargetInner>,
313}
314
315#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
316struct TargetInner {
317 kind: TargetKind,
318 name: String,
319 name_inferred: bool,
321 bin_name: Option<String>,
323 src_path: TargetSourcePath,
328 required_features: Option<Vec<String>>,
329 tested: bool,
330 benched: bool,
331 doc: bool,
332 doctest: bool,
333 harness: bool, for_host: bool,
335 proc_macro: bool,
336 edition: Edition,
337 doc_scrape_examples: RustdocScrapeExamples,
338}
339
340#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
341pub enum TargetSourcePath {
342 Path(PathBuf),
343 Metabuild,
344}
345
346impl TargetSourcePath {
347 pub fn path(&self) -> Option<&Path> {
348 match self {
349 TargetSourcePath::Path(path) => Some(path.as_ref()),
350 TargetSourcePath::Metabuild => None,
351 }
352 }
353
354 pub fn is_path(&self) -> bool {
355 matches!(self, TargetSourcePath::Path(_))
356 }
357}
358
359impl Hash for TargetSourcePath {
360 fn hash<H: Hasher>(&self, _: &mut H) {
361 }
363}
364
365impl fmt::Debug for TargetSourcePath {
366 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
367 match self {
368 TargetSourcePath::Path(path) => path.fmt(f),
369 TargetSourcePath::Metabuild => "metabuild".fmt(f),
370 }
371 }
372}
373
374impl From<PathBuf> for TargetSourcePath {
375 fn from(path: PathBuf) -> Self {
376 assert!(path.is_absolute(), "`{}` is not absolute", path.display());
377 TargetSourcePath::Path(path)
378 }
379}
380
381#[derive(Serialize)]
382struct SerializedTarget<'a> {
383 kind: &'a TargetKind,
386 crate_types: Vec<CrateType>,
389 name: &'a str,
390 src_path: Option<&'a PathBuf>,
391 edition: &'a str,
392 #[serde(rename = "required-features", skip_serializing_if = "Option::is_none")]
393 required_features: Option<Vec<&'a str>>,
394 doc: bool,
397 doctest: bool,
398 test: bool,
400}
401
402impl ser::Serialize for Target {
403 fn serialize<S: ser::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
404 let src_path = match self.src_path() {
405 TargetSourcePath::Path(p) => Some(p),
406 TargetSourcePath::Metabuild => None,
409 };
410 SerializedTarget {
411 kind: self.kind(),
412 crate_types: self.rustc_crate_types(),
413 name: self.name(),
414 src_path,
415 edition: &self.edition().to_string(),
416 required_features: self
417 .required_features()
418 .map(|rf| rf.iter().map(|s| s.as_str()).collect()),
419 doc: self.documented(),
420 doctest: self.doctested() && self.doctestable(),
421 test: self.tested(),
422 }
423 .serialize(s)
424 }
425}
426
427impl fmt::Debug for Target {
428 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
429 self.inner.fmt(f)
430 }
431}
432
433compact_debug! {
434 impl fmt::Debug for TargetInner {
435 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
436 let (default, default_name) = {
437 match &self.kind {
438 TargetKind::Lib(kinds) => {
439 (
440 Target::lib_target(
441 &self.name,
442 kinds.clone(),
443 self.src_path.path().unwrap().to_path_buf(),
444 self.edition,
445 ).inner,
446 format!("lib_target({:?}, {:?}, {:?}, {:?})",
447 self.name, kinds, self.src_path, self.edition),
448 )
449 }
450 TargetKind::CustomBuild => {
451 match self.src_path {
452 TargetSourcePath::Path(ref path) => {
453 (
454 Target::custom_build_target(
455 &self.name,
456 path.to_path_buf(),
457 self.edition,
458 ).inner,
459 format!("custom_build_target({:?}, {:?}, {:?})",
460 self.name, path, self.edition),
461 )
462 }
463 TargetSourcePath::Metabuild => {
464 (
465 Target::metabuild_target(&self.name).inner,
466 format!("metabuild_target({:?})", self.name),
467 )
468 }
469 }
470 }
471 _ => (
472 Target::new(self.src_path.clone(), self.edition).inner,
473 format!("with_path({:?}, {:?})", self.src_path, self.edition),
474 ),
475 }
476 };
477 [debug_the_fields(
478 kind
479 name
480 name_inferred
481 bin_name
482 src_path
483 required_features
484 tested
485 benched
486 doc
487 doctest
488 harness
489 for_host
490 proc_macro
491 edition
492 doc_scrape_examples
493 )]
494 }
495 }
496}
497
498impl Manifest {
499 pub fn new(
500 contents: Option<Rc<String>>,
501 document: Option<Arc<toml::Spanned<toml::de::DeTable<'static>>>>,
502 original_toml: Option<Rc<TomlManifest>>,
503 normalized_toml: Rc<TomlManifest>,
504 summary: Summary,
505
506 default_kind: Option<CompileKind>,
507 forced_kind: Option<CompileKind>,
508 targets: Vec<Target>,
509 exclude: Vec<String>,
510 include: Vec<String>,
511 links: Option<String>,
512 metadata: ManifestMetadata,
513 custom_metadata: Option<toml::Value>,
514 publish: Option<Vec<String>>,
515 replace: Vec<(PackageIdSpec, Dependency)>,
516 patch: HashMap<Url, Vec<Patch>>,
517 workspace: WorkspaceConfig,
518 unstable_features: Features,
519 edition: Edition,
520 rust_version: Option<RustVersion>,
521 im_a_teapot: Option<bool>,
522 default_run: Option<String>,
523 metabuild: Option<Vec<String>>,
524 resolve_behavior: Option<ResolveBehavior>,
525 lint_rustflags: Vec<String>,
526 hints: Option<Hints>,
527 embedded: bool,
528 ) -> Manifest {
529 Manifest {
530 contents,
531 document,
532 original_toml,
533 normalized_toml,
534 summary,
535
536 default_kind,
537 forced_kind,
538 targets,
539 warnings: Warnings::new(),
540 exclude,
541 include,
542 links,
543 metadata,
544 custom_metadata,
545 publish,
546 replace,
547 patch,
548 workspace,
549 unstable_features,
550 edition,
551 rust_version,
552 im_a_teapot,
553 default_run,
554 metabuild,
555 resolve_behavior,
556 lint_rustflags,
557 hints,
558 embedded,
559 }
560 }
561
562 pub fn contents(&self) -> Option<&str> {
564 self.contents.as_deref().map(|c| c.as_str())
565 }
566 pub fn to_normalized_contents(&self) -> CargoResult<String> {
568 let toml = toml::to_string_pretty(self.normalized_toml())?;
569 Ok(format!("{}\n{}", MANIFEST_PREAMBLE, toml))
570 }
571 pub fn document(&self) -> Option<&toml::Spanned<toml::de::DeTable<'static>>> {
573 self.document.as_deref()
574 }
575
576 pub fn document_rc(&self) -> Option<Arc<toml::Spanned<toml::de::DeTable<'static>>>> {
578 self.document.clone()
579 }
580
581 pub fn original_toml(&self) -> Option<&TomlManifest> {
583 self.original_toml.as_deref()
584 }
585 pub fn normalized_toml(&self) -> &TomlManifest {
592 &self.normalized_toml
593 }
594 pub fn summary(&self) -> &Summary {
595 &self.summary
596 }
597 pub fn summary_mut(&mut self) -> &mut Summary {
598 &mut self.summary
599 }
600
601 pub fn dependencies(&self) -> &[Dependency] {
602 self.summary.dependencies()
603 }
604 pub fn default_kind(&self) -> Option<CompileKind> {
605 self.default_kind
606 }
607 pub fn forced_kind(&self) -> Option<CompileKind> {
608 self.forced_kind
609 }
610 pub fn exclude(&self) -> &[String] {
611 &self.exclude
612 }
613 pub fn include(&self) -> &[String] {
614 &self.include
615 }
616 pub fn metadata(&self) -> &ManifestMetadata {
617 &self.metadata
618 }
619 pub fn name(&self) -> InternedString {
620 self.package_id().name()
621 }
622 pub fn package_id(&self) -> PackageId {
623 self.summary.package_id()
624 }
625 pub fn targets(&self) -> &[Target] {
626 &self.targets
627 }
628 pub fn targets_mut(&mut self) -> &mut [Target] {
630 &mut self.targets
631 }
632 pub fn version(&self) -> &Version {
633 self.package_id().version()
634 }
635 pub fn warnings_mut(&mut self) -> &mut Warnings {
636 &mut self.warnings
637 }
638 pub fn warnings(&self) -> &Warnings {
639 &self.warnings
640 }
641 pub fn profiles(&self) -> Option<&TomlProfiles> {
642 self.normalized_toml.profile.as_ref()
643 }
644 pub fn publish(&self) -> &Option<Vec<String>> {
645 &self.publish
646 }
647 pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] {
648 &self.replace
649 }
650 pub fn patch(&self) -> &HashMap<Url, Vec<Patch>> {
651 &self.patch
652 }
653 pub fn links(&self) -> Option<&str> {
654 self.links.as_deref()
655 }
656 pub fn is_embedded(&self) -> bool {
657 self.embedded
658 }
659
660 pub fn workspace_config(&self) -> &WorkspaceConfig {
661 &self.workspace
662 }
663
664 pub fn unstable_features(&self) -> &Features {
666 &self.unstable_features
667 }
668
669 pub fn resolve_behavior(&self) -> Option<ResolveBehavior> {
673 self.resolve_behavior
674 }
675
676 pub fn lint_rustflags(&self) -> &[String] {
678 self.lint_rustflags.as_slice()
679 }
680
681 pub fn hints(&self) -> Option<&Hints> {
682 self.hints.as_ref()
683 }
684
685 pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Manifest {
686 Manifest {
687 summary: self.summary.map_source(to_replace, replace_with),
688 ..self
689 }
690 }
691
692 pub fn feature_gate(&self) -> CargoResult<()> {
693 if self.im_a_teapot.is_some() {
694 self.unstable_features
695 .require(Feature::test_dummy_unstable())
696 .with_context(|| {
697 "the `im-a-teapot` manifest key is unstable and may \
698 not work properly in England"
699 })?;
700 }
701
702 if self.default_kind.is_some() || self.forced_kind.is_some() {
703 self.unstable_features
704 .require(Feature::per_package_target())
705 .with_context(|| {
706 "the `package.default-target` and `package.forced-target` \
707 manifest keys are unstable and may not work properly"
708 })?;
709 }
710
711 Ok(())
712 }
713
714 pub fn print_teapot(&self, gctx: &GlobalContext) {
716 if let Some(teapot) = self.im_a_teapot {
717 if gctx.cli_unstable().print_im_a_teapot {
718 crate::drop_println!(gctx, "im-a-teapot = {}", teapot);
719 }
720 }
721 }
722
723 pub fn edition(&self) -> Edition {
724 self.edition
725 }
726
727 pub fn rust_version(&self) -> Option<&RustVersion> {
728 self.rust_version.as_ref()
729 }
730
731 pub fn custom_metadata(&self) -> Option<&toml::Value> {
732 self.custom_metadata.as_ref()
733 }
734
735 pub fn default_run(&self) -> Option<&str> {
736 self.default_run.as_deref()
737 }
738
739 pub fn metabuild(&self) -> Option<&Vec<String>> {
740 self.metabuild.as_ref()
741 }
742
743 pub fn metabuild_path(&self, target_dir: Filesystem) -> PathBuf {
744 let hash = short_hash(&self.package_id());
745 target_dir
746 .into_path_unlocked()
747 .join(".metabuild")
748 .join(format!("metabuild-{}-{}.rs", self.name(), hash))
749 }
750}
751
752impl VirtualManifest {
753 pub fn new(
754 contents: Option<Rc<String>>,
755 document: Option<Rc<toml::Spanned<toml::de::DeTable<'static>>>>,
756 original_toml: Option<Rc<TomlManifest>>,
757 normalized_toml: Rc<TomlManifest>,
758 replace: Vec<(PackageIdSpec, Dependency)>,
759 patch: HashMap<Url, Vec<Patch>>,
760 workspace: WorkspaceConfig,
761 features: Features,
762 resolve_behavior: Option<ResolveBehavior>,
763 ) -> VirtualManifest {
764 VirtualManifest {
765 contents,
766 document,
767 original_toml,
768 normalized_toml,
769 replace,
770 patch,
771 workspace,
772 warnings: Warnings::new(),
773 features,
774 resolve_behavior,
775 }
776 }
777
778 pub fn contents(&self) -> Option<&str> {
780 self.contents.as_deref().map(|c| c.as_str())
781 }
782 pub fn document(&self) -> Option<&toml::Spanned<toml::de::DeTable<'static>>> {
784 self.document.as_deref()
785 }
786 pub fn original_toml(&self) -> Option<&TomlManifest> {
788 self.original_toml.as_deref()
789 }
790 pub fn normalized_toml(&self) -> &TomlManifest {
792 &self.normalized_toml
793 }
794
795 pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] {
796 &self.replace
797 }
798
799 pub fn patch(&self) -> &HashMap<Url, Vec<Patch>> {
800 &self.patch
801 }
802
803 pub fn workspace_config(&self) -> &WorkspaceConfig {
804 &self.workspace
805 }
806
807 pub fn profiles(&self) -> Option<&TomlProfiles> {
808 self.normalized_toml.profile.as_ref()
809 }
810
811 pub fn warnings_mut(&mut self) -> &mut Warnings {
812 &mut self.warnings
813 }
814
815 pub fn warnings(&self) -> &Warnings {
816 &self.warnings
817 }
818
819 pub fn unstable_features(&self) -> &Features {
820 &self.features
821 }
822
823 pub fn resolve_behavior(&self) -> Option<ResolveBehavior> {
827 self.resolve_behavior
828 }
829}
830
831impl Target {
832 fn new(src_path: TargetSourcePath, edition: Edition) -> Target {
833 Target {
834 inner: Arc::new(TargetInner {
835 kind: TargetKind::Bin,
836 name: String::new(),
837 name_inferred: false,
838 bin_name: None,
839 src_path,
840 required_features: None,
841 doc: false,
842 doctest: false,
843 harness: true,
844 for_host: false,
845 proc_macro: false,
846 doc_scrape_examples: RustdocScrapeExamples::Unset,
847 edition,
848 tested: true,
849 benched: true,
850 }),
851 }
852 }
853
854 fn with_path(src_path: PathBuf, edition: Edition) -> Target {
855 Target::new(TargetSourcePath::from(src_path), edition)
856 }
857
858 pub fn lib_target(
859 name: &str,
860 crate_targets: Vec<CrateType>,
861 src_path: PathBuf,
862 edition: Edition,
863 ) -> Target {
864 let mut target = Target::with_path(src_path, edition);
865 target
866 .set_kind(TargetKind::Lib(crate_targets))
867 .set_name(name)
868 .set_doctest(true)
869 .set_doc(true);
870 target
871 }
872
873 pub fn bin_target(
874 name: &str,
875 bin_name: Option<String>,
876 src_path: PathBuf,
877 required_features: Option<Vec<String>>,
878 edition: Edition,
879 ) -> Target {
880 let mut target = Target::with_path(src_path, edition);
881 target
882 .set_kind(TargetKind::Bin)
883 .set_name(name)
884 .set_binary_name(bin_name)
885 .set_required_features(required_features)
886 .set_doc(true);
887 target
888 }
889
890 pub fn custom_build_target(name: &str, src_path: PathBuf, edition: Edition) -> Target {
892 let mut target = Target::with_path(src_path, edition);
893 target
894 .set_kind(TargetKind::CustomBuild)
895 .set_name(name)
896 .set_for_host(true)
897 .set_benched(false)
898 .set_tested(false)
899 .set_doc_scrape_examples(RustdocScrapeExamples::Disabled);
900 target
901 }
902
903 pub fn metabuild_target(name: &str) -> Target {
904 let mut target = Target::new(TargetSourcePath::Metabuild, Edition::Edition2018);
905 target
906 .set_kind(TargetKind::CustomBuild)
907 .set_name(name)
908 .set_for_host(true)
909 .set_benched(false)
910 .set_tested(false)
911 .set_doc_scrape_examples(RustdocScrapeExamples::Disabled);
912 target
913 }
914
915 pub fn example_target(
916 name: &str,
917 crate_targets: Vec<CrateType>,
918 src_path: PathBuf,
919 required_features: Option<Vec<String>>,
920 edition: Edition,
921 ) -> Target {
922 let kind = if crate_targets.is_empty() || crate_targets.iter().all(|t| *t == CrateType::Bin)
923 {
924 TargetKind::ExampleBin
925 } else {
926 TargetKind::ExampleLib(crate_targets)
927 };
928 let mut target = Target::with_path(src_path, edition);
929 target
930 .set_kind(kind)
931 .set_name(name)
932 .set_required_features(required_features)
933 .set_tested(false)
934 .set_benched(false);
935 target
936 }
937
938 pub fn test_target(
939 name: &str,
940 src_path: PathBuf,
941 required_features: Option<Vec<String>>,
942 edition: Edition,
943 ) -> Target {
944 let mut target = Target::with_path(src_path, edition);
945 target
946 .set_kind(TargetKind::Test)
947 .set_name(name)
948 .set_required_features(required_features)
949 .set_benched(false);
950 target
951 }
952
953 pub fn bench_target(
954 name: &str,
955 src_path: PathBuf,
956 required_features: Option<Vec<String>>,
957 edition: Edition,
958 ) -> Target {
959 let mut target = Target::with_path(src_path, edition);
960 target
961 .set_kind(TargetKind::Bench)
962 .set_name(name)
963 .set_required_features(required_features)
964 .set_tested(false);
965 target
966 }
967
968 pub fn name(&self) -> &str {
969 &self.inner.name
970 }
971 pub fn name_inferred(&self) -> bool {
972 self.inner.name_inferred
973 }
974 pub fn crate_name(&self) -> String {
975 self.name().replace("-", "_")
976 }
977 pub fn src_path(&self) -> &TargetSourcePath {
978 &self.inner.src_path
979 }
980 pub fn set_src_path(&mut self, src_path: TargetSourcePath) {
981 Arc::make_mut(&mut self.inner).src_path = src_path;
982 }
983 pub fn required_features(&self) -> Option<&Vec<String>> {
984 self.inner.required_features.as_ref()
985 }
986 pub fn kind(&self) -> &TargetKind {
987 &self.inner.kind
988 }
989 pub fn tested(&self) -> bool {
990 self.inner.tested
991 }
992 pub fn harness(&self) -> bool {
993 self.inner.harness
994 }
995 pub fn documented(&self) -> bool {
996 self.inner.doc
997 }
998 pub fn for_host(&self) -> bool {
1000 self.inner.for_host
1001 }
1002 pub fn proc_macro(&self) -> bool {
1003 self.inner.proc_macro
1004 }
1005 pub fn edition(&self) -> Edition {
1006 self.inner.edition
1007 }
1008 pub fn doc_scrape_examples(&self) -> RustdocScrapeExamples {
1009 self.inner.doc_scrape_examples
1010 }
1011 pub fn benched(&self) -> bool {
1012 self.inner.benched
1013 }
1014 pub fn doctested(&self) -> bool {
1015 self.inner.doctest
1016 }
1017
1018 pub fn doctestable(&self) -> bool {
1019 match self.kind() {
1020 TargetKind::Lib(kinds) => kinds.iter().any(|k| {
1021 *k == CrateType::Rlib || *k == CrateType::Lib || *k == CrateType::ProcMacro
1022 }),
1023 _ => false,
1024 }
1025 }
1026
1027 pub fn is_lib(&self) -> bool {
1028 matches!(self.kind(), TargetKind::Lib(_))
1029 }
1030
1031 pub fn is_dylib(&self) -> bool {
1032 match self.kind() {
1033 TargetKind::Lib(libs) => libs.contains(&CrateType::Dylib),
1034 _ => false,
1035 }
1036 }
1037
1038 pub fn is_cdylib(&self) -> bool {
1039 match self.kind() {
1040 TargetKind::Lib(libs) => libs.contains(&CrateType::Cdylib),
1041 _ => false,
1042 }
1043 }
1044
1045 pub fn is_staticlib(&self) -> bool {
1046 match self.kind() {
1047 TargetKind::Lib(libs) => libs.contains(&CrateType::Staticlib),
1048 _ => false,
1049 }
1050 }
1051
1052 pub fn is_linkable(&self) -> bool {
1057 match self.kind() {
1058 TargetKind::Lib(kinds) => kinds.iter().any(|k| k.is_linkable()),
1059 _ => false,
1060 }
1061 }
1062
1063 pub fn is_bin(&self) -> bool {
1064 *self.kind() == TargetKind::Bin
1065 }
1066
1067 pub fn is_example(&self) -> bool {
1068 matches!(
1069 self.kind(),
1070 TargetKind::ExampleBin | TargetKind::ExampleLib(..)
1071 )
1072 }
1073
1074 pub fn is_executable(&self) -> bool {
1077 self.is_bin() || self.is_exe_example()
1078 }
1079
1080 pub fn is_exe_example(&self) -> bool {
1082 matches!(self.kind(), TargetKind::ExampleBin)
1084 }
1085
1086 pub fn is_test(&self) -> bool {
1087 *self.kind() == TargetKind::Test
1088 }
1089 pub fn is_bench(&self) -> bool {
1090 *self.kind() == TargetKind::Bench
1091 }
1092 pub fn is_custom_build(&self) -> bool {
1093 *self.kind() == TargetKind::CustomBuild
1094 }
1095
1096 pub fn is_compile_time_dependency(&self) -> bool {
1098 self.is_custom_build() || self.proc_macro()
1099 }
1100
1101 pub fn rustc_crate_types(&self) -> Vec<CrateType> {
1103 self.kind().rustc_crate_types()
1104 }
1105
1106 pub fn set_tested(&mut self, tested: bool) -> &mut Target {
1107 Arc::make_mut(&mut self.inner).tested = tested;
1108 self
1109 }
1110 pub fn set_benched(&mut self, benched: bool) -> &mut Target {
1111 Arc::make_mut(&mut self.inner).benched = benched;
1112 self
1113 }
1114 pub fn set_doctest(&mut self, doctest: bool) -> &mut Target {
1115 Arc::make_mut(&mut self.inner).doctest = doctest;
1116 self
1117 }
1118 pub fn set_for_host(&mut self, for_host: bool) -> &mut Target {
1119 Arc::make_mut(&mut self.inner).for_host = for_host;
1120 self
1121 }
1122 pub fn set_proc_macro(&mut self, proc_macro: bool) -> &mut Target {
1123 Arc::make_mut(&mut self.inner).proc_macro = proc_macro;
1124 self
1125 }
1126 pub fn set_edition(&mut self, edition: Edition) -> &mut Target {
1127 Arc::make_mut(&mut self.inner).edition = edition;
1128 self
1129 }
1130 pub fn set_doc_scrape_examples(
1131 &mut self,
1132 doc_scrape_examples: RustdocScrapeExamples,
1133 ) -> &mut Target {
1134 Arc::make_mut(&mut self.inner).doc_scrape_examples = doc_scrape_examples;
1135 self
1136 }
1137 pub fn set_harness(&mut self, harness: bool) -> &mut Target {
1138 Arc::make_mut(&mut self.inner).harness = harness;
1139 self
1140 }
1141 pub fn set_doc(&mut self, doc: bool) -> &mut Target {
1142 Arc::make_mut(&mut self.inner).doc = doc;
1143 self
1144 }
1145 pub fn set_kind(&mut self, kind: TargetKind) -> &mut Target {
1146 Arc::make_mut(&mut self.inner).kind = kind;
1147 self
1148 }
1149 pub fn set_name(&mut self, name: &str) -> &mut Target {
1150 Arc::make_mut(&mut self.inner).name = name.to_string();
1151 self
1152 }
1153 pub fn set_name_inferred(&mut self, inferred: bool) -> &mut Target {
1154 Arc::make_mut(&mut self.inner).name_inferred = inferred;
1155 self
1156 }
1157 pub fn set_binary_name(&mut self, bin_name: Option<String>) -> &mut Target {
1158 Arc::make_mut(&mut self.inner).bin_name = bin_name;
1159 self
1160 }
1161 pub fn set_required_features(&mut self, required_features: Option<Vec<String>>) -> &mut Target {
1162 Arc::make_mut(&mut self.inner).required_features = required_features;
1163 self
1164 }
1165 pub fn binary_filename(&self) -> Option<String> {
1166 self.inner.bin_name.clone()
1167 }
1168 pub fn description_named(&self) -> String {
1169 match self.kind() {
1170 TargetKind::Lib(..) => "lib".to_string(),
1171 TargetKind::Bin => format!("bin \"{}\"", self.name()),
1172 TargetKind::Test => format!("test \"{}\"", self.name()),
1173 TargetKind::Bench => format!("bench \"{}\"", self.name()),
1174 TargetKind::ExampleLib(..) | TargetKind::ExampleBin => {
1175 format!("example \"{}\"", self.name())
1176 }
1177 TargetKind::CustomBuild => "build script".to_string(),
1178 }
1179 }
1180}
1181
1182impl fmt::Display for Target {
1183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1184 match self.kind() {
1185 TargetKind::Lib(..) => write!(f, "Target(lib)"),
1186 TargetKind::Bin => write!(f, "Target(bin: {})", self.name()),
1187 TargetKind::Test => write!(f, "Target(test: {})", self.name()),
1188 TargetKind::Bench => write!(f, "Target(bench: {})", self.name()),
1189 TargetKind::ExampleBin | TargetKind::ExampleLib(..) => {
1190 write!(f, "Target(example: {})", self.name())
1191 }
1192 TargetKind::CustomBuild => write!(f, "Target(script)"),
1193 }
1194 }
1195}
1196
1197impl Warnings {
1198 fn new() -> Warnings {
1199 Warnings(Vec::new())
1200 }
1201
1202 pub fn add_warning(&mut self, s: String) {
1203 self.0.push(DelayedWarning {
1204 message: s,
1205 is_critical: false,
1206 })
1207 }
1208
1209 pub fn add_critical_warning(&mut self, s: String) {
1210 self.0.push(DelayedWarning {
1211 message: s,
1212 is_critical: true,
1213 })
1214 }
1215
1216 pub fn warnings(&self) -> &[DelayedWarning] {
1217 &self.0
1218 }
1219}