@@ -9,7 +9,7 @@ use std::ptr;
9
9
use std:: str;
10
10
11
11
use crate :: llvm:: archive_ro:: { ArchiveRO , Child } ;
12
- use crate :: llvm:: { self , ArchiveKind , LLVMMachineType , LLVMRustCOFFShortExport } ;
12
+ use crate :: llvm:: { self , ArchiveKind , LLVMMachineType , LLVMRustCOFFShortExport , LLVMRustTbdExport } ;
13
13
use rustc_codegen_ssa:: back:: archive:: { ArchiveBuilder , ArchiveBuilderBuilder } ;
14
14
use rustc_session:: cstore:: { DllCallingConvention , DllImport } ;
15
15
use rustc_session:: Session ;
@@ -104,33 +104,102 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
104
104
dll_imports : & [ DllImport ] ,
105
105
tmpdir : & Path ,
106
106
) -> 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
+
107
112
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)
111
120
} ;
112
121
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
-
119
122
let import_name_and_ordinal_vector: Vec < ( String , Option < u16 > ) > = dll_imports
120
123
. iter ( )
121
124
. map ( |import : & DllImport | {
122
- if sess. target . arch == "x86" {
125
+ if sess. target . arch == "x86" && windows_toolchain {
123
126
(
124
127
LlvmArchiveBuilder :: i686_decorated_name ( import, mingw_gnu_toolchain) ,
125
128
import. ordinal ,
126
129
)
130
+ } else if apple_toolchain {
131
+ ( format ! ( "_{}" , import. name) , import. ordinal )
127
132
} else {
128
133
( import. name . to_string ( ) , import. ordinal )
129
134
}
130
135
} )
131
136
. collect ( ) ;
132
137
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 {
134
203
// The binutils linker used on -windows-gnu targets cannot read the import
135
204
// libraries generated by LLVM: in our attempts, the linker produced an .EXE
136
205
// that loaded but crashed with an AV upon calling one of the imported
0 commit comments