1
1
use crate :: core:: compiler:: { BuildConfig , MessageFormat , TimingOutput } ;
2
2
use crate :: core:: resolver:: CliFeatures ;
3
- use crate :: core:: { Edition , Workspace } ;
3
+ use crate :: core:: { shell , Edition , Workspace } ;
4
4
use crate :: ops:: lockfile:: LOCKFILE_NAME ;
5
5
use crate :: ops:: registry:: RegistryOrIndex ;
6
6
use crate :: ops:: { CompileFilter , CompileOptions , NewOptions , Packages , VersionControl } ;
@@ -19,6 +19,7 @@ use cargo_util_schemas::manifest::ProfileName;
19
19
use cargo_util_schemas:: manifest:: RegistryName ;
20
20
use cargo_util_schemas:: manifest:: StringOrVec ;
21
21
use clap:: builder:: UnknownArgumentValueParser ;
22
+ use home:: cargo_home_with_cwd;
22
23
use std:: ffi:: { OsStr , OsString } ;
23
24
use std:: path:: Path ;
24
25
use std:: path:: PathBuf ;
@@ -261,7 +262,8 @@ pub trait CommandExt: Sized {
261
262
} ;
262
263
self . _arg (
263
264
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) ) ,
265
267
)
266
268
. _arg ( unsupported_short_arg)
267
269
}
@@ -1027,6 +1029,65 @@ pub fn lockfile_path(
1027
1029
return Ok ( Some ( path) ) ;
1028
1030
}
1029
1031
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
+
1030
1091
#[ track_caller]
1031
1092
pub fn ignore_unknown < T : Default > ( r : Result < T , clap:: parser:: MatchesError > ) -> T {
1032
1093
match r {
0 commit comments