11use crate :: core:: compiler:: { BuildConfig , MessageFormat , TimingOutput } ;
22use crate :: core:: resolver:: CliFeatures ;
3- use crate :: core:: { Edition , Workspace } ;
3+ use crate :: core:: { shell , Edition , Workspace } ;
44use crate :: ops:: lockfile:: LOCKFILE_NAME ;
55use crate :: ops:: registry:: RegistryOrIndex ;
66use crate :: ops:: { CompileFilter , CompileOptions , NewOptions , Packages , VersionControl } ;
@@ -19,6 +19,7 @@ use cargo_util_schemas::manifest::ProfileName;
1919use cargo_util_schemas:: manifest:: RegistryName ;
2020use cargo_util_schemas:: manifest:: StringOrVec ;
2121use clap:: builder:: UnknownArgumentValueParser ;
22+ use home:: cargo_home_with_cwd;
2223use std:: ffi:: { OsStr , OsString } ;
2324use std:: path:: Path ;
2425use std:: path:: PathBuf ;
@@ -261,7 +262,8 @@ pub trait CommandExt: Sized {
261262 } ;
262263 self . _arg (
263264 optional_multi_opt ( "target" , "TRIPLE" , target)
264- . help_heading ( heading:: COMPILATION_OPTIONS ) ,
265+ . help_heading ( heading:: COMPILATION_OPTIONS )
266+ . add ( clap_complete:: ArgValueCandidates :: new ( get_target_triples) ) ,
265267 )
266268 . _arg ( unsupported_short_arg)
267269 }
@@ -1027,6 +1029,65 @@ pub fn lockfile_path(
10271029 return Ok ( Some ( path) ) ;
10281030}
10291031
1032+ fn get_target_triples ( ) -> Vec < clap_complete:: CompletionCandidate > {
1033+ let mut candidates = Vec :: new ( ) ;
1034+
1035+ if is_rustup ( ) {
1036+ if let Ok ( targets) = get_target_triples_from_rustup ( ) {
1037+ candidates. extend ( targets) ;
1038+ }
1039+ } else {
1040+ if let Ok ( targets) = get_target_triples_from_rustc ( ) {
1041+ candidates. extend ( targets) ;
1042+ }
1043+ }
1044+
1045+ candidates
1046+ }
1047+
1048+ fn get_target_triples_from_rustup ( ) -> CargoResult < Vec < clap_complete:: CompletionCandidate > > {
1049+ let output = std:: process:: Command :: new ( "rustup" )
1050+ . arg ( "target" )
1051+ . arg ( "list" )
1052+ . output ( ) ?;
1053+
1054+ if !output. status . success ( ) {
1055+ return Ok ( vec ! [ ] ) ;
1056+ }
1057+
1058+ let stdout = String :: from_utf8 ( output. stdout ) ?;
1059+
1060+ Ok ( stdout
1061+ . lines ( )
1062+ . map ( |line| {
1063+ let target = line. split_once ( ' ' ) ;
1064+ match target {
1065+ None => clap_complete:: CompletionCandidate :: new ( line. to_owned ( ) ) . hide ( true ) ,
1066+ Some ( ( target, _installed) ) => clap_complete:: CompletionCandidate :: new ( target) ,
1067+ }
1068+ } )
1069+ . collect ( ) )
1070+ }
1071+
1072+ fn get_target_triples_from_rustc ( ) -> CargoResult < Vec < clap_complete:: CompletionCandidate > > {
1073+ let cwd = std:: env:: current_dir ( ) ?;
1074+ let gctx = GlobalContext :: new ( shell:: Shell :: new ( ) , cwd. clone ( ) , cargo_home_with_cwd ( & cwd) ?) ;
1075+ let ws = Workspace :: new ( & find_root_manifest_for_wd ( & PathBuf :: from ( & cwd) ) ?, & gctx) ;
1076+
1077+ let rustc = match ws {
1078+ Ok ( ws) => gctx. load_global_rustc ( Some ( & ws) ) ?,
1079+ Err ( _) => gctx. load_global_rustc ( None ) ?,
1080+ } ;
1081+
1082+ let ( stdout, _stderr) =
1083+ rustc. cached_output ( rustc. process ( ) . arg ( "--print" ) . arg ( "target-list" ) , 0 ) ?;
1084+
1085+ Ok ( stdout
1086+ . lines ( )
1087+ . map ( |line| clap_complete:: CompletionCandidate :: new ( line. to_owned ( ) ) )
1088+ . collect ( ) )
1089+ }
1090+
10301091#[ track_caller]
10311092pub fn ignore_unknown < T : Default > ( r : Result < T , clap:: parser:: MatchesError > ) -> T {
10321093 match r {
0 commit comments