Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions guide/src/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ strip = true
# Source distribution generator,
# supports cargo (default) and git.
sdist-generator = "cargo"
# Include the Windows import library (.dll.lib or .dll.a) in the wheel.
# This is useful when distributing shared libraries that other programs
# need to link against at compile time.
include-import-lib = false
# Use base Python executable instead of venv Python executable in PEP 517 build.
#
# This can help avoid unnecessary rebuilds, as the Python executable does not change
Expand Down
5 changes: 5 additions & 0 deletions maturin.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@
"$ref": "#/$defs/GlobPattern"
}
},
"include-import-lib": {
"description": "Include the import library (.dll.lib) in the wheel on Windows",
"type": "boolean",
"default": false
},
"locked": {
"description": "Require Cargo.lock is up to date",
"type": [
Expand Down
19 changes: 19 additions & 0 deletions src/binding_generator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@ where
}
}
}

// 4a. Install import library on Windows
if let Some(import_lib) = &artifact.import_lib_path
&& context.include_import_lib
{
let target = base_path.join(import_lib.file_name().unwrap());
fs::create_dir_all(target.parent().unwrap())?;
debug!("Installing import library {}", target.display());
fs::copy(import_lib, &target)?;
}
}
_ => {
// 2b. Install the artifact
Expand All @@ -213,6 +223,15 @@ where
writer.add_entry_force(target, source)?;
}
}

// 4b. Install import library on Windows
if let Some(import_lib) = &artifact.import_lib_path
&& context.include_import_lib
{
let dest = module.join(import_lib.file_name().unwrap());
debug!("Adding import library to archive {}", dest.display());
writer.add_file_force(dest, import_lib, false)?;
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/build_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ pub struct BuildContext {
pub pypi_validation: bool,
/// SBOM configuration
pub sbom: Option<SbomConfig>,
/// Include the import library (.dll.lib) in the wheel on Windows
pub include_import_lib: bool,
}

/// The wheel file location and its Python version tag (e.g. `py3`).
Expand Down
4 changes: 4 additions & 0 deletions src/build_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,9 @@ impl BuildContextBuilder {
}

let crate_name = cargo_toml.package.name;
let include_import_lib = pyproject
.map(|p| p.include_import_lib())
.unwrap_or_default();
Ok(BuildContext {
target,
compile_targets,
Expand All @@ -912,6 +915,7 @@ impl BuildContextBuilder {
compression: build_options.compression,
pypi_validation,
sbom,
include_import_lib,
})
}
}
Expand Down
60 changes: 39 additions & 21 deletions src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub struct CompileTarget {
pub struct BuildArtifact {
/// Path to the build artifact
pub path: PathBuf,
/// Path to the Windows import library (.dll.lib or .dll.a), if any
pub import_lib_path: Option<PathBuf>,
/// Array of paths to include in the library search path, as indicated by
/// the `cargo:rustc-link-search` instruction.
pub linked_paths: Vec<String>,
Expand Down Expand Up @@ -143,6 +145,7 @@ fn compile_universal2(
let mut result = HashMap::new();
let universal_artifact = BuildArtifact {
path: PathBuf::from(output_path),
import_lib_path: None,
linked_paths: x86_64_artifact.linked_paths.clone(),
};
result.insert(build_type, universal_artifact);
Expand Down Expand Up @@ -564,27 +567,42 @@ fn compile_target(

// Extract the location of the .so/.dll/etc. from cargo's json output
if crate_name.as_ref() == context.crate_name {
let tuples = artifact
.target
.crate_types
.into_iter()
.zip(artifact.filenames);
for (crate_type, filename) in tuples {
let path = if using_cross && filename.starts_with("/target") {
// Convert cross target path in docker back to path on host
context
.cargo_metadata
.target_directory
.join(filename.strip_prefix("/target").unwrap())
.into_std_path_buf()
} else {
filename.into()
};
let artifact = BuildArtifact {
path,
linked_paths: Vec::new(),
};
artifacts.insert(crate_type, artifact);
let num_crate_types = artifact.target.crate_types.len();
let mut filenames_iter = artifact.filenames.into_iter();
for crate_type in artifact.target.crate_types {
if let Some(filename) = filenames_iter.next() {
let path = if using_cross && filename.starts_with("/target") {
// Convert cross target path in docker back to path on host
context
.cargo_metadata
.target_directory
.join(filename.strip_prefix("/target").unwrap())
.into_std_path_buf()
} else {
filename.into()
};
let artifact = BuildArtifact {
path,
import_lib_path: None,
linked_paths: Vec::new(),
};
artifacts.insert(crate_type, artifact);
}
}
// Remaining filenames may include import libraries (.dll.lib, .dll.a)
if num_crate_types == 1
&& let Some((_, artifact)) = artifacts.iter_mut().next()
{
for extra in filenames_iter {
let extra_path: PathBuf = extra.into();
if extra_path
.extension()
.is_some_and(|ext| ext == "lib" || ext == "a")
{
artifact.import_lib_path = Some(extra_path);
break;
}
}
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/pyproject_toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,9 @@ pub struct ToolMaturin {
pub use_base_python: bool,
/// SBOM configuration
pub sbom: Option<SbomConfig>,
/// Include the import library (.dll.lib) in the wheel on Windows
#[serde(default)]
pub include_import_lib: bool,
}

/// A pyproject.toml as specified in PEP 517
Expand Down Expand Up @@ -440,6 +443,13 @@ impl PyProjectToml {
self.maturin()?.manifest_path.as_deref()
}

/// Returns the value of `[tool.maturin.include-import-lib]` in pyproject.toml
pub fn include_import_lib(&self) -> bool {
self.maturin()
.map(|maturin| maturin.include_import_lib)
.unwrap_or_default()
}

/// Warn about `build-system.requires` mismatching expectations.
///
/// Having a pyproject.toml without a version constraint is a bad idea
Expand Down
1 change: 1 addition & 0 deletions test-crates/cffi-pure/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ dynamic = ["version"]

[tool.maturin]
bindings = "cffi"
include-import-lib = true
Loading