@@ -63,12 +63,66 @@ 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+ if outputs. outputs . contains_key ( & OutputType :: Metadata ) {
72+ let out_filename = filename_for_metadata ( sess, crate_name, outputs) ;
73+ // To avoid races with another rustc process scanning the output directory,
74+ // we need to write the file somewhere else and atomically move it to its
75+ // final destination, with a `fs::rename` call. In order for the rename to
76+ // always succeed, the temporary file needs to be on the same filesystem,
77+ // which is why we create it inside the output directory specifically.
78+ let metadata_tmpdir = TempFileBuilder :: new ( )
79+ . prefix ( "rmeta" )
80+ . tempdir_in ( out_filename. parent ( ) . unwrap ( ) )
81+ . unwrap_or_else ( |err| sess. fatal ( & format ! ( "couldn't create a temp dir: {}" , err) ) ) ;
82+ let metadata = emit_metadata ( sess, codegen_results, & metadata_tmpdir) ;
83+ match fs:: rename ( & metadata, & out_filename) {
84+ Ok ( _) => {
85+ if sess. opts . debugging_opts . emit_directives {
86+ sess. parse_sess . span_diagnostic . maybe_emit_json_directive (
87+ format ! ( "metadata file written: {}" , out_filename. display( ) ) ) ;
88+ }
89+ }
90+ Err ( e) => sess. fatal ( & format ! ( "failed to write {}: {}" , out_filename. display( ) , e) ) ,
91+ }
92+ }
93+
94+ let tmpdir = TempFileBuilder :: new ( ) . prefix ( "rustc" ) . tempdir ( ) . unwrap_or_else ( |err|
95+ sess. fatal ( & format ! ( "couldn't create a temp dir: {}" , err) ) ) ;
96+
97+ if outputs. outputs . should_codegen ( ) {
98+ let out_filename = out_filename ( sess, crate_type, outputs, crate_name) ;
99+ match crate_type {
100+ config:: CrateType :: Rlib => {
101+ link_rlib :: < B > ( sess,
102+ codegen_results,
103+ RlibFlavor :: Normal ,
104+ & out_filename,
105+ & tmpdir) . build ( ) ;
106+ }
107+ config:: CrateType :: Staticlib => {
108+ link_staticlib :: < B > ( sess, codegen_results, & out_filename, & tmpdir) ;
109+ }
110+ _ => {
111+ link_natively :: < B > (
112+ sess,
113+ crate_type,
114+ & out_filename,
115+ codegen_results,
116+ tmpdir. path ( ) ,
117+ target_cpu,
118+ ) ;
119+ }
120+ }
121+ }
122+
123+ if sess. opts . cg . save_temps {
124+ let _ = tmpdir. into_path ( ) ;
125+ }
72126 }
73127
74128 // Remove the temporary object file and metadata if we aren't saving temps
@@ -85,7 +139,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
85139 if let Some ( ref obj) = metadata_module. object {
86140 remove ( sess, obj) ;
87141 }
88- }
142+ }
89143 if let Some ( ref allocator_module) = codegen_results. allocator_module {
90144 if let Some ( ref obj) = allocator_module. object {
91145 remove ( sess, obj) ;
@@ -97,73 +151,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
97151 }
98152}
99153
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-
167154// The third parameter is for env vars, used on windows to set up the
168155// path for MSVC to find its DLLs, and gcc to find its bundled
169156// toolchain
0 commit comments