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