1
- use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
1
+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
2
2
use rustc_data_structures:: temp_dir:: MaybeTempDir ;
3
- use rustc_errors:: Handler ;
3
+ use rustc_errors:: { ErrorReported , Handler } ;
4
4
use rustc_fs_util:: fix_windows_verbatim_for_gcc;
5
5
use rustc_hir:: def_id:: CrateNum ;
6
- use rustc_middle:: middle:: cstore:: { DllCallingConvention , DllImport } ;
6
+ use rustc_middle:: middle:: cstore:: DllImport ;
7
7
use rustc_middle:: middle:: dependency_format:: Linkage ;
8
8
use rustc_session:: config:: { self , CFGuard , CrateType , DebugInfo , LdImpl , Strip } ;
9
9
use rustc_session:: config:: { OutputFilenames , OutputType , PrintRequest } ;
@@ -35,7 +35,6 @@ use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, Se
35
35
use tempfile:: Builder as TempFileBuilder ;
36
36
37
37
use std:: ffi:: OsString ;
38
- use std:: iter:: FromIterator ;
39
38
use std:: path:: { Path , PathBuf } ;
40
39
use std:: process:: { ExitStatus , Output , Stdio } ;
41
40
use std:: { ascii, char, env, fmt, fs, io, mem, str} ;
@@ -54,7 +53,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
54
53
sess : & ' a Session ,
55
54
codegen_results : & CodegenResults ,
56
55
outputs : & OutputFilenames ,
57
- ) {
56
+ ) -> Result < ( ) , ErrorReported > {
58
57
let _timer = sess. timer ( "link_binary" ) ;
59
58
let output_metadata = sess. opts . output_types . contains_key ( & OutputType :: Metadata ) ;
60
59
for & crate_type in sess. crate_types ( ) . iter ( ) {
@@ -95,11 +94,17 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
95
94
match crate_type {
96
95
CrateType :: Rlib => {
97
96
let _timer = sess. timer ( "link_rlib" ) ;
98
- link_rlib :: < B > ( sess, codegen_results, RlibFlavor :: Normal , & out_filename, & path)
99
- . build ( ) ;
97
+ link_rlib :: < B > (
98
+ sess,
99
+ codegen_results,
100
+ RlibFlavor :: Normal ,
101
+ & out_filename,
102
+ & path,
103
+ ) ?
104
+ . build ( ) ;
100
105
}
101
106
CrateType :: Staticlib => {
102
- link_staticlib :: < B > ( sess, codegen_results, & out_filename, & path) ;
107
+ link_staticlib :: < B > ( sess, codegen_results, & out_filename, & path) ? ;
103
108
}
104
109
_ => {
105
110
link_natively :: < B > (
@@ -145,6 +150,8 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
145
150
}
146
151
}
147
152
} ) ;
153
+
154
+ Ok ( ( ) )
148
155
}
149
156
150
157
pub fn each_linked_rlib (
@@ -220,7 +227,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
220
227
flavor : RlibFlavor ,
221
228
out_filename : & Path ,
222
229
tmpdir : & MaybeTempDir ,
223
- ) -> B {
230
+ ) -> Result < B , ErrorReported > {
224
231
info ! ( "preparing rlib to {:?}" , out_filename) ;
225
232
let mut ab = <B as ArchiveBuilder >:: new ( sess, out_filename, None ) ;
226
233
@@ -259,7 +266,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
259
266
}
260
267
261
268
for ( raw_dylib_name, raw_dylib_imports) in
262
- collate_raw_dylibs ( sess, & codegen_results. crate_info . used_libraries )
269
+ collate_raw_dylibs ( sess, & codegen_results. crate_info . used_libraries ) ?
263
270
{
264
271
ab. inject_dll_import_lib ( & raw_dylib_name, & raw_dylib_imports, tmpdir) ;
265
272
}
@@ -312,7 +319,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
312
319
}
313
320
}
314
321
}
315
- return ab ;
322
+ return Ok ( ab ) ;
316
323
317
324
// For rlibs we "pack" rustc metadata into a dummy object file. When rustc
318
325
// creates a dylib crate type it will pass `--whole-archive` (or the
@@ -454,65 +461,40 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
454
461
fn collate_raw_dylibs (
455
462
sess : & Session ,
456
463
used_libraries : & [ NativeLib ] ,
457
- ) -> Vec < ( String , Vec < DllImport > ) > {
458
- let mut dylib_table: FxHashMap < String , FxHashSet < DllImport > > = FxHashMap :: default ( ) ;
464
+ ) -> Result < Vec < ( String , Vec < DllImport > ) > , ErrorReported > {
465
+ // Use index maps to preserve original order of imports and libraries.
466
+ let mut dylib_table = FxIndexMap :: < String , FxIndexMap < Symbol , & DllImport > > :: default ( ) ;
459
467
460
468
for lib in used_libraries {
461
469
if lib. kind == NativeLibKind :: RawDylib {
462
- let name = lib. name . unwrap_or_else ( ||
463
- bug ! ( "`link` attribute with kind = \" raw-dylib\" and no name should have caused error earlier" )
464
- ) ;
465
- let name = if matches ! ( lib. verbatim, Some ( true ) ) {
466
- name. to_string ( )
467
- } else {
468
- format ! ( "{}.dll" , name)
469
- } ;
470
- dylib_table. entry ( name) . or_default ( ) . extend ( lib. dll_imports . iter ( ) . cloned ( ) ) ;
471
- }
472
- }
473
-
474
- // Rustc already signals an error if we have two imports with the same name but different
475
- // calling conventions (or function signatures), so we don't have pay attention to those
476
- // when ordering.
477
- // FIXME: when we add support for ordinals, figure out if we need to do anything if we
478
- // have two DllImport values with the same name but different ordinals.
479
- let mut result: Vec < ( String , Vec < DllImport > ) > = dylib_table
480
- . into_iter ( )
481
- . map ( |( lib_name, import_table) | {
482
- let mut imports = Vec :: from_iter ( import_table. into_iter ( ) ) ;
483
- imports. sort_unstable_by_key ( |x : & DllImport | x. name . as_str ( ) ) ;
484
- ( lib_name, imports)
485
- } )
486
- . collect :: < Vec < _ > > ( ) ;
487
- result. sort_unstable_by ( |a : & ( String , Vec < DllImport > ) , b : & ( String , Vec < DllImport > ) | {
488
- a. 0 . cmp ( & b. 0 )
489
- } ) ;
490
- let result = result;
491
-
492
- // Check for multiple imports with the same name but different calling conventions or
493
- // (when relevant) argument list sizes. Rustc only signals an error for this if the
494
- // declarations are at the same scope level; if one shadows the other, we only get a lint
495
- // warning.
496
- for ( library, imports) in & result {
497
- let mut import_table: FxHashMap < Symbol , DllCallingConvention > = FxHashMap :: default ( ) ;
498
- for import in imports {
499
- if let Some ( old_convention) =
500
- import_table. insert ( import. name , import. calling_convention )
501
- {
502
- if import. calling_convention != old_convention {
503
- sess. span_fatal (
504
- import. span ,
505
- & format ! (
506
- "multiple definitions of external function `{}` from library `{}` have different calling conventions" ,
507
- import. name,
508
- library,
509
- ) ) ;
470
+ let ext = if matches ! ( lib. verbatim, Some ( true ) ) { "" } else { ".dll" } ;
471
+ let name = format ! ( "{}{}" , lib. name. expect( "unnamed raw-dylib library" ) , ext) ;
472
+ let imports = dylib_table. entry ( name. clone ( ) ) . or_default ( ) ;
473
+ for import in & lib. dll_imports {
474
+ if let Some ( old_import) = imports. insert ( import. name , import) {
475
+ // FIXME: when we add support for ordinals, figure out if we need to do anything
476
+ // if we have two DllImport values with the same name but different ordinals.
477
+ if import. calling_convention != old_import. calling_convention {
478
+ sess. span_err (
479
+ import. span ,
480
+ & format ! (
481
+ "multiple declarations of external function `{}` from \
482
+ library `{}` have different calling conventions",
483
+ import. name, name,
484
+ ) ,
485
+ ) ;
486
+ }
510
487
}
511
488
}
512
489
}
513
490
}
514
-
515
- result
491
+ sess. compile_status ( ) ?;
492
+ Ok ( dylib_table
493
+ . into_iter ( )
494
+ . map ( |( name, imports) | {
495
+ ( name, imports. into_iter ( ) . map ( |( _, import) | import. clone ( ) ) . collect ( ) )
496
+ } )
497
+ . collect ( ) )
516
498
}
517
499
518
500
/// Create a static archive.
@@ -531,9 +513,9 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
531
513
codegen_results : & CodegenResults ,
532
514
out_filename : & Path ,
533
515
tempdir : & MaybeTempDir ,
534
- ) {
516
+ ) -> Result < ( ) , ErrorReported > {
535
517
let mut ab =
536
- link_rlib :: < B > ( sess, codegen_results, RlibFlavor :: StaticlibBase , out_filename, tempdir) ;
518
+ link_rlib :: < B > ( sess, codegen_results, RlibFlavor :: StaticlibBase , out_filename, tempdir) ? ;
537
519
let mut all_native_libs = vec ! [ ] ;
538
520
539
521
let res = each_linked_rlib ( & codegen_results. crate_info , & mut |cnum, path| {
@@ -581,6 +563,8 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
581
563
print_native_static_libs ( sess, & all_native_libs) ;
582
564
}
583
565
}
566
+
567
+ Ok ( ( ) )
584
568
}
585
569
586
570
fn escape_stdout_stderr_string ( s : & [ u8 ] ) -> String {
0 commit comments