@@ -1131,48 +1131,7 @@ impl Build {
11311131 } ;
11321132 let dst = self . get_out_dir ( ) ?;
11331133
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) ?;
11761135 let print = PrintThread :: new ( ) ?;
11771136
11781137 self . compile_objects ( & objects, & print) ?;
@@ -1316,6 +1275,32 @@ impl Build {
13161275 }
13171276 }
13181277
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+
13191304 #[ cfg( feature = "parallel" ) ]
13201305 fn compile_objects ( & self , objs : & [ Object ] , print : & PrintThread ) -> Result < ( ) , Error > {
13211306 use std:: cell:: Cell ;
@@ -2379,6 +2364,7 @@ impl Build {
23792364 }
23802365
23812366 fn apple_flags ( & self , cmd : & mut Tool ) -> Result < ( ) , Error > {
2367+ #[ allow( dead_code) ]
23822368 enum ArchSpec {
23832369 Device ( & ' static str ) ,
23842370 Simulator ( & ' static str ) ,
@@ -3837,6 +3823,54 @@ fn wait_on_child(cmd: &Command, program: &str, child: &mut Child) -> Result<(),
38373823 }
38383824}
38393825
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+
38403874#[ cfg( feature = "parallel" ) ]
38413875fn try_wait_on_child (
38423876 cmd : & Command ,
0 commit comments