5656//! let env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap();
5757//!
5858//! let libdir = std::path::Path::new(&cross_lib_dir);
59- //! python3_dll_a::generate_implib_for_target(libdir, &arch, &env)
59+ //! python3_dll_a::generate_implib_for_target(None, libdir, &arch, &env)
6060//! .expect("python3.dll import library generator failed");
6161//! }
6262//! }
@@ -80,17 +80,11 @@ use std::io::{Error, ErrorKind, Result};
8080use std:: path:: Path ;
8181use std:: process:: Command ;
8282
83- /// Module-Definition file name for `python3.dll`
84- const DEF_FILE : & str = "python3.def " ;
83+ /// Import library file extension for the GNU environment ABI (MinGW-w64)
84+ const IMPLIB_EXT_GNU : & str = ".dll.a " ;
8585
86- /// Module-Definition file content for `python3.dll`
87- const DEF_FILE_CONTENT : & [ u8 ] = include_bytes ! ( "python3.def" ) ;
88-
89- /// Canonical `python3.dll` import library file name for the GNU environment ABI (MinGW-w64)
90- const IMPLIB_FILE_GNU : & str = "python3.dll.a" ;
91-
92- /// Canonical `python3.dll` import library file name for the MSVC environment ABI
93- const IMPLIB_FILE_MSVC : & str = "python3.lib" ;
86+ /// Import library file extension for the MSVC environment ABI
87+ const IMPLIB_EXT_MSVC : & str = ".lib" ;
9488
9589/// Canonical MinGW-w64 `dlltool` program name
9690const DLLTOOL_GNU : & str = "x86_64-w64-mingw32-dlltool" ;
@@ -115,26 +109,52 @@ const LIB_MSVC: &str = "lib.exe";
115109///
116110/// The compile target environment ABI name (as in `CARGO_CFG_TARGET_ENV`)
117111/// is passed in `env`.
118- pub fn generate_implib_for_target ( out_dir : & Path , arch : & str , env : & str ) -> Result < ( ) > {
112+ pub fn generate_implib_for_target (
113+ version : Option < ( u8 , u8 ) > ,
114+ out_dir : & Path ,
115+ arch : & str ,
116+ env : & str ,
117+ ) -> Result < ( ) > {
119118 create_dir_all ( out_dir) ?;
120119
121120 let mut defpath = out_dir. to_owned ( ) ;
122- defpath. push ( DEF_FILE ) ;
121+ let ( def_file, def_file_content) = match version {
122+ None => ( "python3.def" , include_str ! ( "python3.def" ) ) ,
123+ Some ( ( 3 , 7 ) ) => ( "python37.def" , include_str ! ( "python37.def" ) ) ,
124+ Some ( ( 3 , 8 ) ) => ( "python38.def" , include_str ! ( "python38.def" ) ) ,
125+ Some ( ( 3 , 9 ) ) => ( "python39.def" , include_str ! ( "python39.def" ) ) ,
126+ Some ( ( 3 , 10 ) ) => ( "python310.def" , include_str ! ( "python310.def" ) ) ,
127+ Some ( ( 3 , 11 ) ) => ( "python311.def" , include_str ! ( "python311.def" ) ) ,
128+ _ => return Err ( Error :: new ( ErrorKind :: Other , "Unsupported Python version" ) ) ,
129+ } ;
130+ defpath. push ( def_file) ;
123131
124- write ( & defpath, DEF_FILE_CONTENT ) ?;
132+ write ( & defpath, def_file_content ) ?;
125133
126134 // Try to guess the `dlltool` executable name from the target triple.
127- let ( command, dlltool) = match ( arch, env) {
135+ let ( command, dlltool, implib_file ) = match ( arch, env) {
128136 // 64-bit MinGW-w64 (aka x86_64-pc-windows-gnu)
129- ( "x86_64" , "gnu" ) => ( Command :: new ( DLLTOOL_GNU ) , DLLTOOL_GNU ) ,
137+ ( "x86_64" , "gnu" ) => (
138+ Command :: new ( DLLTOOL_GNU ) ,
139+ DLLTOOL_GNU ,
140+ def_file. replace ( ".def" , IMPLIB_EXT_GNU ) ,
141+ ) ,
130142 // 32-bit MinGW-w64 (aka i686-pc-windows-gnu)
131- ( "x86" , "gnu" ) => ( Command :: new ( DLLTOOL_GNU_32 ) , DLLTOOL_GNU_32 ) ,
143+ ( "x86" , "gnu" ) => (
144+ Command :: new ( DLLTOOL_GNU_32 ) ,
145+ DLLTOOL_GNU_32 ,
146+ def_file. replace ( ".def" , IMPLIB_EXT_GNU ) ,
147+ ) ,
132148 // MSVC ABI (multiarch)
133149 ( _, "msvc" ) => {
134150 if let Some ( command) = find_lib_exe ( arch) {
135- ( command, LIB_MSVC )
151+ ( command, LIB_MSVC , def_file . replace ( ".def" , IMPLIB_EXT_MSVC ) )
136152 } else {
137- ( Command :: new ( DLLTOOL_MSVC ) , DLLTOOL_MSVC )
153+ (
154+ Command :: new ( DLLTOOL_MSVC ) ,
155+ DLLTOOL_MSVC ,
156+ def_file. replace ( ".def" , IMPLIB_EXT_MSVC ) ,
157+ )
138158 }
139159 }
140160 _ => {
@@ -144,7 +164,8 @@ pub fn generate_implib_for_target(out_dir: &Path, arch: &str, env: &str) -> Resu
144164 } ;
145165
146166 // Run the selected `dlltool` executable to generate the import library.
147- let status = build_dlltool_command ( command, dlltool, arch, & defpath, out_dir) . status ( ) ?;
167+ let status =
168+ build_dlltool_command ( command, dlltool, & implib_file, arch, & defpath, out_dir) . status ( ) ?;
148169
149170 if status. success ( ) {
150171 Ok ( ( ) )
@@ -177,6 +198,7 @@ fn find_lib_exe(_arch: &str) -> Option<Command> {
177198fn build_dlltool_command (
178199 mut command : Command ,
179200 dlltool : & str ,
201+ implib_file : & str ,
180202 arch : & str ,
181203 defpath : & Path ,
182204 out_dir : & Path ,
@@ -185,7 +207,7 @@ fn build_dlltool_command(
185207
186208 // Check whether we are using LLVM `dlltool` or MinGW `dlltool`.
187209 if dlltool == DLLTOOL_MSVC {
188- libpath. push ( IMPLIB_FILE_MSVC ) ;
210+ libpath. push ( implib_file ) ;
189211
190212 // LLVM tools use their own target architecture names...
191213 let machine = match arch {
@@ -203,7 +225,7 @@ fn build_dlltool_command(
203225 . arg ( "-l" )
204226 . arg ( libpath) ;
205227 } else if dlltool == LIB_MSVC {
206- libpath. push ( IMPLIB_FILE_MSVC ) ;
228+ libpath. push ( implib_file ) ;
207229
208230 // lib.exe use their own target architecure names...
209231 let machine = match arch {
@@ -217,7 +239,7 @@ fn build_dlltool_command(
217239 . arg ( format ! ( "/DEF:{}" , defpath. display( ) ) )
218240 . arg ( format ! ( "/OUT:{}" , libpath. display( ) ) ) ;
219241 } else {
220- libpath. push ( IMPLIB_FILE_GNU ) ;
242+ libpath. push ( implib_file ) ;
221243
222244 command
223245 . arg ( "--input-def" )
@@ -244,7 +266,12 @@ mod tests {
244266 dir. push ( "x86_64-pc-windows-gnu" ) ;
245267 dir. push ( "python3-dll" ) ;
246268
247- generate_implib_for_target ( & dir, "x86_64" , "gnu" ) . unwrap ( ) ;
269+ generate_implib_for_target ( None , & dir, "x86_64" , "gnu" ) . unwrap ( ) ;
270+ generate_implib_for_target ( Some ( ( 3 , 7 ) ) , & dir, "x86_64" , "gnu" ) . unwrap ( ) ;
271+ generate_implib_for_target ( Some ( ( 3 , 8 ) ) , & dir, "x86_64" , "gnu" ) . unwrap ( ) ;
272+ generate_implib_for_target ( Some ( ( 3 , 9 ) ) , & dir, "x86_64" , "gnu" ) . unwrap ( ) ;
273+ generate_implib_for_target ( Some ( ( 3 , 10 ) ) , & dir, "x86_64" , "gnu" ) . unwrap ( ) ;
274+ generate_implib_for_target ( Some ( ( 3 , 11 ) ) , & dir, "x86_64" , "gnu" ) . unwrap ( ) ;
248275 }
249276
250277 #[ cfg( unix) ]
@@ -255,7 +282,7 @@ mod tests {
255282 dir. push ( "i686-pc-windows-gnu" ) ;
256283 dir. push ( "python3-dll" ) ;
257284
258- generate_implib_for_target ( & dir, "x86" , "gnu" ) . unwrap ( ) ;
285+ generate_implib_for_target ( None , & dir, "x86" , "gnu" ) . unwrap ( ) ;
259286 }
260287
261288 #[ test]
@@ -265,7 +292,7 @@ mod tests {
265292 dir. push ( "x86_64-pc-windows-msvc" ) ;
266293 dir. push ( "python3-dll" ) ;
267294
268- generate_implib_for_target ( & dir, "x86_64" , "msvc" ) . unwrap ( ) ;
295+ generate_implib_for_target ( None , & dir, "x86_64" , "msvc" ) . unwrap ( ) ;
269296 }
270297
271298 #[ test]
@@ -275,7 +302,7 @@ mod tests {
275302 dir. push ( "i686-pc-windows-msvc" ) ;
276303 dir. push ( "python3-dll" ) ;
277304
278- generate_implib_for_target ( & dir, "x86" , "msvc" ) . unwrap ( ) ;
305+ generate_implib_for_target ( None , & dir, "x86" , "msvc" ) . unwrap ( ) ;
279306 }
280307
281308 #[ test]
@@ -285,6 +312,6 @@ mod tests {
285312 dir. push ( "aarch64-pc-windows-msvc" ) ;
286313 dir. push ( "python3-dll" ) ;
287314
288- generate_implib_for_target ( & dir, "aarch64" , "msvc" ) . unwrap ( ) ;
315+ generate_implib_for_target ( None , & dir, "aarch64" , "msvc" ) . unwrap ( ) ;
289316 }
290317}
0 commit comments