Skip to content

Commit 160085d

Browse files
committed
refactor: Break down generate() into smaller fns
Add two private helper methods `write_def_file()` and `implib_file_name()`. Expand the docstrings on some public items.
1 parent d3794f5 commit 160085d

File tree

1 file changed

+71
-52
lines changed

1 file changed

+71
-52
lines changed

src/lib.rs

Lines changed: 71 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
use std::ffi::OsStr;
8080
use std::fs::{create_dir_all, write};
8181
use std::io::{Error, ErrorKind, Result};
82-
use std::path::Path;
82+
use std::path::{Path, PathBuf};
8383
use std::process::Command;
8484

8585
/// Import library file extension for the GNU environment ABI (MinGW-w64)
@@ -110,12 +110,18 @@ pub struct ImportLibraryGenerator {
110110
arch: String,
111111
// The compile target environment ABI name (as in `CARGO_CFG_TARGET_ENV`)
112112
env: String,
113-
/// Python major and minor version
113+
/// Major and minor Python version (for `pythonXY.dll` only)
114114
version: Option<(u8, u8)>,
115115
}
116116

117117
impl ImportLibraryGenerator {
118-
/// Creates a new import library generator for the specified compile target
118+
/// Creates a new import library generator for the specified compile target.
119+
///
120+
/// The compile target architecture name (as in `CARGO_CFG_TARGET_ARCH`)
121+
/// is passed in `arch`.
122+
///
123+
/// The compile target environment ABI name (as in `CARGO_CFG_TARGET_ENV`)
124+
/// is passed in `env`.
119125
pub fn new(arch: &str, env: &str) -> Self {
120126
Self {
121127
arch: arch.to_string(),
@@ -124,62 +130,37 @@ impl ImportLibraryGenerator {
124130
}
125131
}
126132

127-
/// Set python major and minor version
133+
/// Sets major and minor version for the `pythonXY.dll` import library.
134+
///
135+
/// The version-agnostic `python3.dll` is generated by default.
128136
pub fn version(&mut self, version: Option<(u8, u8)>) -> &mut Self {
129137
self.version = version;
130138
self
131139
}
132140

133-
/// Generates the import library in `out_dir`
141+
/// Generates the Python DLL import library in `out_dir`.
142+
///
143+
/// The version-agnostic `python3.dll` import library is generated
144+
/// by default unless the version-specific `pythonXY.dll` import
145+
/// was requested via `version()`.
134146
pub fn generate(&self, out_dir: &Path) -> Result<()> {
135147
create_dir_all(out_dir)?;
136148

137-
let mut defpath = out_dir.to_owned();
138-
let (def_file, def_file_content) = match self.version {
139-
None => ("python3.def", include_str!("python3.def")),
140-
Some((3, 7)) => ("python37.def", include_str!("python37.def")),
141-
Some((3, 8)) => ("python38.def", include_str!("python38.def")),
142-
Some((3, 9)) => ("python39.def", include_str!("python39.def")),
143-
Some((3, 10)) => ("python310.def", include_str!("python310.def")),
144-
Some((3, 11)) => ("python311.def", include_str!("python311.def")),
145-
_ => return Err(Error::new(ErrorKind::Other, "Unsupported Python version")),
146-
};
147-
defpath.push(def_file);
148-
149-
write(&defpath, def_file_content)?;
149+
let defpath = self.write_def_file(out_dir)?;
150+
let implib_file = self.implib_file_path(out_dir);
150151

151-
let impllib_ext = if self.env == "msvc" {
152-
IMPLIB_EXT_MSVC
153-
} else {
154-
IMPLIB_EXT_GNU
155-
};
156-
let implib_file = match self.version {
157-
Some((major, minor)) => {
158-
format!("python{}{}{}", major, minor, impllib_ext)
159-
}
160-
None => format!("python3{}", impllib_ext),
161-
};
162152
// Try to guess the `dlltool` executable name from the target triple.
163153
let mut command = match (self.arch.as_str(), self.env.as_str()) {
164154
// 64-bit MinGW-w64 (aka x86_64-pc-windows-gnu)
165-
("x86_64", "gnu") => {
166-
self.build_dlltool_command(DLLTOOL_GNU, &implib_file, &defpath, out_dir)
167-
}
155+
("x86_64", "gnu") => self.build_dlltool_command(DLLTOOL_GNU, &implib_file, &defpath),
168156
// 32-bit MinGW-w64 (aka i686-pc-windows-gnu)
169-
("x86", "gnu") => {
170-
self.build_dlltool_command(DLLTOOL_GNU_32, &implib_file, &defpath, out_dir)
171-
}
157+
("x86", "gnu") => self.build_dlltool_command(DLLTOOL_GNU_32, &implib_file, &defpath),
172158
// MSVC ABI (multiarch)
173159
(_, "msvc") => {
174160
if let Some(command) = find_lib_exe(&self.arch) {
175-
self.build_dlltool_command(
176-
command.get_program(),
177-
&implib_file,
178-
&defpath,
179-
out_dir,
180-
)
161+
self.build_dlltool_command(command.get_program(), &implib_file, &defpath)
181162
} else {
182-
self.build_dlltool_command(DLLTOOL_MSVC, &implib_file, &defpath, out_dir)
163+
self.build_dlltool_command(DLLTOOL_MSVC, &implib_file, &defpath)
183164
}
184165
}
185166
_ => {
@@ -205,18 +186,61 @@ impl ImportLibraryGenerator {
205186
}
206187
}
207188

189+
/// Writes out the embedded Python library definitions file to `out_dir`.
190+
///
191+
/// Returns the newly created `python3.def` or `pythonXY.def` file path.
192+
fn write_def_file(&self, out_dir: &Path) -> Result<PathBuf> {
193+
let (def_file, def_file_content) = match self.version {
194+
None => ("python3.def", include_str!("python3.def")),
195+
Some((3, 7)) => ("python37.def", include_str!("python37.def")),
196+
Some((3, 8)) => ("python38.def", include_str!("python38.def")),
197+
Some((3, 9)) => ("python39.def", include_str!("python39.def")),
198+
Some((3, 10)) => ("python310.def", include_str!("python310.def")),
199+
Some((3, 11)) => ("python311.def", include_str!("python311.def")),
200+
_ => return Err(Error::new(ErrorKind::Other, "Unsupported Python version")),
201+
};
202+
203+
let mut defpath = out_dir.to_owned();
204+
defpath.push(def_file);
205+
206+
write(&defpath, def_file_content)?;
207+
208+
Ok(defpath)
209+
}
210+
211+
/// Builds the generated import library file name.
212+
///
213+
/// Returns the full import library file path under `out_dir`.
214+
fn implib_file_path(&self, out_dir: &Path) -> PathBuf {
215+
let libext = if self.env == "msvc" {
216+
IMPLIB_EXT_MSVC
217+
} else {
218+
IMPLIB_EXT_GNU
219+
};
220+
221+
let libname = match self.version {
222+
Some((major, minor)) => {
223+
format!("python{}{}{}", major, minor, libext)
224+
}
225+
None => format!("python3{}", libext),
226+
};
227+
228+
let mut libpath = out_dir.to_owned();
229+
libpath.push(libname);
230+
231+
libpath
232+
}
233+
208234
/// Generates the complete `dlltool` executable invocation command.
209235
///
210236
/// Supports Visual Studio `lib.exe`, LLVM and MinGW `dlltool` flavors.
211237
fn build_dlltool_command(
212238
&self,
213239
dlltool: impl AsRef<OsStr>,
214-
implib_file: &str,
240+
libpath: &Path,
215241
defpath: &Path,
216-
out_dir: &Path,
217242
) -> Command {
218243
let dlltool = dlltool.as_ref();
219-
let mut libpath = out_dir.to_owned();
220244
let mut command = if self.env == "msvc" {
221245
find_lib_exe(&self.arch).unwrap_or_else(|| Command::new(dlltool))
222246
} else {
@@ -225,8 +249,6 @@ impl ImportLibraryGenerator {
225249

226250
// Check whether we are using LLVM `dlltool` or MinGW `dlltool`.
227251
if dlltool == DLLTOOL_MSVC {
228-
libpath.push(implib_file);
229-
230252
// LLVM tools use their own target architecture names...
231253
let machine = match self.arch.as_str() {
232254
"x86_64" => "i386:x86-64",
@@ -243,8 +265,6 @@ impl ImportLibraryGenerator {
243265
.arg("-l")
244266
.arg(libpath);
245267
} else if Path::new(dlltool).file_name() == Some(LIB_MSVC.as_ref()) {
246-
libpath.push(implib_file);
247-
248268
// lib.exe use their own target architecure names...
249269
let machine = match self.arch.as_str() {
250270
"x86_64" => "X64",
@@ -257,8 +277,6 @@ impl ImportLibraryGenerator {
257277
.arg(format!("/DEF:{}", defpath.display()))
258278
.arg(format!("/OUT:{}", libpath.display()));
259279
} else {
260-
libpath.push(implib_file);
261-
262280
command
263281
.arg("--input-def")
264282
.arg(defpath)
@@ -285,7 +303,7 @@ pub fn generate_implib_for_target(out_dir: &Path, arch: &str, env: &str) -> Resu
285303
ImportLibraryGenerator::new(arch, env).generate(out_dir)
286304
}
287305

288-
/// Find Visual Studio lib.exe on Windows
306+
/// Finds Visual Studio `lib.exe` when running on Windows.
289307
#[cfg(windows)]
290308
fn find_lib_exe(arch: &str) -> Option<Command> {
291309
let target = match arch {
@@ -294,6 +312,7 @@ fn find_lib_exe(arch: &str) -> Option<Command> {
294312
"aarch64" => "aarch64-pc-windows-msvc",
295313
_ => return None,
296314
};
315+
297316
cc::windows_registry::find(target, LIB_MSVC)
298317
}
299318

0 commit comments

Comments
 (0)