@@ -9,7 +9,7 @@ use std::ptr;
99use std:: str;
1010
1111use crate :: llvm:: archive_ro:: { ArchiveRO , Child } ;
12- use crate :: llvm:: { self , ArchiveKind , LLVMMachineType , LLVMRustCOFFShortExport } ;
12+ use crate :: llvm:: { self , ArchiveKind , LLVMMachineType , LLVMRustCOFFShortExport , LLVMRustTbdExport } ;
1313use rustc_codegen_ssa:: back:: archive:: { ArchiveBuilder , ArchiveBuilderBuilder } ;
1414use rustc_session:: cstore:: { DllCallingConvention , DllImport } ;
1515use rustc_session:: Session ;
@@ -104,33 +104,102 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
104104 dll_imports : & [ DllImport ] ,
105105 tmpdir : & Path ,
106106 ) -> PathBuf {
107+ let target = & sess. target ;
108+ let windows_toolchain = target. vendor == "pc" && target. os == "windows" ;
109+ let mingw_gnu_toolchain = windows_toolchain && target. env == "gnu" && target. abi . is_empty ( ) ;
110+ let apple_toolchain = target. is_like_osx ;
111+
107112 let output_path = {
108- let mut output_path: PathBuf = tmpdir. to_path_buf ( ) ;
109- output_path. push ( format ! ( "{}_imports" , lib_name) ) ;
110- output_path. with_extension ( "lib" )
113+ let mut filename = lib_name. replace ( '/' , "_" ) ;
114+ if apple_toolchain {
115+ filename. push_str ( "tbd" ) ;
116+ } else {
117+ filename. push_str ( "lib" ) ;
118+ }
119+ tmpdir. join ( filename)
111120 } ;
112121
113- let target = & sess. target ;
114- let mingw_gnu_toolchain = target. vendor == "pc"
115- && target. os == "windows"
116- && target. env == "gnu"
117- && target. abi . is_empty ( ) ;
118-
119122 let import_name_and_ordinal_vector: Vec < ( String , Option < u16 > ) > = dll_imports
120123 . iter ( )
121124 . map ( |import : & DllImport | {
122- if sess. target . arch == "x86" {
125+ if sess. target . arch == "x86" && windows_toolchain {
123126 (
124127 LlvmArchiveBuilder :: i686_decorated_name ( import, mingw_gnu_toolchain) ,
125128 import. ordinal ,
126129 )
130+ } else if apple_toolchain {
131+ ( format ! ( "_{}" , import. name) , import. ordinal )
127132 } else {
128133 ( import. name . to_string ( ) , import. ordinal )
129134 }
130135 } )
131136 . collect ( ) ;
132137
133- if mingw_gnu_toolchain {
138+ if apple_toolchain {
139+ // we've checked for \0 characters in the library name already
140+ let dll_name_z = CString :: new ( lib_name) . unwrap ( ) ;
141+
142+ let output_path_z = rustc_fs_util:: path_to_c_string ( & output_path) ;
143+
144+ tracing:: info!( "invoking LLVMRustWriteTbdFile" ) ;
145+ tracing:: info!( " dll_name {:#?}" , dll_name_z) ;
146+ tracing:: info!( " output_path {}" , output_path. display( ) ) ;
147+ tracing:: info!(
148+ " import names: {}" ,
149+ dll_imports
150+ . iter( )
151+ . map( |import| import. name. to_string( ) )
152+ . collect:: <Vec <_>>( )
153+ . join( ", " ) ,
154+ ) ;
155+
156+ let cstring_import_name_vector: Vec < CString > = import_name_and_ordinal_vector
157+ . into_iter ( )
158+ . map ( |( name, _ordinal) | CString :: new ( name) . unwrap ( ) )
159+ . collect ( ) ;
160+
161+ let ffi_exports: Vec < LLVMRustTbdExport > = cstring_import_name_vector
162+ . iter ( )
163+ . map ( |name_z| LLVMRustTbdExport :: new ( name_z. as_ptr ( ) , 0 ) )
164+ . collect ( ) ;
165+
166+ // Get LLVM architecture from the target triple.
167+ let arch = sess. target . llvm_target . split ( "-" ) . nth ( 0 ) . unwrap ( ) ;
168+
169+ let plat = match ( & * target. options . os , & * target. options . abi ) {
170+ ( "macos" , "" ) => "macos" ,
171+ ( "ios" , "" ) => "ios" ,
172+ ( "tvos" , "" ) => "tvos" ,
173+ ( "watchos" , "" ) => "watchos" ,
174+ ( "macos" , "macabi" ) => "maccatalyst" ,
175+ ( "ios" , "sim" ) => "ios-simulator" ,
176+ ( "tvos" , "sim" ) => "tvos-simulator" ,
177+ ( "watchos" , "sim" ) => "watchos-simulator" ,
178+ _ => "unknown" ,
179+ } ;
180+
181+ let target = CString :: new ( format ! ( "{}-{}" , arch, plat) ) . unwrap ( ) ;
182+ let ffi_targets = & [ target. as_ptr ( ) ] ;
183+
184+ let result = unsafe {
185+ crate :: llvm:: LLVMRustWriteTbdFile (
186+ dll_name_z. as_ptr ( ) ,
187+ output_path_z. as_ptr ( ) ,
188+ ffi_exports. as_ptr ( ) ,
189+ ffi_exports. len ( ) ,
190+ ffi_targets. as_ptr ( ) ,
191+ ffi_targets. len ( ) ,
192+ )
193+ } ;
194+
195+ if result == crate :: llvm:: LLVMRustResult :: Failure {
196+ sess. fatal ( & format ! (
197+ "Error creating apple import library for {}: {}" ,
198+ lib_name,
199+ llvm:: last_error( ) . unwrap_or( "unknown LLVM error" . to_string( ) )
200+ ) ) ;
201+ }
202+ } else if mingw_gnu_toolchain {
134203 // The binutils linker used on -windows-gnu targets cannot read the import
135204 // libraries generated by LLVM: in our attempts, the linker produced an .EXE
136205 // that loaded but crashed with an AV upon calling one of the imported
0 commit comments