@@ -5,6 +5,8 @@ use crate::util::errors::CargoResult;
55use crate :: util:: interning:: InternedString ;
66use crate :: util:: { GlobalContext , StableHasher , try_canonicalize} ;
77use anyhow:: Context as _;
8+ use anyhow:: bail;
9+ use cargo_util:: ProcessBuilder ;
810use serde:: Serialize ;
911use std:: collections:: BTreeSet ;
1012use std:: fs;
@@ -92,9 +94,15 @@ impl CompileKind {
9294
9395 if value. as_str ( ) == "host-tuple" {
9496 let host_triple = env ! ( "RUST_HOST_TARGET" ) ;
95- Ok ( CompileKind :: Target ( CompileTarget :: new ( host_triple) ?) )
97+ Ok ( CompileKind :: Target ( CompileTarget :: new (
98+ host_triple,
99+ gctx. cli_unstable ( ) . json_target_spec ,
100+ ) ?) )
96101 } else {
97- Ok ( CompileKind :: Target ( CompileTarget :: new ( value. as_str ( ) ) ?) )
102+ Ok ( CompileKind :: Target ( CompileTarget :: new (
103+ value. as_str ( ) ,
104+ gctx. cli_unstable ( ) . json_target_spec ,
105+ ) ?) )
98106 }
99107 } )
100108 // First collect into a set to deduplicate any `--target` passed
@@ -132,6 +140,17 @@ impl CompileKind {
132140 CompileKind :: Target ( target) => target. fingerprint_hash ( ) ,
133141 }
134142 }
143+
144+ /// Adds the `--target` flag to the given [`ProcessBuilder`] if this is a
145+ /// non-host build.
146+ pub fn add_target_arg ( & self , builder : & mut ProcessBuilder ) {
147+ if let CompileKind :: Target ( target) = self {
148+ builder. arg ( "--target" ) . arg ( target. rustc_target ( ) ) ;
149+ if matches ! ( target, CompileTarget :: Json { .. } ) {
150+ builder. arg ( "-Zunstable-options" ) ;
151+ }
152+ }
153+ }
135154}
136155
137156impl serde:: ser:: Serialize for CompileKind {
@@ -141,7 +160,7 @@ impl serde::ser::Serialize for CompileKind {
141160 {
142161 match self {
143162 CompileKind :: Host => None :: < & str > . serialize ( s) ,
144- CompileKind :: Target ( t) => Some ( t. name ) . serialize ( s) ,
163+ CompileKind :: Target ( t) => Some ( t. rustc_target ( ) ) . serialize ( s) ,
145164 }
146165 }
147166}
@@ -164,31 +183,39 @@ impl serde::ser::Serialize for CompileKind {
164183/// file stem of JSON target files. For built-in rustc targets this is just an
165184/// uninterpreted string basically.
166185#[ derive( PartialEq , Eq , Hash , Debug , Clone , Copy , PartialOrd , Ord , Serialize ) ]
167- pub struct CompileTarget {
168- name : InternedString ,
186+ pub enum CompileTarget {
187+ Tuple ( InternedString ) ,
188+ Json {
189+ short : InternedString ,
190+ path : InternedString ,
191+ } ,
169192}
170193
171194impl CompileTarget {
172- pub fn new ( name : & str ) -> CargoResult < CompileTarget > {
195+ pub fn new ( name : & str , unstable_json : bool ) -> CargoResult < CompileTarget > {
173196 let name = name. trim ( ) ;
174197 if name. is_empty ( ) {
175- anyhow :: bail!( "target was empty" ) ;
198+ bail ! ( "target was empty" ) ;
176199 }
177200 if !name. ends_with ( ".json" ) {
178- return Ok ( CompileTarget { name : name. into ( ) } ) ;
201+ return Ok ( CompileTarget :: Tuple ( name. into ( ) ) ) ;
202+ }
203+
204+ if !unstable_json {
205+ bail ! ( "`.json` target specs require -Zjson-target-spec" ) ;
179206 }
180207
181208 // If `name` ends in `.json` then it's likely a custom target
182209 // specification. Canonicalize the path to ensure that different builds
183210 // with different paths always produce the same result.
184- let path = try_canonicalize ( Path :: new ( name) )
185- . with_context ( || format ! ( "target path {:?} is not a valid file" , name ) ) ?;
186-
187- let name = path
188- . into_os_string ( )
189- . into_string ( )
190- . map_err ( |_| anyhow :: format_err! ( "target path is not valid unicode" ) ) ? ;
191- Ok ( CompileTarget { name : name . into ( ) } )
211+ let p = try_canonicalize ( Path :: new ( name) )
212+ . with_context ( || format ! ( "target path `{name}` is not a valid file" ) ) ?;
213+ let path = p
214+ . to_str ( )
215+ . ok_or_else ( || anyhow :: format_err! ( "target path `{name}` is not valid unicode" ) ) ?
216+ . into ( ) ;
217+ let short = p . file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . into ( ) ;
218+ Ok ( CompileTarget :: Json { short , path } )
192219 }
193220
194221 /// Returns the full unqualified name of this target, suitable for passing
@@ -198,7 +225,10 @@ impl CompileTarget {
198225 /// of JSON target files this will be a full canonicalized path name for the
199226 /// current filesystem.
200227 pub fn rustc_target ( & self ) -> InternedString {
201- self . name
228+ match self {
229+ CompileTarget :: Tuple ( name) => * name,
230+ CompileTarget :: Json { path, .. } => * path,
231+ }
202232 }
203233
204234 /// Returns a "short" version of the target name suitable for usage within
@@ -208,34 +238,25 @@ impl CompileTarget {
208238 /// JSON target files this returns just the file stem (e.g. `foo` out of
209239 /// `foo.json`) instead of the full path.
210240 pub fn short_name ( & self ) -> & str {
211- // Flexible target specifications often point at json files, so if it
212- // looks like we've got one of those just use the file stem (the file
213- // name without ".json") as a short name for this target. Note that the
214- // `unwrap()` here should never trigger since we have a nonempty name
215- // and it starts as utf-8 so it's always utf-8
216- if self . name . ends_with ( ".json" ) {
217- Path :: new ( & self . name ) . file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( )
218- } else {
219- & self . name
241+ match self {
242+ CompileTarget :: Tuple ( name) => name,
243+ CompileTarget :: Json { short, .. } => short,
220244 }
221245 }
222246
223247 /// See [`CompileKind::fingerprint_hash`].
224248 pub fn fingerprint_hash ( & self ) -> u64 {
225249 let mut hasher = StableHasher :: new ( ) ;
226- match self
227- . name
228- . ends_with ( ".json" )
229- . then ( || fs:: read_to_string ( self . name ) )
230- {
231- Some ( Ok ( contents) ) => {
250+ match self {
251+ CompileTarget :: Tuple ( name) => name. hash ( & mut hasher) ,
252+ CompileTarget :: Json { path, .. } => {
232253 // This may have some performance concerns, since it is called
233254 // fairly often. If that ever seems worth fixing, consider
234255 // embedding this in `CompileTarget`.
235- contents . hash ( & mut hasher ) ;
236- }
237- _ => {
238- self . name . hash ( & mut hasher ) ;
256+ match fs :: read_to_string ( path ) {
257+ Ok ( contents ) => contents . hash ( & mut hasher ) ,
258+ Err ( _ ) => path . hash ( & mut hasher ) ,
259+ }
239260 }
240261 }
241262 Hasher :: finish ( & hasher)
0 commit comments