@@ -1131,48 +1131,7 @@ impl Build {
1131
1131
} ;
1132
1132
let dst = self . get_out_dir ( ) ?;
1133
1133
1134
- let mut objects = Vec :: new ( ) ;
1135
- for file in self . files . iter ( ) {
1136
- let obj = if file. has_root ( ) || file. components ( ) . any ( |x| x == Component :: ParentDir ) {
1137
- // If `file` is an absolute path or might not be usable directly as a suffix due to
1138
- // using "..", use the `basename` prefixed with the `dirname`'s hash to ensure name
1139
- // uniqueness.
1140
- let basename = file
1141
- . file_name ( )
1142
- . ok_or_else ( || Error :: new ( ErrorKind :: InvalidArgument , "file_name() failure" ) ) ?
1143
- . to_string_lossy ( ) ;
1144
- let dirname = file
1145
- . parent ( )
1146
- . ok_or_else ( || Error :: new ( ErrorKind :: InvalidArgument , "parent() failure" ) ) ?
1147
- . to_string_lossy ( ) ;
1148
- let mut hasher = hash_map:: DefaultHasher :: new ( ) ;
1149
- hasher. write ( dirname. to_string ( ) . as_bytes ( ) ) ;
1150
- dst. join ( format ! ( "{:016x}-{}" , hasher. finish( ) , basename) )
1151
- . with_extension ( "o" )
1152
- } else {
1153
- dst. join ( file) . with_extension ( "o" )
1154
- } ;
1155
- let obj = if !obj. starts_with ( & dst) {
1156
- dst. join ( obj. file_name ( ) . ok_or_else ( || {
1157
- Error :: new ( ErrorKind :: IOError , "Getting object file details failed." )
1158
- } ) ?)
1159
- } else {
1160
- obj
1161
- } ;
1162
-
1163
- match obj. parent ( ) {
1164
- Some ( s) => fs:: create_dir_all ( s) ?,
1165
- None => {
1166
- return Err ( Error :: new (
1167
- ErrorKind :: IOError ,
1168
- "Getting object file details failed." ,
1169
- ) ) ;
1170
- }
1171
- } ;
1172
-
1173
- objects. push ( Object :: new ( file. to_path_buf ( ) , obj) ) ;
1174
- }
1175
-
1134
+ let objects = objects_from_files ( & self . files , & dst) ?;
1176
1135
let print = PrintThread :: new ( ) ?;
1177
1136
1178
1137
self . compile_objects ( & objects, & print) ?;
@@ -1316,6 +1275,32 @@ impl Build {
1316
1275
}
1317
1276
}
1318
1277
1278
+ /// Run the compiler, generating intermediate files, but without linking
1279
+ /// them into an archive file.
1280
+ ///
1281
+ /// This will return a list of compiled object files, in the same order
1282
+ /// as they were passed in as `file`/`files` methods.
1283
+ pub fn compile_intermediates ( & self ) -> Vec < PathBuf > {
1284
+ match self . try_compile_intermediates ( ) {
1285
+ Ok ( v) => v,
1286
+ Err ( e) => fail ( & e. message ) ,
1287
+ }
1288
+ }
1289
+
1290
+ /// Run the compiler, generating intermediate files, but without linking
1291
+ /// them into an archive file.
1292
+ ///
1293
+ /// This will return a result instead of panicing; see `compile_intermediates()` for the complete description.
1294
+ pub fn try_compile_intermediates ( & self ) -> Result < Vec < PathBuf > , Error > {
1295
+ let dst = self . get_out_dir ( ) ?;
1296
+ let objects = objects_from_files ( & self . files , & dst) ?;
1297
+ let print = PrintThread :: new ( ) ?;
1298
+
1299
+ self . compile_objects ( & objects, & print) ?;
1300
+
1301
+ Ok ( objects. into_iter ( ) . map ( |v| v. dst ) . collect ( ) )
1302
+ }
1303
+
1319
1304
#[ cfg( feature = "parallel" ) ]
1320
1305
fn compile_objects ( & self , objs : & [ Object ] , print : & PrintThread ) -> Result < ( ) , Error > {
1321
1306
use std:: cell:: Cell ;
@@ -2379,6 +2364,7 @@ impl Build {
2379
2364
}
2380
2365
2381
2366
fn apple_flags ( & self , cmd : & mut Tool ) -> Result < ( ) , Error > {
2367
+ #[ allow( dead_code) ]
2382
2368
enum ArchSpec {
2383
2369
Device ( & ' static str ) ,
2384
2370
Simulator ( & ' static str ) ,
@@ -3837,6 +3823,54 @@ fn wait_on_child(cmd: &Command, program: &str, child: &mut Child) -> Result<(),
3837
3823
}
3838
3824
}
3839
3825
3826
+ /// Find the destination object path for each file in the input source files,
3827
+ /// and store them in the output Object.
3828
+ fn objects_from_files ( files : & [ Arc < Path > ] , dst : & Path ) -> Result < Vec < Object > , Error > {
3829
+ let mut objects = Vec :: with_capacity ( files. len ( ) ) ;
3830
+ for file in files {
3831
+ let basename = file
3832
+ . file_name ( )
3833
+ . ok_or_else ( || {
3834
+ Error :: new (
3835
+ ErrorKind :: InvalidArgument ,
3836
+ "No file_name for object file path!" ,
3837
+ )
3838
+ } ) ?
3839
+ . to_string_lossy ( ) ;
3840
+ let dirname = file
3841
+ . parent ( )
3842
+ . ok_or_else ( || {
3843
+ Error :: new (
3844
+ ErrorKind :: InvalidArgument ,
3845
+ "No parent for object file path!" ,
3846
+ )
3847
+ } ) ?
3848
+ . to_string_lossy ( ) ;
3849
+
3850
+ // Hash the dirname. This should prevent conflicts if we have multiple
3851
+ // object files with the same filename in different subfolders.
3852
+ let mut hasher = hash_map:: DefaultHasher :: new ( ) ;
3853
+ hasher. write ( dirname. to_string ( ) . as_bytes ( ) ) ;
3854
+ let obj = dst
3855
+ . join ( format ! ( "{:016x}-{}" , hasher. finish( ) , basename) )
3856
+ . with_extension ( "o" ) ;
3857
+
3858
+ match obj. parent ( ) {
3859
+ Some ( s) => fs:: create_dir_all ( s) ?,
3860
+ None => {
3861
+ return Err ( Error :: new (
3862
+ ErrorKind :: InvalidArgument ,
3863
+ "dst is an invalid path with no parent" ,
3864
+ ) ) ;
3865
+ }
3866
+ } ;
3867
+
3868
+ objects. push ( Object :: new ( file. to_path_buf ( ) , obj) ) ;
3869
+ }
3870
+
3871
+ Ok ( objects)
3872
+ }
3873
+
3840
3874
#[ cfg( feature = "parallel" ) ]
3841
3875
fn try_wait_on_child (
3842
3876
cmd : & Command ,
0 commit comments