Skip to content

Commit 846860c

Browse files
committed
Add support for PyPy
1 parent 719bab5 commit 846860c

File tree

1 file changed

+65
-13
lines changed

1 file changed

+65
-13
lines changed

src/lib.rs

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ const DLLTOOL_MSVC: &str = "llvm-dlltool";
118118
#[cfg(windows)]
119119
const 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

164175
impl 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

Comments
 (0)