Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow users to specify a crate version for bindings generation #901

Merged
merged 1 commit into from
Feb 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 19 additions & 6 deletions src/bindgen/cargo/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl Cargo {
}

pub(crate) fn binding_crate_ref(&self) -> PackageRef {
match self.find_pkg_ref(&self.binding_crate_name) {
match self.find_pkg_to_generate_bindings_ref(&self.binding_crate_name) {
Some(pkg_ref) => pkg_ref,
None => panic!(
"Unable to find {} for {:?}",
Expand Down Expand Up @@ -180,15 +180,28 @@ impl Cargo {
.collect()
}

/// Finds the package reference in `cargo metadata` that has `package_name`
/// ignoring the version.
fn find_pkg_ref(&self, package_name: &str) -> Option<PackageRef> {
/// Finds the package reference for which we want to generate bindings in `cargo metadata`
/// matching on `package_name` and verifying the manifest path matches so that we don't get a
/// a dependency with the same name (fix for https://github.com/mozilla/cbindgen/issues/900)
fn find_pkg_to_generate_bindings_ref(&self, package_name: &str) -> Option<PackageRef> {
// Keep a list of candidates in case the manifest check fails, so that the old behavior
// still applies, returning the first package that was found
let mut candidates = vec![];
for package in &self.metadata.packages {
if package.name_and_version.name == package_name {
return Some(package.name_and_version.clone());
// If we are sure it is the right package return it
if Path::new(package.manifest_path.as_str()) == self.manifest_path {
return Some(package.name_and_version.clone());
}
// Otherwise note that a package was found
candidates.push(package.name_and_version.clone());
}
}
None

// If we could not verify the manifest path but we found candidates return the first one if
// any, this is the old behavior which did not check for manifest path, kept for backwards
// compatibility
candidates.into_iter().next()
}

/// Finds the directory for a specified package reference.
Expand Down