@@ -63,7 +63,10 @@ use super::rmeta_link::RmetaLinkCache;
6363use super :: rpath:: { self , RPathConfig } ;
6464use super :: { apple, rmeta_link, versioned_llvm_target} ;
6565use crate :: base:: needs_allocator_shim_for_linking;
66- use crate :: { CodegenLintLevelSpecs , CompiledModule , CompiledModules , CrateInfo , NativeLib , errors} ;
66+ use crate :: {
67+ CodegenLintLevelSpecs , CompiledModule , CompiledModules , CrateInfo , NativeLib , SymbolExport ,
68+ errors,
69+ } ;
6770
6871pub fn ensure_removed ( dcx : DiagCtxtHandle < ' _ > , path : & Path ) {
6972 if let Err ( e) = fs:: remove_file ( path) {
@@ -593,7 +596,7 @@ fn link_staticlib(
593596 crate_info
594597 . exported_symbols
595598 . get ( & CrateType :: StaticLib )
596- . map ( |symbols| symbols. iter ( ) . map ( |( s , _ ) | s . clone ( ) ) . collect ( ) )
599+ . map ( |symbols| symbols. iter ( ) . map ( |symbol| symbol . name . clone ( ) ) . collect ( ) )
597600 }
598601 } else {
599602 None
@@ -2196,9 +2199,15 @@ fn add_linked_symbol_object(
21962199 cmd : & mut dyn Linker ,
21972200 sess : & Session ,
21982201 tmpdir : & Path ,
2199- symbols : & [ ( String , SymbolExportKind ) ] ,
2202+ crate_type : CrateType ,
2203+ linked_symbols : & [ ( String , SymbolExportKind ) ] ,
2204+ exported_symbols : & [ SymbolExport ] ,
22002205) {
2201- if symbols. is_empty ( ) {
2206+ let should_export_symbols = sess. target . is_like_msvc
2207+ && !exported_symbols. is_empty ( )
2208+ && ( crate_type != CrateType :: Executable
2209+ || sess. opts . unstable_opts . export_executable_symbols ) ;
2210+ if linked_symbols. is_empty ( ) && !should_export_symbols {
22022211 return ;
22032212 }
22042213
@@ -2235,7 +2244,7 @@ fn add_linked_symbol_object(
22352244 None
22362245 } ;
22372246
2238- for ( sym, kind) in symbols . iter ( ) {
2247+ for ( sym, kind) in linked_symbols . iter ( ) {
22392248 let symbol = file. add_symbol ( object:: write:: Symbol {
22402249 name : sym. clone ( ) . into ( ) ,
22412250 value : 0 ,
@@ -2293,6 +2302,37 @@ fn add_linked_symbol_object(
22932302 }
22942303 }
22952304
2305+ if should_export_symbols {
2306+ // Currently the compiler doesn't use `dllexport` (an LLVM attribute) to
2307+ // export symbols from a dynamic library. When building a dynamic library,
2308+ // however, we're going to want some symbols exported, so this adds a
2309+ // `.drectve` section which lists all the symbols using /EXPORT arguments.
2310+ //
2311+ // The linker will read these arguments from the `.drectve` section and
2312+ // export all the symbols from the dynamic library. Note that this is not
2313+ // as simple as just exporting all the symbols in the current crate (as
2314+ // specified by `codegen.reachable`) but rather we also need to possibly
2315+ // export the symbols of upstream crates. Upstream rlibs may be linked
2316+ // statically to this dynamic library, in which case they may continue to
2317+ // transitively be used and hence need their symbols exported.
2318+ fn msvc_drectve_export ( symbol : & SymbolExport ) -> String {
2319+ let data = if symbol. kind == SymbolExportKind :: Data { ",DATA" } else { "" } ;
2320+
2321+ if let Some ( link_name) = symbol. link_name . as_deref ( ) {
2322+ // The first name is the decorated symbol used by the import library, while
2323+ // EXPORTAS gives the public name written to the DLL export table.
2324+ format ! ( " /EXPORT:\" {link_name}\" {data},EXPORTAS,\" {}\" " , symbol. name)
2325+ } else {
2326+ format ! ( " /EXPORT:\" {}\" {data}" , symbol. name)
2327+ }
2328+ }
2329+
2330+ let drectve = exported_symbols. iter ( ) . map ( msvc_drectve_export) . collect :: < String > ( ) ;
2331+
2332+ let section = file. add_section ( vec ! [ ] , b".drectve" . to_vec ( ) , object:: SectionKind :: Linker ) ;
2333+ file. append_section_data ( section, drectve. as_bytes ( ) , 1 ) ;
2334+ }
2335+
22962336 let path = tmpdir. join ( "symbols.o" ) ;
22972337 let result = std:: fs:: write ( & path, file. write ( ) . unwrap ( ) ) ;
22982338 if let Err ( error) = result {
@@ -2486,7 +2526,7 @@ fn undecorate_c_symbol<'a>(
24862526fn add_c_staticlib_symbols (
24872527 sess : & Session ,
24882528 lib : & NativeLib ,
2489- out : & mut Vec < ( String , SymbolExportKind ) > ,
2529+ out : & mut Vec < SymbolExport > ,
24902530) -> io:: Result < ( ) > {
24912531 let file_path = find_native_static_library ( lib. name . as_str ( ) , lib. verbatim , sess) ;
24922532
@@ -2549,7 +2589,11 @@ fn add_c_staticlib_symbols(
25492589 let Some ( undecorated) = undecorate_c_symbol ( name, sess, export_kind) else {
25502590 continue ;
25512591 } ;
2552- out. push ( ( undecorated. to_string ( ) , export_kind) ) ;
2592+ out. push ( SymbolExport :: with_link_name (
2593+ undecorated. to_string ( ) ,
2594+ export_kind,
2595+ name. to_string ( ) ,
2596+ ) ) ;
25532597 }
25542598 }
25552599
@@ -2629,7 +2673,14 @@ fn linker_with_args(
26292673 // Pre-link CRT objects.
26302674 add_pre_link_objects ( cmd, sess, flavor, link_output_kind, self_contained_crt_objects) ;
26312675
2632- add_linked_symbol_object ( cmd, sess, tmpdir, & crate_info. linked_symbols [ & crate_type] ) ;
2676+ add_linked_symbol_object (
2677+ cmd,
2678+ sess,
2679+ tmpdir,
2680+ crate_type,
2681+ & crate_info. linked_symbols [ & crate_type] ,
2682+ & export_symbols,
2683+ ) ;
26332684
26342685 // Sanitizer libraries.
26352686 add_sanitizer_libraries ( sess, flavor, crate_type, cmd) ;
0 commit comments