@@ -7,7 +7,7 @@ use rustc::session::config::{
77} ;
88use rustc:: session:: search_paths:: PathKind ;
99use rustc:: middle:: dependency_format:: Linkage ;
10- use rustc:: middle:: cstore:: { LibSource , NativeLibrary , NativeLibraryKind } ;
10+ use rustc:: middle:: cstore:: { EncodedMetadata , LibSource , NativeLibrary , NativeLibraryKind } ;
1111use rustc:: util:: common:: { time, time_ext} ;
1212use rustc:: hir:: def_id:: CrateNum ;
1313use rustc_data_structures:: fx:: FxHashSet ;
@@ -50,9 +50,9 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
5050 outputs : & OutputFilenames ,
5151 crate_name : & str ,
5252 target_cpu : & str ) {
53+ let output_metadata = sess. opts . output_types . contains_key ( & OutputType :: Metadata ) ;
5354 for & crate_type in sess. crate_types . borrow ( ) . iter ( ) {
5455 // Ignore executable crates if we have -Z no-codegen, as they will error.
55- let output_metadata = sess. opts . output_types . contains_key ( & OutputType :: Metadata ) ;
5656 if ( sess. opts . debugging_opts . no_codegen || !sess. opts . output_types . should_codegen ( ) ) &&
5757 !output_metadata &&
5858 crate_type == config:: CrateType :: Executable {
@@ -63,12 +63,43 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
6363 bug ! ( "invalid output type `{:?}` for target os `{}`" ,
6464 crate_type, sess. opts. target_triple) ;
6565 }
66- link_binary_output :: < B > ( sess,
67- codegen_results,
68- crate_type,
69- outputs,
70- crate_name,
71- target_cpu) ;
66+
67+ for obj in codegen_results. modules . iter ( ) . filter_map ( |m| m. object . as_ref ( ) ) {
68+ check_file_is_writeable ( obj, sess) ;
69+ }
70+
71+ let tmpdir = TempFileBuilder :: new ( ) . prefix ( "rustc" ) . tempdir ( ) . unwrap_or_else ( |err|
72+ sess. fatal ( & format ! ( "couldn't create a temp dir: {}" , err) ) ) ;
73+
74+ if outputs. outputs . should_codegen ( ) {
75+ let out_filename = out_filename ( sess, crate_type, outputs, crate_name) ;
76+ match crate_type {
77+ config:: CrateType :: Rlib => {
78+ link_rlib :: < B > ( sess,
79+ codegen_results,
80+ RlibFlavor :: Normal ,
81+ & out_filename,
82+ & tmpdir) . build ( ) ;
83+ }
84+ config:: CrateType :: Staticlib => {
85+ link_staticlib :: < B > ( sess, codegen_results, & out_filename, & tmpdir) ;
86+ }
87+ _ => {
88+ link_natively :: < B > (
89+ sess,
90+ crate_type,
91+ & out_filename,
92+ codegen_results,
93+ tmpdir. path ( ) ,
94+ target_cpu,
95+ ) ;
96+ }
97+ }
98+ }
99+
100+ if sess. opts . cg . save_temps {
101+ let _ = tmpdir. into_path ( ) ;
102+ }
72103 }
73104
74105 // Remove the temporary object file and metadata if we aren't saving temps
@@ -85,7 +116,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
85116 if let Some ( ref obj) = metadata_module. object {
86117 remove ( sess, obj) ;
87118 }
88- }
119+ }
89120 if let Some ( ref allocator_module) = codegen_results. allocator_module {
90121 if let Some ( ref obj) = allocator_module. object {
91122 remove ( sess, obj) ;
@@ -97,73 +128,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
97128 }
98129}
99130
100- fn link_binary_output < ' a , B : ArchiveBuilder < ' a > > ( sess : & ' a Session ,
101- codegen_results : & CodegenResults ,
102- crate_type : config:: CrateType ,
103- outputs : & OutputFilenames ,
104- crate_name : & str ,
105- target_cpu : & str ) {
106- for obj in codegen_results. modules . iter ( ) . filter_map ( |m| m. object . as_ref ( ) ) {
107- check_file_is_writeable ( obj, sess) ;
108- }
109-
110- if outputs. outputs . contains_key ( & OutputType :: Metadata ) {
111- let out_filename = filename_for_metadata ( sess, crate_name, outputs) ;
112- // To avoid races with another rustc process scanning the output directory,
113- // we need to write the file somewhere else and atomically move it to its
114- // final destination, with a `fs::rename` call. In order for the rename to
115- // always succeed, the temporary file needs to be on the same filesystem,
116- // which is why we create it inside the output directory specifically.
117- let metadata_tmpdir = TempFileBuilder :: new ( )
118- . prefix ( "rmeta" )
119- . tempdir_in ( out_filename. parent ( ) . unwrap ( ) )
120- . unwrap_or_else ( |err| sess. fatal ( & format ! ( "couldn't create a temp dir: {}" , err) ) ) ;
121- let metadata = emit_metadata ( sess, codegen_results, & metadata_tmpdir) ;
122- match fs:: rename ( & metadata, & out_filename) {
123- Ok ( _) => {
124- if sess. opts . debugging_opts . emit_directives {
125- sess. parse_sess . span_diagnostic . maybe_emit_json_directive (
126- format ! ( "metadata file written: {}" , out_filename. display( ) ) ) ;
127- }
128- }
129- Err ( e) => sess. fatal ( & format ! ( "failed to write {}: {}" , out_filename. display( ) , e) ) ,
130- }
131- }
132-
133- let tmpdir = TempFileBuilder :: new ( ) . prefix ( "rustc" ) . tempdir ( ) . unwrap_or_else ( |err|
134- sess. fatal ( & format ! ( "couldn't create a temp dir: {}" , err) ) ) ;
135-
136- if outputs. outputs . should_codegen ( ) {
137- let out_filename = out_filename ( sess, crate_type, outputs, crate_name) ;
138- match crate_type {
139- config:: CrateType :: Rlib => {
140- link_rlib :: < B > ( sess,
141- codegen_results,
142- RlibFlavor :: Normal ,
143- & out_filename,
144- & tmpdir) . build ( ) ;
145- }
146- config:: CrateType :: Staticlib => {
147- link_staticlib :: < B > ( sess, codegen_results, & out_filename, & tmpdir) ;
148- }
149- _ => {
150- link_natively :: < B > (
151- sess,
152- crate_type,
153- & out_filename,
154- codegen_results,
155- tmpdir. path ( ) ,
156- target_cpu,
157- ) ;
158- }
159- }
160- }
161-
162- if sess. opts . cg . save_temps {
163- let _ = tmpdir. into_path ( ) ;
164- }
165- }
166-
167131// The third parameter is for env vars, used on windows to set up the
168132// path for MSVC to find its DLLs, and gcc to find its bundled
169133// toolchain
@@ -261,13 +225,13 @@ pub fn each_linked_rlib(sess: &Session,
261225/// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
262226/// directory being searched for `extern crate` (observing an incomplete file).
263227/// The returned path is the temporary file containing the complete metadata.
264- fn emit_metadata < ' a > (
228+ pub fn emit_metadata < ' a > (
265229 sess : & ' a Session ,
266- codegen_results : & CodegenResults ,
230+ metadata : & EncodedMetadata ,
267231 tmpdir : & TempDir
268232) -> PathBuf {
269233 let out_filename = tmpdir. path ( ) . join ( METADATA_FILENAME ) ;
270- let result = fs:: write ( & out_filename, & codegen_results . metadata . raw_data ) ;
234+ let result = fs:: write ( & out_filename, & metadata. raw_data ) ;
271235
272236 if let Err ( e) = result {
273237 sess. fatal ( & format ! ( "failed to write {}: {}" , out_filename. display( ) , e) ) ;
@@ -351,7 +315,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
351315 RlibFlavor :: Normal => {
352316 // Instead of putting the metadata in an object file section, rlibs
353317 // contain the metadata in a separate file.
354- ab. add_file ( & emit_metadata ( sess, codegen_results, tmpdir) ) ;
318+ ab. add_file ( & emit_metadata ( sess, & codegen_results. metadata , tmpdir) ) ;
355319
356320 // For LTO purposes, the bytecode of this library is also inserted
357321 // into the archive.
0 commit comments