diff --git a/Library/Homebrew/extend/os/mac/diagnostic.rb b/Library/Homebrew/extend/os/mac/diagnostic.rb index cef36ac8f9..799b9a512e 100644 --- a/Library/Homebrew/extend/os/mac/diagnostic.rb +++ b/Library/Homebrew/extend/os/mac/diagnostic.rb @@ -20,6 +20,7 @@ module Homebrew check_xcode_minimum_version check_clt_minimum_version check_if_xcode_needs_clt_installed + check_if_clt_needs_headers_installed ].freeze end @@ -135,6 +136,17 @@ module Homebrew EOS end + def check_if_clt_needs_headers_installed + return unless MacOS::CLT.separate_header_package? + return if MacOS::CLT.headers_installed? + + <<~EOS + The Command Line Tools header package must be installed on #{MacOS.version.pretty_name}. + The installer is located at: + #{MacOS::CLT::HEADER_PKG_PATH.sub(":macos_version", MacOS.version)} + EOS + end + def check_for_other_package_managers ponk = MacOS.macports_or_fink return if ponk.empty? diff --git a/Library/Homebrew/extend/os/mac/system_config.rb b/Library/Homebrew/extend/os/mac/system_config.rb index 20f04c0abd..d92da157b1 100644 --- a/Library/Homebrew/extend/os/mac/system_config.rb +++ b/Library/Homebrew/extend/os/mac/system_config.rb @@ -39,6 +39,12 @@ class SystemConfig end end + def clt_headers + @clt_headers ||= if MacOS::CLT.headers_installed? + MacOS::CLT.headers_version + end + end + def xquartz @xquartz ||= if MacOS::XQuartz.installed? "#{MacOS::XQuartz.version} => #{describe_path(MacOS::XQuartz.prefix)}" @@ -49,6 +55,9 @@ class SystemConfig dump_generic_verbose_config(f) f.puts "macOS: #{MacOS.full_version}-#{kernel}" f.puts "CLT: #{clt ? clt : "N/A"}" + if MacOS::CLT.separate_header_package? + f.puts "CLT headers: #{clt_headers ? clt_headers : "N/A"}" + end f.puts "Xcode: #{xcode ? xcode : "N/A"}" f.puts "XQuartz: #{xquartz ? xquartz : "N/A"}" end diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb index c8a1c40440..b8f0f4031f 100644 --- a/Library/Homebrew/os/mac/xcode.rb +++ b/Library/Homebrew/os/mac/xcode.rb @@ -196,9 +196,13 @@ module OS STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo".freeze FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI".freeze - MAVERICKS_PKG_ID = "com.apple.pkg.CLTools_Executables".freeze + # EXECUTABLE_PKG_ID now means two things: + # 1. The original Mavericks CLT package ID, and + # 2. The additional header package included in Mojave. + EXECUTABLE_PKG_ID = "com.apple.pkg.CLTools_Executables".freeze MAVERICKS_NEW_PKG_ID = "com.apple.pkg.CLTools_Base".freeze # obsolete PKG_PATH = "/Library/Developer/CommandLineTools".freeze + HEADER_PKG_PATH = "/Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_:macos_version.pkg".freeze # Returns true even if outdated tools are installed, e.g. # tools from Xcode 4.x on 10.9 @@ -206,6 +210,18 @@ module OS !version.null? end + def separate_header_package? + MacOS.version >= :mojave + end + + def headers_installed? + if !separate_header_package? + installed? + else + headers_version == version + end + end + def update_instructions if MacOS.version >= "10.9" <<~EOS @@ -282,6 +298,18 @@ module OS end end + # Version string of the header package, which is a + # separate package as of macOS 10.14. + def headers_version + if !separate_header_package? + version + else + @header_version ||= MacOS.pkgutil_info(EXECUTABLE_PKG_ID)[/version: (.+)$/, 1] + return ::Version::NULL unless @header_version + ::Version.new(@header_version) + end + end + def detect_version # CLT isn't a distinct entity pre-4.3, and pkgutil doesn't exist # at all on Tiger, so just count it as installed if Xcode is installed @@ -290,7 +318,7 @@ module OS end version = nil - [MAVERICKS_PKG_ID, MAVERICKS_NEW_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID].each do |id| + [EXECUTABLE_PKG_ID, MAVERICKS_NEW_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID].each do |id| if MacOS.version >= :mavericks next unless File.exist?("#{PKG_PATH}/usr/bin/clang") end diff --git a/Library/Homebrew/test/os/mac/diagnostic_spec.rb b/Library/Homebrew/test/os/mac/diagnostic_spec.rb index 22cbd158f1..d04b592dfb 100644 --- a/Library/Homebrew/test/os/mac/diagnostic_spec.rb +++ b/Library/Homebrew/test/os/mac/diagnostic_spec.rb @@ -32,6 +32,19 @@ describe Homebrew::Diagnostic::Checks do .to match("Xcode alone is not sufficient on El Capitan") end + specify "#check_if_clt_needs_headers_installed" do + allow(MacOS).to receive(:version).and_return(OS::Mac::Version.new("10.14")) + allow(MacOS::CLT).to receive(:installed?).and_return(true) + allow(MacOS::CLT).to receive(:headers_installed?).and_return(false) + + expect(subject.check_if_clt_needs_headers_installed) + .to match("The Command Line Tools header package must be installed on Mojave.") + + allow(MacOS).to receive(:version).and_return(OS::Mac::Version.new("10.13")) + expect(subject.check_if_clt_needs_headers_installed) + .to be_nil + end + specify "#check_homebrew_prefix" do # the integration tests are run in a special prefix expect(subject.check_homebrew_prefix)