From e7902348fe11281e13dc9d1a25b68347ae744425 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sat, 6 Apr 2024 17:07:44 +0530 Subject: [PATCH] Never pick up Strawberry Perl's pkg-config as a valid implementation Strawberry Perl places a `pkg-config.bat` into PATH that is written in Perl and is not intended to be used by third parties as a MinGW distribution. This wouldn't matter, except that Strawberry Perl is also included in Github CI images out of the box, in `PATH`, and it breaks everyone's CI jobs. This is already done by Meson and CMake: https://github.com/mesonbuild/meson/pull/9384 https://gitlab.kitware.com/cmake/cmake/-/merge_requests/9375 Fixes https://github.com/rust-lang/pkg-config-rs/issues/164 --- src/lib.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3b9a359..b386b47 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,7 +92,7 @@ use std::fmt; use std::fmt::Display; use std::io; use std::ops::{Bound, RangeBounds}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::{Command, Output}; use std::str; @@ -652,6 +652,53 @@ impl Config { self.statik.unwrap_or_else(|| self.infer_static(name)) } + fn pkg_config_from_path(&self) -> OsString { + if cfg!(target_os = "windows") { + // Resolve pkg-config in PATH to find the absolute path to pkg-config that we should + // use, so that we can skip Strawberry Perl's pure-perl implementation of pkg-config, + // which (despite its presence in PATH) is for internal use and not meant to be used as + // a MinGW distribution. + let pathexts = env::var_os("PATHEXT").map_or_else( + || Vec::from(["COM", "EXE", "BAT"].map(|v| OsStr::new(v).to_owned())), + |v| { + env::split_paths(&v) + .map(|v| v.into_os_string()) + .collect::>() + }, + ); + if let Some(paths) = env::var_os("PATH") { + for mut path in env::split_paths(&paths) { + path.push("pkg-config"); + for pathext in &pathexts { + path.set_extension(pathext); + if !path.is_file() { + continue; + } + // Strawberry Perl's pkg-config is pkg-config.bat + if *pathext == "bat" || *pathext == "BAT" { + let mut cmd = Command::new(path.as_os_str()); + let out = match cmd.output() { + Ok(o) => o, + Err(e) => { + eprintln!("Ignoring unusable pkg-config ({:?}): {:?}", path, e); + continue; + } + }; + if let Ok(out) = str::from_utf8(&out.stdout) { + if out.contains("Pure-Perl") { + eprintln!("Ignoring Strawberry Perl pkg-config: {:?}", path); + continue; + } + }; + } + return path.into_os_string(); + } + } + } + } + OsString::from("pkg-config") + } + fn run(&self, name: &str, args: &[&str]) -> Result, Error> { let pkg_config_exe = self.targeted_env_var("PKG_CONFIG"); let fallback_exe = if pkg_config_exe.is_none() { @@ -659,7 +706,7 @@ impl Config { } else { None }; - let exe = pkg_config_exe.unwrap_or_else(|| OsString::from("pkg-config")); + let exe = pkg_config_exe.unwrap_or_else(|| self.pkg_config_from_path()); let mut cmd = self.command(exe, name, args);