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