@@ -118,6 +118,15 @@ const DLLTOOL_MSVC: &str = "llvm-dlltool";
118118#[ cfg( windows) ]
119119const LIB_MSVC : & str = "lib.exe" ;
120120
121+ /// Python interpreter implementations
122+ #[ derive( Debug , Clone , Copy ) ]
123+ pub enum PythonImplementation {
124+ /// CPython
125+ CPython ,
126+ /// PyPy
127+ PyPy ,
128+ }
129+
121130/// Windows import library generator for Python
122131///
123132/// Generates `python3.dll` or `pythonXY.dll` import library directly from the
@@ -159,6 +168,8 @@ pub struct ImportLibraryGenerator {
159168 env : String ,
160169 /// Major and minor Python version (for `pythonXY.dll` only)
161170 version : Option < ( u8 , u8 ) > ,
171+ /// Python interpreter implementation
172+ implementation : PythonImplementation ,
162173}
163174
164175impl ImportLibraryGenerator {
@@ -174,6 +185,7 @@ impl ImportLibraryGenerator {
174185 arch : arch. to_string ( ) ,
175186 env : env. to_string ( ) ,
176187 version : None ,
188+ implementation : PythonImplementation :: CPython ,
177189 }
178190 }
179191
@@ -185,6 +197,12 @@ impl ImportLibraryGenerator {
185197 self
186198 }
187199
200+ /// Sets Python interpreter implementation
201+ pub fn implementation ( & mut self , implementation : PythonImplementation ) -> & mut Self {
202+ self . implementation = implementation;
203+ self
204+ }
205+
188206 /// Generates the Python DLL import library in `out_dir`.
189207 ///
190208 /// The version-agnostic `python3.dll` import library is generated
@@ -224,14 +242,22 @@ impl ImportLibraryGenerator {
224242 ///
225243 /// Returns the newly created `python3.def` or `pythonXY.def` file path.
226244 fn write_def_file ( & self , out_dir : & Path ) -> Result < PathBuf > {
227- let ( def_file, def_file_content) = match self . version {
228- None => ( "python3.def" , include_str ! ( "python3.def" ) ) ,
229- Some ( ( 3 , 7 ) ) => ( "python37.def" , include_str ! ( "python37.def" ) ) ,
230- Some ( ( 3 , 8 ) ) => ( "python38.def" , include_str ! ( "python38.def" ) ) ,
231- Some ( ( 3 , 9 ) ) => ( "python39.def" , include_str ! ( "python39.def" ) ) ,
232- Some ( ( 3 , 10 ) ) => ( "python310.def" , include_str ! ( "python310.def" ) ) ,
233- Some ( ( 3 , 11 ) ) => ( "python311.def" , include_str ! ( "python311.def" ) ) ,
234- _ => return Err ( Error :: new ( ErrorKind :: Other , "Unsupported Python version" ) ) ,
245+ let ( def_file, def_file_content) = match self . implementation {
246+ PythonImplementation :: CPython => match self . version {
247+ None => ( "python3.def" , include_str ! ( "python3.def" ) ) ,
248+ Some ( ( 3 , 7 ) ) => ( "python37.def" , include_str ! ( "python37.def" ) ) ,
249+ Some ( ( 3 , 8 ) ) => ( "python38.def" , include_str ! ( "python38.def" ) ) ,
250+ Some ( ( 3 , 9 ) ) => ( "python39.def" , include_str ! ( "python39.def" ) ) ,
251+ Some ( ( 3 , 10 ) ) => ( "python310.def" , include_str ! ( "python310.def" ) ) ,
252+ Some ( ( 3 , 11 ) ) => ( "python311.def" , include_str ! ( "python311.def" ) ) ,
253+ _ => return Err ( Error :: new ( ErrorKind :: Other , "Unsupported Python version" ) ) ,
254+ } ,
255+ PythonImplementation :: PyPy => match self . version {
256+ Some ( ( 3 , 7 ) ) => ( "libpypy3-c.def" , include_str ! ( "libpypy3-c.def" ) ) ,
257+ Some ( ( 3 , 8 ) ) => ( "libpypy3-c.def" , include_str ! ( "libpypy3-c.def" ) ) ,
258+ Some ( ( 3 , 9 ) ) => ( "libpypy3.9-c.def" , include_str ! ( "libpypy3.9-c.def" ) ) ,
259+ _ => return Err ( Error :: new ( ErrorKind :: Other , "Unsupported PyPy version" ) ) ,
260+ } ,
235261 } ;
236262
237263 let mut defpath = out_dir. to_owned ( ) ;
@@ -248,11 +274,19 @@ impl ImportLibraryGenerator {
248274 ///
249275 /// Returns the full import library file path under `out_dir`.
250276 fn implib_file_path ( & self , out_dir : & Path , libext : & str ) -> PathBuf {
251- let libname = match self . version {
252- Some ( ( major, minor) ) => {
253- format ! ( "python{}{}{}" , major, minor, libext)
254- }
255- None => format ! ( "python3{}" , libext) ,
277+ let libname = match self . implementation {
278+ PythonImplementation :: CPython => match self . version {
279+ Some ( ( major, minor) ) => {
280+ format ! ( "python{}{}{}" , major, minor, libext)
281+ }
282+ None => format ! ( "python3{}" , libext) ,
283+ } ,
284+ PythonImplementation :: PyPy => match self . version {
285+ Some ( ( major, minor) ) if ( major, minor) >= ( 3 , 9 ) => {
286+ format ! ( "libpypy{}.{}-c{}" , major, minor, libext)
287+ }
288+ _ => format ! ( "libpypy3-c{}" , libext) ,
289+ } ,
256290 } ;
257291
258292 let mut libpath = out_dir. to_owned ( ) ;
@@ -477,6 +511,15 @@ mod tests {
477511 . generate ( & dir)
478512 . unwrap ( ) ;
479513 }
514+
515+ // PyPy
516+ for minor in 7 ..=9 {
517+ ImportLibraryGenerator :: new ( "x86_64" , "gnu" )
518+ . version ( Some ( ( 3 , minor) ) )
519+ . implementation ( PythonImplementation :: PyPy )
520+ . generate ( & dir)
521+ . unwrap ( ) ;
522+ }
480523 }
481524
482525 #[ cfg( unix) ]
@@ -507,6 +550,15 @@ mod tests {
507550 . generate ( & dir)
508551 . unwrap ( ) ;
509552 }
553+
554+ // PyPy
555+ for minor in 7 ..=9 {
556+ ImportLibraryGenerator :: new ( "x86_64" , "msvc" )
557+ . version ( Some ( ( 3 , minor) ) )
558+ . implementation ( PythonImplementation :: PyPy )
559+ . generate ( & dir)
560+ . unwrap ( ) ;
561+ }
510562 }
511563
512564 #[ test]
0 commit comments