Skip to content

Commit 18d1ac8

Browse files
committed
Add support for generating non-abi3 pythonXY.dll
1 parent d591bfc commit 18d1ac8

File tree

2 files changed

+56
-29
lines changed

2 files changed

+56
-29
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ fn main() {
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
}

src/lib.rs

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
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};
8080
use std::path::Path;
8181
use 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
9690
const 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> {
177198
fn 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

Comments
 (0)