1use super::ExtractedCustomPlatform;
5use crate::{
6 cargo_config::{CargoConfigSource, CargoConfigs, DiscoveredConfig},
7 errors::TargetTripleError,
8};
9use bstr::ByteSlice;
10use camino::{Utf8Path, Utf8PathBuf};
11use std::{fmt, process::Command};
12use target_spec::{Platform, TargetFeatures, summaries::PlatformSummary};
13
14#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct TargetTriple {
17 pub platform: Platform,
19
20 pub source: TargetTripleSource,
22
23 pub location: TargetDefinitionLocation,
25}
26
27impl TargetTriple {
28 pub fn deserialize(
31 platform: Option<PlatformSummary>,
32 ) -> Result<Option<TargetTriple>, target_spec::Error> {
33 platform
34 .map(|summary| {
35 let platform = summary.to_platform()?;
36 let location = if platform.is_custom() {
37 TargetDefinitionLocation::MetadataCustom(
38 summary
39 .custom_json
40 .expect("custom platform <=> custom JSON"),
41 )
42 } else {
43 TargetDefinitionLocation::Builtin
44 };
45 Ok(TargetTriple {
46 platform,
47 source: TargetTripleSource::Metadata,
48 location,
49 })
50 })
51 .transpose()
52 }
53
54 pub fn deserialize_str(
56 triple_str: Option<String>,
57 ) -> Result<Option<TargetTriple>, target_spec::Error> {
58 triple_str
59 .map(|triple_str| {
60 Ok(TargetTriple {
61 platform: Platform::new(triple_str, TargetFeatures::Unknown)?,
62 source: TargetTripleSource::Metadata,
63 location: TargetDefinitionLocation::Builtin,
64 })
65 })
66 .transpose()
67 }
68
69 pub fn to_cargo_target_arg(&self) -> Result<CargoTargetArg, TargetTripleError> {
75 match &self.location {
76 TargetDefinitionLocation::Builtin | TargetDefinitionLocation::Heuristic => Ok(
78 CargoTargetArg::Builtin(self.platform.triple_str().to_string()),
79 ),
80 TargetDefinitionLocation::DirectPath(path)
81 | TargetDefinitionLocation::RustTargetPath(path) => {
82 Ok(CargoTargetArg::Path(path.clone()))
83 }
84 TargetDefinitionLocation::MetadataCustom(json) => CargoTargetArg::from_custom_json(
85 self.platform.triple_str(),
86 json,
87 self.source.clone(),
88 ),
89 TargetDefinitionLocation::RustcCfgCustom => Ok(CargoTargetArg::RustcCfg(
90 self.platform.triple_str().to_string(),
91 )),
92 }
93 }
94
95 pub fn find(
106 cargo_configs: &CargoConfigs,
107 target_cli_option: Option<&str>,
108 host_platform: &Platform,
109 ) -> Result<Option<Self>, TargetTripleError> {
110 if let Some(triple_str_or_path) = target_cli_option {
112 let ret = Self::resolve_triple(
113 triple_str_or_path,
114 TargetTripleSource::CliOption,
115 cargo_configs.cwd(),
116 cargo_configs.target_paths(),
117 host_platform,
118 )?;
119 return Ok(Some(ret));
120 }
121
122 Self::from_cargo_configs(cargo_configs, host_platform)
124 }
125
126 pub const CARGO_BUILD_TARGET_ENV: &'static str = "CARGO_BUILD_TARGET";
128
129 fn from_env(
130 cwd: &Utf8Path,
131 target_paths: &[Utf8PathBuf],
132 host_platform: &Platform,
133 ) -> Result<Option<Self>, TargetTripleError> {
134 if let Some(triple_val) = std::env::var_os(Self::CARGO_BUILD_TARGET_ENV) {
135 let triple = triple_val
136 .into_string()
137 .map_err(|_osstr| TargetTripleError::InvalidEnvironmentVar)?;
138 let ret = Self::resolve_triple(
139 &triple,
140 TargetTripleSource::Env,
141 cwd,
142 target_paths,
143 host_platform,
144 )?;
145 Ok(Some(ret))
146 } else {
147 Ok(None)
148 }
149 }
150
151 fn from_cargo_configs(
152 cargo_configs: &CargoConfigs,
153 host_platform: &Platform,
154 ) -> Result<Option<Self>, TargetTripleError> {
155 for discovered_config in cargo_configs.discovered_configs() {
156 match discovered_config {
157 DiscoveredConfig::CliOption { config, source }
158 | DiscoveredConfig::File { config, source } => {
159 if let Some(triple) = &config.build.target {
160 let resolve_dir = source.resolve_dir(cargo_configs.cwd());
161 let source = TargetTripleSource::CargoConfig {
162 source: source.clone(),
163 };
164 let ret = Self::resolve_triple(
165 triple,
166 source,
167 resolve_dir,
168 cargo_configs.target_paths(),
169 host_platform,
170 )?;
171 return Ok(Some(ret));
172 }
173 }
174 DiscoveredConfig::Env => {
175 if let Some(triple) = Self::from_env(
177 cargo_configs.cwd(),
178 cargo_configs.target_paths(),
179 host_platform,
180 )? {
181 return Ok(Some(triple));
182 }
183 }
184 }
185 }
186
187 Ok(None)
188 }
189
190 fn resolve_triple(
194 triple_str_or_path: &str,
195 source: TargetTripleSource,
196 resolve_dir: &Utf8Path,
199 target_paths: &[Utf8PathBuf],
200 host_platform: &Platform,
201 ) -> Result<Self, TargetTripleError> {
202 if triple_str_or_path == "host-tuple" {
204 return Ok(Self {
205 platform: host_platform.clone(),
206 source,
207 location: TargetDefinitionLocation::Builtin,
208 });
209 }
210
211 if triple_str_or_path.ends_with(".json") {
212 return Self::custom_from_path(triple_str_or_path.as_ref(), source, resolve_dir);
213 }
214
215 if let Ok(platform) =
217 Platform::new_strict(triple_str_or_path.to_owned(), TargetFeatures::Unknown)
218 {
219 return Ok(Self {
220 platform,
221 source,
222 location: TargetDefinitionLocation::Builtin,
223 });
224 }
225
226 let triple_filename = {
228 let mut triple_str = triple_str_or_path.to_owned();
229 triple_str.push_str(".json");
230 Utf8PathBuf::from(triple_str)
231 };
232
233 for dir in target_paths {
234 let path = dir.join(&triple_filename);
235 if path.is_file() {
236 let path = path.canonicalize_utf8().map_err(|error| {
237 TargetTripleError::TargetPathReadError {
238 source: source.clone(),
239 path,
240 error,
241 }
242 })?;
243 return Self::load_file(
244 triple_str_or_path,
245 &path,
246 source,
247 TargetDefinitionLocation::RustTargetPath(path.clone()),
248 );
249 }
250 }
251
252 if let Ok(stdout) = Command::new(std::env::var("RUSTC").unwrap_or("rustc".to_owned()))
253 .arg("--print=cfg")
254 .arg("--target")
255 .arg(triple_str_or_path)
256 .output()
257 .map(|out| out.stdout)
258 && let Ok(cfg_text) = stdout.to_str()
259 && let Ok(platform) = Platform::new_custom_cfg(
260 triple_str_or_path.to_owned(),
261 cfg_text,
262 TargetFeatures::Unknown,
263 )
264 {
265 return Ok(Self {
266 platform,
267 source,
268 location: TargetDefinitionLocation::RustcCfgCustom,
269 });
270 }
271
272 let platform = Platform::new(triple_str_or_path.to_owned(), TargetFeatures::Unknown)
278 .map_err(|error| TargetTripleError::TargetSpecError {
279 source: source.clone(),
280 error,
281 })?;
282 Ok(Self {
283 platform,
284 source,
285 location: TargetDefinitionLocation::Heuristic,
286 })
287 }
288
289 pub(super) fn custom_from_path(
291 path: &Utf8Path,
292 source: TargetTripleSource,
293 resolve_dir: &Utf8Path,
294 ) -> Result<Self, TargetTripleError> {
295 assert_eq!(
296 path.extension(),
297 Some("json"),
298 "path {path} must end with .json",
299 );
300 let path = resolve_dir.join(path);
301 let canonicalized_path =
302 path.canonicalize_utf8()
303 .map_err(|error| TargetTripleError::TargetPathReadError {
304 source: source.clone(),
305 path,
306 error,
307 })?;
308 let triple_str = canonicalized_path
310 .file_stem()
311 .expect("target path must not be empty")
312 .to_owned();
313 Self::load_file(
314 &triple_str,
315 &canonicalized_path,
316 source,
317 TargetDefinitionLocation::DirectPath(canonicalized_path.clone()),
318 )
319 }
320
321 fn load_file(
322 triple_str: &str,
323 path: &Utf8Path,
324 source: TargetTripleSource,
325 location: TargetDefinitionLocation,
326 ) -> Result<Self, TargetTripleError> {
327 let contents = std::fs::read_to_string(path).map_err(|error| {
328 TargetTripleError::TargetPathReadError {
329 source: source.clone(),
330 path: path.to_owned(),
331 error,
332 }
333 })?;
334 let platform =
335 Platform::new_custom(triple_str.to_owned(), &contents, TargetFeatures::Unknown)
336 .map_err(|error| TargetTripleError::TargetSpecError {
337 source: source.clone(),
338 error,
339 })?;
340 Ok(Self {
341 platform,
342 source,
343 location,
344 })
345 }
346}
347
348#[derive(Debug)]
356pub enum CargoTargetArg {
357 Builtin(String),
359
360 Path(Utf8PathBuf),
362
363 Extracted(ExtractedCustomPlatform),
365
366 RustcCfg(String),
368}
369
370impl CargoTargetArg {
371 fn from_custom_json(
372 triple_str: &str,
373 json: &str,
374 source: TargetTripleSource,
375 ) -> Result<Self, TargetTripleError> {
376 let extracted = ExtractedCustomPlatform::new(triple_str, json, source)?;
377 Ok(Self::Extracted(extracted))
378 }
379}
380
381impl fmt::Display for CargoTargetArg {
382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383 match self {
384 Self::Builtin(triple) => {
385 write!(f, "{triple}")
386 }
387 Self::Path(path) => {
388 write!(f, "{path}")
389 }
390 Self::Extracted(extracted) => {
391 write!(f, "{}", extracted.path())
392 }
393 Self::RustcCfg(triple) => {
394 write!(f, "{triple}")
395 }
396 }
397 }
398}
399
400#[derive(Clone, Debug, PartialEq, Eq)]
404pub enum TargetTripleSource {
405 CliOption,
407
408 Env,
410
411 CargoConfig {
414 source: CargoConfigSource,
416 },
417
418 Metadata,
421}
422
423impl fmt::Display for TargetTripleSource {
424 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
425 match self {
426 Self::CliOption => {
427 write!(f, "--target <option>")
428 }
429 Self::Env => {
430 write!(f, "environment variable `CARGO_BUILD_TARGET`")
431 }
432 Self::CargoConfig {
433 source: CargoConfigSource::CliOption,
434 } => {
435 write!(f, "`build.target` specified by `--config`")
436 }
437
438 Self::CargoConfig {
439 source: CargoConfigSource::File(path),
440 } => {
441 write!(f, "`build.target` within `{path}`")
442 }
443 Self::Metadata => {
444 write!(f, "--archive-file or --binaries-metadata option")
445 }
446 }
447 }
448}
449
450#[derive(Clone, Debug, Eq, PartialEq)]
452pub enum TargetDefinitionLocation {
453 Builtin,
455
456 DirectPath(Utf8PathBuf),
458
459 RustTargetPath(Utf8PathBuf),
461
462 Heuristic,
464
465 MetadataCustom(String),
467
468 RustcCfgCustom,
470}
471
472impl fmt::Display for TargetDefinitionLocation {
473 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
474 match self {
475 Self::Builtin => {
476 write!(f, "target was builtin")
477 }
478 Self::DirectPath(path) => {
479 write!(f, "definition obtained from file at path `{path}`")
480 }
481 Self::RustTargetPath(path) => {
482 write!(f, "definition obtained from RUST_TARGET_PATH: `{path}`")
483 }
484 Self::Heuristic => {
485 write!(f, "definition obtained heuristically")
486 }
487 Self::MetadataCustom(_) => {
488 write!(f, "custom definition stored in metadata")
489 }
490 Self::RustcCfgCustom => {
491 write!(f, "custom definition from the rustc cfg")
492 }
493 }
494 }
495}
496
497#[cfg(test)]
498mod tests {
499 use super::*;
500 use crate::cargo_config::test_helpers::{custom_platform, setup_temp_dir};
501
502 #[test]
503 fn test_find_target_triple() {
504 let dir = setup_temp_dir().unwrap();
505 let dir_path = Utf8PathBuf::try_from(dir.path().canonicalize().unwrap()).unwrap();
506 let dir_foo_path = dir_path.join("foo");
507 let dir_foo_bar_path = dir_foo_path.join("bar");
508 let dir_foo_bar_custom1_path = dir_foo_bar_path.join("custom1");
509 let dir_foo_bar_custom2_path = dir_foo_bar_path.join("custom2");
510 let custom_target_dir = dir.path().join("custom-target");
511 let custom_target_path = dir
512 .path()
513 .join("custom-target/my-target.json")
514 .canonicalize_utf8()
515 .expect("path exists");
516
517 assert_eq!(
519 find_target_triple(&[], None, &dir_foo_bar_path, &dir_path),
520 Some(TargetTriple {
521 platform: platform("x86_64-unknown-linux-gnu"),
522 source: TargetTripleSource::CargoConfig {
523 source: CargoConfigSource::File(dir_path.join("foo/bar/.cargo/config.toml")),
524 },
525 location: TargetDefinitionLocation::Builtin,
526 }),
527 );
528
529 assert_eq!(
530 find_target_triple(&[], None, &dir_foo_path, &dir_path),
531 Some(TargetTriple {
532 platform: platform("x86_64-pc-windows-msvc"),
533 source: TargetTripleSource::CargoConfig {
534 source: CargoConfigSource::File(dir_path.join("foo/.cargo/config")),
535 },
536 location: TargetDefinitionLocation::Builtin,
537 }),
538 );
539
540 assert_eq!(
541 find_target_triple(&[], None, &dir_foo_bar_custom2_path, &dir_path),
542 Some(TargetTriple {
543 platform: custom_platform(),
544 source: TargetTripleSource::CargoConfig {
545 source: CargoConfigSource::File(
546 dir_path.join("foo/bar/custom2/.cargo/config.toml")
547 ),
548 },
549 location: TargetDefinitionLocation::DirectPath(custom_target_path.clone()),
550 })
551 );
552
553 assert_eq!(
554 find_target_triple_with_paths(
555 &[],
556 None,
557 &dir_foo_bar_custom1_path,
558 &dir_path,
559 vec![custom_target_dir]
560 ),
561 Some(TargetTriple {
562 platform: custom_platform(),
563 source: TargetTripleSource::CargoConfig {
564 source: CargoConfigSource::File(
565 dir_path.join("foo/bar/custom1/.cargo/config.toml")
566 ),
567 },
568 location: TargetDefinitionLocation::RustTargetPath(custom_target_path.clone()),
569 })
570 );
571
572 assert_eq!(
573 find_target_triple(
574 &["build.target=\"aarch64-unknown-linux-gnu\""],
575 None,
576 &dir_foo_bar_path,
577 &dir_path
578 ),
579 Some(TargetTriple {
580 platform: platform("aarch64-unknown-linux-gnu"),
581 source: TargetTripleSource::CargoConfig {
582 source: CargoConfigSource::CliOption,
583 },
584 location: TargetDefinitionLocation::Builtin,
585 })
586 );
587
588 assert_eq!(
590 find_target_triple(
591 &[
592 "build.target=\"aarch64-unknown-linux-gnu\"",
593 "build.target=\"x86_64-unknown-linux-musl\""
594 ],
595 None,
596 &dir_foo_bar_path,
597 &dir_path
598 ),
599 Some(TargetTriple {
600 platform: platform("aarch64-unknown-linux-gnu"),
601 source: TargetTripleSource::CargoConfig {
602 source: CargoConfigSource::CliOption,
603 },
604 location: TargetDefinitionLocation::Builtin,
605 })
606 );
607
608 assert_eq!(
610 find_target_triple(
611 &["build.target=\"../../custom-target/my-target.json\"",],
612 None,
613 &dir_foo_bar_path,
614 &dir_path
615 ),
616 Some(TargetTriple {
617 platform: custom_platform(),
618 source: TargetTripleSource::CargoConfig {
619 source: CargoConfigSource::CliOption,
620 },
621 location: TargetDefinitionLocation::DirectPath(custom_target_path.clone()),
622 })
623 );
624
625 assert_eq!(
627 find_target_triple(
628 &["build.target=\"aarch64-unknown-linux-gnu\"",],
629 Some("aarch64-pc-windows-msvc"),
630 &dir_foo_bar_path,
631 &dir_path
632 ),
633 Some(TargetTriple {
634 platform: platform("aarch64-unknown-linux-gnu"),
635 source: TargetTripleSource::CargoConfig {
636 source: CargoConfigSource::CliOption,
637 },
638 location: TargetDefinitionLocation::Builtin,
639 })
640 );
641
642 assert_eq!(
644 find_target_triple(
645 &[],
646 Some("aarch64-pc-windows-msvc"),
647 &dir_foo_bar_path,
648 &dir_path
649 ),
650 Some(TargetTriple {
651 platform: platform("aarch64-pc-windows-msvc"),
652 source: TargetTripleSource::Env,
653 location: TargetDefinitionLocation::Builtin,
654 })
655 );
656
657 assert_eq!(
662 find_target_triple(&["extra-config.toml"], None, &dir_foo_path, &dir_path),
663 Some(TargetTriple {
664 platform: platform("aarch64-unknown-linux-gnu"),
665 source: TargetTripleSource::CargoConfig {
666 source: CargoConfigSource::File(dir_foo_path.join("extra-config.toml")),
667 },
668 location: TargetDefinitionLocation::Builtin,
669 })
670 );
671 assert_eq!(
672 find_target_triple(
673 &["extra-config.toml"],
674 Some("aarch64-pc-windows-msvc"),
675 &dir_foo_path,
676 &dir_path
677 ),
678 Some(TargetTriple {
679 platform: platform("aarch64-unknown-linux-gnu"),
680 source: TargetTripleSource::CargoConfig {
681 source: CargoConfigSource::File(dir_foo_path.join("extra-config.toml")),
682 },
683 location: TargetDefinitionLocation::Builtin,
684 })
685 );
686 assert_eq!(
687 find_target_triple(
688 &[
689 "../extra-config.toml",
690 "build.target=\"x86_64-unknown-linux-musl\"",
691 ],
692 None,
693 &dir_foo_bar_path,
694 &dir_path
695 ),
696 Some(TargetTriple {
697 platform: platform("x86_64-unknown-linux-musl"),
698 source: TargetTripleSource::CargoConfig {
699 source: CargoConfigSource::CliOption,
700 },
701 location: TargetDefinitionLocation::Builtin,
702 })
703 );
704 assert_eq!(
705 find_target_triple(
706 &[
707 "build.target=\"x86_64-unknown-linux-musl\"",
708 "extra-config.toml",
709 ],
710 None,
711 &dir_foo_path,
712 &dir_path
713 ),
714 Some(TargetTriple {
715 platform: platform("x86_64-unknown-linux-musl"),
716 source: TargetTripleSource::CargoConfig {
717 source: CargoConfigSource::CliOption,
718 },
719 location: TargetDefinitionLocation::Builtin,
720 })
721 );
722 assert_eq!(
726 find_target_triple(
727 &["../extra-custom-config.toml"],
728 None,
729 &dir_foo_bar_path,
730 &dir_path
731 ),
732 Some(TargetTriple {
733 platform: custom_platform(),
734 source: TargetTripleSource::CargoConfig {
735 source: CargoConfigSource::File(dir_foo_path.join("extra-custom-config.toml")),
736 },
737 location: TargetDefinitionLocation::DirectPath(custom_target_path),
738 })
739 );
740
741 assert_eq!(find_target_triple(&[], None, &dir_path, &dir_path), None);
742 }
743
744 fn find_target_triple(
745 cli_configs: &[&str],
746 env: Option<&str>,
747 start_search_at: &Utf8Path,
748 terminate_search_at: &Utf8Path,
749 ) -> Option<TargetTriple> {
750 find_target_triple_with_paths(
751 cli_configs,
752 env,
753 start_search_at,
754 terminate_search_at,
755 Vec::new(),
756 )
757 }
758
759 fn find_target_triple_with_paths(
760 cli_configs: &[&str],
761 env: Option<&str>,
762 start_search_at: &Utf8Path,
763 terminate_search_at: &Utf8Path,
764 target_paths: Vec<Utf8PathBuf>,
765 ) -> Option<TargetTriple> {
766 find_target_triple_impl(
767 cli_configs,
768 None,
769 env,
770 start_search_at,
771 terminate_search_at,
772 target_paths,
773 &dummy_host_platform(),
774 )
775 }
776
777 fn find_target_triple_with_host(
778 cli_configs: &[&str],
779 target_cli_option: Option<&str>,
780 env: Option<&str>,
781 start_search_at: &Utf8Path,
782 terminate_search_at: &Utf8Path,
783 host_platform: &Platform,
784 ) -> Option<TargetTriple> {
785 find_target_triple_impl(
786 cli_configs,
787 target_cli_option,
788 env,
789 start_search_at,
790 terminate_search_at,
791 Vec::new(),
792 host_platform,
793 )
794 }
795
796 fn find_target_triple_impl(
797 cli_configs: &[&str],
798 target_cli_option: Option<&str>,
799 env: Option<&str>,
800 start_search_at: &Utf8Path,
801 terminate_search_at: &Utf8Path,
802 target_paths: Vec<Utf8PathBuf>,
803 host_platform: &Platform,
804 ) -> Option<TargetTriple> {
805 let configs = CargoConfigs::new_with_isolation(
806 cli_configs,
807 start_search_at,
808 terminate_search_at,
809 target_paths,
810 )
811 .unwrap();
812 if let Some(env) = env {
813 unsafe { std::env::set_var("CARGO_BUILD_TARGET", env) };
816 }
817 let ret = TargetTriple::find(&configs, target_cli_option, host_platform).unwrap();
818 unsafe { std::env::remove_var("CARGO_BUILD_TARGET") };
821 ret
822 }
823
824 #[test]
825 fn test_host_tuple() {
826 let dir = camino_tempfile::Builder::new()
828 .tempdir()
829 .expect("error creating tempdir");
830 let dir_path = Utf8PathBuf::try_from(dir.path().canonicalize().unwrap()).unwrap();
831
832 std::fs::create_dir_all(dir.path().join(".cargo")).expect("error creating .cargo subdir");
833 std::fs::write(
834 dir.path().join(".cargo/config.toml"),
835 r#"
836 [build]
837 target = "host-tuple"
838 "#,
839 )
840 .expect("error writing .cargo/config.toml");
841
842 let host_platform = platform("aarch64-apple-darwin");
843
844 assert_eq!(
846 find_target_triple_with_host(
847 &[],
848 Some("host-tuple"),
849 None,
850 &dir_path,
851 &dir_path,
852 &host_platform,
853 ),
854 Some(TargetTriple {
855 platform: platform("aarch64-apple-darwin"),
856 source: TargetTripleSource::CliOption,
857 location: TargetDefinitionLocation::Builtin,
858 })
859 );
860
861 assert_eq!(
863 find_target_triple_with_host(
864 &["build.target=\"host-tuple\""],
865 None,
866 None,
867 &dir_path,
868 &dir_path,
869 &host_platform,
870 ),
871 Some(TargetTriple {
872 platform: platform("aarch64-apple-darwin"),
873 source: TargetTripleSource::CargoConfig {
874 source: CargoConfigSource::CliOption,
875 },
876 location: TargetDefinitionLocation::Builtin,
877 })
878 );
879
880 assert_eq!(
882 find_target_triple_with_host(
883 &[],
884 None,
885 Some("host-tuple"),
886 &dir_path,
887 &dir_path,
888 &host_platform,
889 ),
890 Some(TargetTriple {
891 platform: platform("aarch64-apple-darwin"),
892 source: TargetTripleSource::Env,
893 location: TargetDefinitionLocation::Builtin,
894 })
895 );
896
897 assert_eq!(
899 find_target_triple_with_host(&[], None, None, &dir_path, &dir_path, &host_platform),
900 Some(TargetTriple {
901 platform: platform("aarch64-apple-darwin"),
902 source: TargetTripleSource::CargoConfig {
903 source: CargoConfigSource::File(dir_path.join(".cargo/config.toml")),
904 },
905 location: TargetDefinitionLocation::Builtin,
906 })
907 );
908 }
909
910 fn platform(triple_str: &str) -> Platform {
911 Platform::new(triple_str.to_owned(), TargetFeatures::Unknown).expect("triple str is valid")
912 }
913
914 fn dummy_host_platform() -> Platform {
915 Platform::new(
916 "x86_64-unknown-linux-gnu".to_owned(),
917 TargetFeatures::Unknown,
918 )
919 .unwrap()
920 }
921}