diff --git a/Library/Homebrew/extend/os/mac/diagnostic.rb b/Library/Homebrew/extend/os/mac/diagnostic.rb index f6f70440a8..cf5a15b2ba 100644 --- a/Library/Homebrew/extend/os/mac/diagnostic.rb +++ b/Library/Homebrew/extend/os/mac/diagnostic.rb @@ -506,6 +506,42 @@ module OS nil end + + def check_pkgconf_macos_sdk_mismatch + # We don't provide suitable bottles for these versions. + return if OS::Mac.version.prerelease? || OS::Mac.version.outdated_release? + + pkgconf = begin + ::Formula["pkgconf"] + rescue FormulaUnavailableError + nil + end + return unless pkgconf + return unless pkgconf.any_version_installed? + + tab = Tab.for_formula(pkgconf) + return unless tab.built_on + + built_on_version = tab.built_on["os_version"] + &.delete_prefix("macOS ") + &.sub(/\.\d+$/, "") + return unless built_on_version + + current_version = MacOS.version.to_s + return if built_on_version == current_version + + <<~EOS + You have pkgconf installed that was built on macOS #{built_on_version} + but you are running macOS #{current_version}. + + This can cause issues with packages that depend on system libraries, such as libffi. + To fix this issue, reinstall pkgconf: + brew reinstall pkgconf + + For more information, see: https://github.com/Homebrew/brew/issues/16137 + We'd welcome a PR to automatically mitigate this instead of just warning about it. + EOS + end end end end diff --git a/Library/Homebrew/test/os/mac/diagnostic_spec.rb b/Library/Homebrew/test/os/mac/diagnostic_spec.rb index c75a2da2a4..fe7840eabf 100644 --- a/Library/Homebrew/test/os/mac/diagnostic_spec.rb +++ b/Library/Homebrew/test/os/mac/diagnostic_spec.rb @@ -95,4 +95,52 @@ RSpec.describe Homebrew::Diagnostic::Checks do .to include("The contents of the SDKs in your Xcode installation do not match the SDK folder names") end end + + describe "#check_pkgconf_macos_sdk_mismatch" do + let(:pkg_config_formula) { instance_double(Formula, any_version_installed?: true) } + let(:tab) { instance_double(Tab, built_on: { "os_version" => "13" }) } + + before do + allow(Formula).to receive(:[]).with("pkgconf").and_return(pkg_config_formula) + allow(Tab).to receive(:for_formula).with(pkg_config_formula).and_return(tab) + end + + it "doesn't trigger when pkgconf is not installed" do + allow(Formula).to receive(:[]).with("pkgconf").and_raise(FormulaUnavailableError.new("pkgconf")) + + expect(checks.check_pkgconf_macos_sdk_mismatch).to be_nil + end + + it "doesn't trigger when no versions are installed" do + allow(pkg_config_formula).to receive(:any_version_installed?).and_return(false) + + expect(checks.check_pkgconf_macos_sdk_mismatch).to be_nil + end + + it "doesn't trigger when built_on information is missing" do + allow(tab).to receive(:built_on).and_return(nil) + + expect(checks.check_pkgconf_macos_sdk_mismatch).to be_nil + end + + it "doesn't trigger when os_version information is missing" do + allow(tab).to receive(:built_on).and_return({ "cpu_family" => "x86_64" }) + + expect(checks.check_pkgconf_macos_sdk_mismatch).to be_nil + end + + it "doesn't trigger when versions match" do + current_version = MacOS.version.to_s + allow(tab).to receive(:built_on).and_return({ "os_version" => current_version }) + + expect(checks.check_pkgconf_macos_sdk_mismatch).to be_nil + end + + it "triggers when built_on version differs from current macOS version" do + allow(MacOS).to receive(:version).and_return(MacOSVersion.new("14")) + allow(tab).to receive(:built_on).and_return({ "os_version" => "13" }) + + expect(checks.check_pkgconf_macos_sdk_mismatch).to include("brew reinstall pkgconf") + end + end end