@@ -800,12 +800,8 @@ impl<'a> Linker for GccLinker<'a> {
800
800
return ;
801
801
}
802
802
803
- if self . sess . target . is_like_windows {
804
- // We already add -export arguments to the .drectve section of symbols.o
805
- return ;
806
- }
807
-
808
- let path = tmpdir. join ( "list" ) ;
803
+ let is_windows = self . sess . target . is_like_windows ;
804
+ let path = tmpdir. join ( if is_windows { "list.def" } else { "list" } ) ;
809
805
810
806
debug ! ( "EXPORTED SYMBOLS:" ) ;
811
807
@@ -821,6 +817,23 @@ impl<'a> Linker for GccLinker<'a> {
821
817
if let Err ( error) = res {
822
818
self . sess . dcx ( ) . emit_fatal ( errors:: LibDefWriteFailure { error } ) ;
823
819
}
820
+ } else if is_windows {
821
+ let res: io:: Result < ( ) > = try {
822
+ let mut f = File :: create_buffered ( & path) ?;
823
+
824
+ // .def file similar to MSVC one but without LIBRARY section
825
+ // because LD doesn't like when it's empty
826
+ writeln ! ( f, "EXPORTS" ) ?;
827
+ for ( symbol, _) in symbols {
828
+ debug ! ( " _{symbol}" ) ;
829
+ // Quote the name in case it's reserved by linker in some way
830
+ // (this accounts for names with dots in particular).
831
+ writeln ! ( f, " \" {symbol}\" " ) ?;
832
+ }
833
+ } ;
834
+ if let Err ( error) = res {
835
+ self . sess . dcx ( ) . emit_fatal ( errors:: LibDefWriteFailure { error } ) ;
836
+ }
824
837
} else {
825
838
// Write an LD version script
826
839
let res: io:: Result < ( ) > = try {
@@ -844,6 +857,8 @@ impl<'a> Linker for GccLinker<'a> {
844
857
self . link_arg ( "-exported_symbols_list" ) . link_arg ( path) ;
845
858
} else if self . sess . target . is_like_solaris {
846
859
self . link_arg ( "-M" ) . link_arg ( path) ;
860
+ } else if is_windows {
861
+ self . link_arg ( path) ;
847
862
} else {
848
863
let mut arg = OsString :: from ( "--version-script=" ) ;
849
864
arg. push ( path) ;
@@ -1083,11 +1098,37 @@ impl<'a> Linker for MsvcLinker<'a> {
1083
1098
1084
1099
fn export_symbols (
1085
1100
& mut self ,
1086
- _tmpdir : & Path ,
1087
- _crate_type : CrateType ,
1101
+ tmpdir : & Path ,
1102
+ crate_type : CrateType ,
1088
1103
_symbols : & [ ( String , SymbolExportKind ) ] ,
1089
1104
) {
1090
- // We already add /EXPORT arguments to the .drectve section of symbols.o
1105
+ // We already add /EXPORT arguments to the .drectve section of symbols.o. We generate
1106
+ // a .DEF file here anyway as it might prevent auto-export of some symbols.
1107
+
1108
+ // Symbol visibility takes care of this typically
1109
+ if crate_type == CrateType :: Executable {
1110
+ let should_export_executable_symbols =
1111
+ self . sess . opts . unstable_opts . export_executable_symbols ;
1112
+ if !should_export_executable_symbols {
1113
+ return ;
1114
+ }
1115
+ }
1116
+
1117
+ let path = tmpdir. join ( "lib.def" ) ;
1118
+ let res: io:: Result < ( ) > = try {
1119
+ let mut f = File :: create_buffered ( & path) ?;
1120
+
1121
+ // Start off with the standard module name header and then go
1122
+ // straight to exports.
1123
+ writeln ! ( f, "LIBRARY" ) ?;
1124
+ writeln ! ( f, "EXPORTS" ) ?;
1125
+ } ;
1126
+ if let Err ( error) = res {
1127
+ self . sess . dcx ( ) . emit_fatal ( errors:: LibDefWriteFailure { error } ) ;
1128
+ }
1129
+ let mut arg = OsString :: from ( "/DEF:" ) ;
1130
+ arg. push ( path) ;
1131
+ self . link_arg ( & arg) ;
1091
1132
}
1092
1133
1093
1134
fn subsystem ( & mut self , subsystem : & str ) {
0 commit comments