diff --git a/src/bindgen/cargo/cargo_metadata.rs b/src/bindgen/cargo/cargo_metadata.rs index 25c9fe40e..2d96dc435 100644 --- a/src/bindgen/cargo/cargo_metadata.rs +++ b/src/bindgen/cargo/cargo_metadata.rs @@ -176,6 +176,41 @@ impl PartialEq for Dependency { impl Eq for Dependency {} +fn discover_target(manifest_path: &Path) -> Option { + if let Ok(target) = std::env::var("TARGET") { + return Some(target); + } + + // We must be running as a standalone script, not under cargo. + // Let's use the host platform instead. + // We figure out the host platform through rustc and use that. + // We unfortunatelly cannot go through cargo, since cargo rustc _also_ builds. + // If `rustc` fails to run, we just fall back to not passing --filter-platforms. + // + // NOTE: We set the current directory in case of rustup shenanigans. + let rustc = env::var("RUSTC").unwrap_or_else(|_| String::from("rustc")); + debug!("Discovering host platform by {:?}", rustc); + + let rustc_output = Command::new(rustc) + .current_dir(manifest_path.parent().unwrap()) + .arg("-vV") + .output(); + let rustc_output = match rustc_output { + Ok(ref out) => String::from_utf8_lossy(&out.stdout), + Err(..) => return None, + }; + + let field = "host: "; + rustc_output.lines().find_map(|l| { + // XXX l.strip_prefix(field) re-implemented to preserve MSRV + if l.starts_with(field) { + Some(l[field.len()..].into()) + } else { + None + } + }) +} + /// The main entry point to obtaining metadata pub fn metadata( manifest_path: &Path, @@ -186,49 +221,18 @@ pub fn metadata( let metadata = match existing_metadata_file { Some(path) => Cow::Owned(std::fs::read_to_string(path)?), None => { - let mut target = None; - - if only_target { - target = std::env::var_os("TARGET"); - } - - if only_target && target.is_none() { - // We must be running as a standalone script, not under cargo. - // Let's use the host platform instead. - // We figure out the host platform through rustc and use that. - // We unfortunatelly cannot go through cargo, since cargo rustc _also_ builds. - // If `rustc` fails to run, we just fall back to not passing --filter-platforms. - // - // NOTE: We set the current directory in case of rustup shenanigans. - let rustc = env::var("RUSTC").unwrap_or_else(|_| String::from("rustc")); - let rustc = Command::new(rustc) - .current_dir(manifest_path.parent().unwrap()) - .arg("-vV") - .output(); - log::debug!("Discovering host platform by {:?}", rustc); - if let Ok(out) = rustc { - if let Ok(stdout) = std::str::from_utf8(&out.stdout) { - let field = "host: "; - let value = stdout.lines().find_map(|l| { - // XXX l.strip_prefix(field) re-implemented to preserve MSRV - if l.starts_with(field) { - Some(&l[field.len()..]) - } else { - None - } - }); - if let Some(value) = value { - target = Some(value.into()); - } - } - } + let target = if only_target { + let target = discover_target(manifest_path); if target.is_none() { - log::warn!( + warn!( "Failed to discover host platform for cargo metadata; \ will fetch dependencies for all platforms." ); } - } + target + } else { + None + }; let cargo = env::var("CARGO").unwrap_or_else(|_| String::from("cargo")); let mut cmd = Command::new(cargo); diff --git a/src/bindgen/config.rs b/src/bindgen/config.rs index ab242321a..d229bd8fc 100644 --- a/src/bindgen/config.rs +++ b/src/bindgen/config.rs @@ -968,6 +968,10 @@ pub struct Config { /// If this value is instead to `true`, cbindgen will _not_ download the `windows` dependency /// if it's not compiling for Windows, but will also fail to generate a Windows binding for /// `Error` as it does not know the definition for `ErrorCode`. + /// + /// The target can be chosen via the `TARGET` environment variable (if used + /// via the CLI, when ran from a build script cargo sets this variable + /// appropriately). pub only_target_dependencies: bool, /// Configuration options specific to Cython. pub cython: CythonConfig,