Handle macOS Homebrew on ARM
- Output `brew doctor` and `brew install` messages noting this configuration is (currently) unsupported and encourage use of Rosetta instead - Output Rosetta 2 usage in `brew config` on ARM (whether in Rosetta 2 or not) - Check the architecture of (newly installed) dependencies and ensure they are using the correct architecture. - Don't allow installing macOS Intel Homebrew in macOS ARM Homebrew default prefix (and vice versa - Actually write out the architecture of dependencies to the tab rather than generating and throwing them away - Set and document the expected default prefix for macOS Intel Homebrew, macOS ARM Homebrew (`/opt/homebrew`) and Homebrew on Linux While we're here: - Don't say Big Sur is a prerelease version but still make it clear we don't support it (yet). - Don't reference non-existent IRC channel
This commit is contained in:
		
							parent
							
								
									8cffae872e
								
							
						
					
					
						commit
						5afff3f3aa
					
				@ -12,6 +12,7 @@ Style/Documentation:
 | 
			
		||||
    - 'keg_relocate.rb'
 | 
			
		||||
    - 'os/linux/global.rb'
 | 
			
		||||
    - 'os/mac/architecture_list.rb'
 | 
			
		||||
    - 'os/mac/global.rb'
 | 
			
		||||
    - 'os/mac/keg.rb'
 | 
			
		||||
    - 'reinstall.rb'
 | 
			
		||||
    - 'software_spec.rb'
 | 
			
		||||
 | 
			
		||||
@ -164,7 +164,7 @@ rescue BuildError => e
 | 
			
		||||
  if e.formula.head? || e.formula.deprecated? || e.formula.disabled?
 | 
			
		||||
    $stderr.puts <<~EOS
 | 
			
		||||
      Please create pull requests instead of asking for help on Homebrew's GitHub,
 | 
			
		||||
      Discourse, Twitter or IRC.
 | 
			
		||||
      Discourse, Twitter or any other official channels.
 | 
			
		||||
    EOS
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,9 @@ BOTTLE_ERB = <<-EOS
 | 
			
		||||
    <% if  root_url != "#{HOMEBREW_BOTTLE_DEFAULT_DOMAIN}/bottles" %>
 | 
			
		||||
    root_url "<%= root_url %>"
 | 
			
		||||
    <% end  %>
 | 
			
		||||
    <% if  ![HOMEBREW_DEFAULT_PREFIX, LINUXBREW_DEFAULT_PREFIX].include?(prefix) %>
 | 
			
		||||
    <% if  ![HOMEBREW_DEFAULT_PREFIX,
 | 
			
		||||
            HOMEBREW_MACOS_ARM_DEFAULT_PREFIX,
 | 
			
		||||
            HOMEBREW_LINUX_DEFAULT_PREFIX].include?(prefix) %>
 | 
			
		||||
    prefix "<%= prefix %>"
 | 
			
		||||
    <% end  %>
 | 
			
		||||
    <% if  cellar.is_a? Symbol %>
 | 
			
		||||
 | 
			
		||||
@ -112,8 +112,9 @@ module Homebrew
 | 
			
		||||
        <<~EOS
 | 
			
		||||
          You will encounter build failures with some formulae.
 | 
			
		||||
          Please create pull requests instead of asking for help on Homebrew's GitHub,
 | 
			
		||||
          Discourse, Twitter or IRC. You are responsible for resolving any issues you
 | 
			
		||||
          experience while you are running this #{what}.
 | 
			
		||||
          Discourse, Twitter or any other official channels. You are responsible for
 | 
			
		||||
          resolving any issues you experience while you are running this
 | 
			
		||||
          #{what}.
 | 
			
		||||
        EOS
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -63,6 +63,7 @@ module Homebrew
 | 
			
		||||
 | 
			
		||||
      def supported_configuration_checks
 | 
			
		||||
        %w[
 | 
			
		||||
          check_for_unsupported_arch
 | 
			
		||||
          check_for_unsupported_macos
 | 
			
		||||
        ].freeze
 | 
			
		||||
      end
 | 
			
		||||
@ -90,21 +91,35 @@ module Homebrew
 | 
			
		||||
        nil
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def check_for_unsupported_arch
 | 
			
		||||
        return if Homebrew::EnvConfig.developer?
 | 
			
		||||
        return unless Hardware::CPU.arm?
 | 
			
		||||
 | 
			
		||||
        <<~EOS
 | 
			
		||||
          You are running macOS on a #{Hardware::CPU.arch} CPU architecture.
 | 
			
		||||
          We do not provide support for this (yet).
 | 
			
		||||
          Reinstall Homebrew under Rosetta 2 until we support it.
 | 
			
		||||
          #{please_create_pull_requests}
 | 
			
		||||
        EOS
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def check_for_unsupported_macos
 | 
			
		||||
        return if Homebrew::EnvConfig.developer?
 | 
			
		||||
 | 
			
		||||
        # TODO: remove when Big Sur is released.
 | 
			
		||||
        return if MacOS.version == :big_sur && ENV["HOMEBREW_GITHUB_ACTIONS_BIG_SUR_TESTING"]
 | 
			
		||||
 | 
			
		||||
        who = +"We"
 | 
			
		||||
        if OS::Mac.prerelease?
 | 
			
		||||
          what = "pre-release version"
 | 
			
		||||
        # TODO: remove when Big Sur is supported.
 | 
			
		||||
        what = if MacOS.version == :big_sur
 | 
			
		||||
          return if ENV["HOMEBREW_GITHUB_ACTIONS_BIG_SUR_TESTING"]
 | 
			
		||||
 | 
			
		||||
          "released but not yet supported version"
 | 
			
		||||
        elsif OS::Mac.prerelease?
 | 
			
		||||
          "pre-release version"
 | 
			
		||||
        elsif OS::Mac.outdated_release?
 | 
			
		||||
          who << " (and Apple)"
 | 
			
		||||
          what = "old version"
 | 
			
		||||
        else
 | 
			
		||||
          return
 | 
			
		||||
          "old version"
 | 
			
		||||
        end
 | 
			
		||||
        return if what.blank?
 | 
			
		||||
 | 
			
		||||
        who.freeze
 | 
			
		||||
 | 
			
		||||
        <<~EOS
 | 
			
		||||
 | 
			
		||||
@ -64,11 +64,11 @@ module Hardware
 | 
			
		||||
        [arch_64_bit, arch_32_bit].extend ArchitectureListExtension
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # True when running under an Intel-based shell via Rosetta on an
 | 
			
		||||
      # True when running under an Intel-based shell via Rosetta 2 on an
 | 
			
		||||
      # Apple Silicon Mac. This can be detected via seeing if there's a
 | 
			
		||||
      # conflict between what `uname` reports and the underlying `sysctl` flags,
 | 
			
		||||
      # since the `sysctl` flags don't change behaviour under Rosetta.
 | 
			
		||||
      def in_rosetta?
 | 
			
		||||
      # since the `sysctl` flags don't change behaviour under Rosetta 2.
 | 
			
		||||
      def in_rosetta2?
 | 
			
		||||
        intel? && physical_cpu_arm64?
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
@ -116,14 +116,14 @@ module Hardware
 | 
			
		||||
        sysctl_bool("hw.optional.sse4_2")
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      # Note: this is more reliable than checking uname.
 | 
			
		||||
      # `sysctl` returns the right answer even when running in Rosetta.
 | 
			
		||||
      # `sysctl` returns the right answer even when running in Rosetta 2.
 | 
			
		||||
      def physical_cpu_arm64?
 | 
			
		||||
        sysctl_bool("hw.optional.arm64")
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      def sysctl_bool(key)
 | 
			
		||||
        sysctl_int(key) == 1
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
@ -51,6 +51,7 @@ module SystemConfig
 | 
			
		||||
      f.puts "CLT: #{clt || "N/A"}"
 | 
			
		||||
      f.puts "Xcode: #{xcode || "N/A"}"
 | 
			
		||||
      f.puts "XQuartz: #{xquartz}" if xquartz
 | 
			
		||||
      f.puts "Rosetta 2: #{Hardware::CPU.in_rosetta2?}" if Hardware::CPU.physical_cpu_arm64?
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -235,12 +235,17 @@ class FormulaInstaller
 | 
			
		||||
    recursive_formulae = recursive_deps.map(&:to_formula)
 | 
			
		||||
 | 
			
		||||
    recursive_dependencies = []
 | 
			
		||||
    invalid_arch_dependencies = []
 | 
			
		||||
    recursive_formulae.each do |dep|
 | 
			
		||||
      dep_recursive_dependencies = dep.recursive_dependencies.map(&:to_s)
 | 
			
		||||
      if dep_recursive_dependencies.include?(formula.name)
 | 
			
		||||
        recursive_dependencies << "#{formula.full_name} depends on #{dep.full_name}"
 | 
			
		||||
        recursive_dependencies << "#{dep.full_name} depends on #{formula.full_name}"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if (tab = Tab.for_formula(dep)) && tab.arch.present? && tab.arch.to_s != Hardware::CPU.arch.to_s
 | 
			
		||||
        invalid_arch_dependencies << "#{dep} was built for #{tab.arch}"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    unless recursive_dependencies.empty?
 | 
			
		||||
@ -258,6 +263,13 @@ class FormulaInstaller
 | 
			
		||||
      EOS
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    unless invalid_arch_dependencies.empty?
 | 
			
		||||
      raise CannotInstallFormulaError, <<~EOS
 | 
			
		||||
        #{formula.full_name} dependencies not built for the #{Hardware::CPU.arch} CPU architecture:
 | 
			
		||||
          #{invalid_arch_dependencies.join("\n  ")}
 | 
			
		||||
      EOS
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    pinned_unsatisfied_deps = recursive_deps.select do |dep|
 | 
			
		||||
      dep.to_formula.pinned? && !dep.satisfied?(inherited_options_for(dep))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
@ -69,7 +69,8 @@ HOMEBREW_USER_AGENT_FAKE_SAFARI =
 | 
			
		||||
  "(KHTML, like Gecko) Version/10.0.3 Safari/602.4.8"
 | 
			
		||||
 | 
			
		||||
HOMEBREW_DEFAULT_PREFIX = "/usr/local"
 | 
			
		||||
LINUXBREW_DEFAULT_PREFIX = "/home/linuxbrew/.linuxbrew"
 | 
			
		||||
HOMEBREW_MACOS_ARM_DEFAULT_PREFIX = "/opt/homebrew"
 | 
			
		||||
HOMEBREW_LINUX_DEFAULT_PREFIX = "/home/linuxbrew/.linuxbrew"
 | 
			
		||||
 | 
			
		||||
require "fileutils"
 | 
			
		||||
require "os/global"
 | 
			
		||||
 | 
			
		||||
@ -156,7 +156,7 @@ module Hardware
 | 
			
		||||
        "-march=#{arch}"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def in_rosetta?
 | 
			
		||||
      def in_rosetta2?
 | 
			
		||||
        false
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@ module Homebrew
 | 
			
		||||
    module_function
 | 
			
		||||
 | 
			
		||||
    def perform_preinstall_checks(all_fatal: false, cc: nil)
 | 
			
		||||
      check_prefix
 | 
			
		||||
      check_cpu
 | 
			
		||||
      attempt_directory_creation
 | 
			
		||||
      check_cc_argv(cc)
 | 
			
		||||
@ -28,20 +29,27 @@ module Homebrew
 | 
			
		||||
      Diagnostic.checks(:build_from_source_checks, fatal: all_fatal)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def check_prefix
 | 
			
		||||
      if Hardware::CPU.intel? && HOMEBREW_PREFIX == HOMEBREW_MACOS_ARM_DEFAULT_PREFIX
 | 
			
		||||
        odie "Cannot install in Homebrew on Intel processor in ARM default prefix (#{HOMEBREW_PREFIX})!"
 | 
			
		||||
      elsif Hardware::CPU.arm? && HOMEBREW_PREFIX == HOMEBREW_DEFAULT_PREFIX
 | 
			
		||||
        odie "Cannot install in Homebrew on ARM processor in Intel default prefix (#{HOMEBREW_PREFIX})!"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def check_cpu
 | 
			
		||||
      return if Hardware::CPU.intel? && Hardware::CPU.is_64_bit?
 | 
			
		||||
 | 
			
		||||
      message = "Sorry, Homebrew does not support your computer's CPU architecture!"
 | 
			
		||||
      if Hardware::CPU.arm?
 | 
			
		||||
        opoo message
 | 
			
		||||
        return
 | 
			
		||||
      elsif Hardware::CPU.ppc?
 | 
			
		||||
        message += <<~EOS
 | 
			
		||||
          For PowerPC Mac (PPC32/PPC64BE) support, see:
 | 
			
		||||
            #{Formatter.url("https://github.com/mistydemeo/tigerbrew")}
 | 
			
		||||
        EOS
 | 
			
		||||
      end
 | 
			
		||||
      abort message
 | 
			
		||||
      # Handled by check_for_unsupported_arch in extend/os/mac/diagnostic.rb
 | 
			
		||||
      return if Hardware::CPU.arm?
 | 
			
		||||
 | 
			
		||||
      return unless Hardware::CPU.ppc?
 | 
			
		||||
 | 
			
		||||
      odie <<~EOS
 | 
			
		||||
        Sorry, Homebrew does not support your computer's CPU architecture!
 | 
			
		||||
        For PowerPC Mac (PPC32/PPC64BE) support, see:
 | 
			
		||||
          #{Formatter.url("https://github.com/mistydemeo/tigerbrew")}
 | 
			
		||||
      EOS
 | 
			
		||||
    end
 | 
			
		||||
    private_class_method :check_cpu
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,8 @@
 | 
			
		||||
# typed: strict
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "os/linux/global" if OS.linux?
 | 
			
		||||
if OS.mac?
 | 
			
		||||
  require "os/mac/global"
 | 
			
		||||
elsif OS.linux?
 | 
			
		||||
  require "os/linux/global"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -12,6 +12,6 @@ module Homebrew
 | 
			
		||||
  DEFAULT_PREFIX ||= if Homebrew::EnvConfig.force_homebrew_on_linux?
 | 
			
		||||
    HOMEBREW_DEFAULT_PREFIX
 | 
			
		||||
  else
 | 
			
		||||
    LINUXBREW_DEFAULT_PREFIX
 | 
			
		||||
    HOMEBREW_LINUX_DEFAULT_PREFIX
 | 
			
		||||
  end.freeze
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								Library/Homebrew/os/mac/global.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Library/Homebrew/os/mac/global.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
# typed: false
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module Homebrew
 | 
			
		||||
  DEFAULT_PREFIX ||= if Hardware::CPU.arm?
 | 
			
		||||
    HOMEBREW_MACOS_ARM_DEFAULT_PREFIX
 | 
			
		||||
  else
 | 
			
		||||
    HOMEBREW_DEFAULT_PREFIX
 | 
			
		||||
  end.freeze
 | 
			
		||||
end
 | 
			
		||||
@ -13404,8 +13404,10 @@ class Object
 | 
			
		||||
  HOMEBREW_LIBRARY = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  HOMEBREW_LIBRARY_PATH = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  HOMEBREW_LINKED_KEGS = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  HOMEBREW_LINUX_DEFAULT_PREFIX = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  HOMEBREW_LOCKS = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  HOMEBREW_LOGS = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  HOMEBREW_MACOS_ARM_DEFAULT_PREFIX = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  HOMEBREW_OFFICIAL_REPO_PREFIXES_REGEX = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  HOMEBREW_PATCHELF_RB_WRITE = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  HOMEBREW_PINNED_KEGS = ::T.let(nil, ::T.untyped)
 | 
			
		||||
@ -13428,7 +13430,6 @@ class Object
 | 
			
		||||
  HOMEBREW_VERSION = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  HOMEBREW_WWW = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  HOMEPAGE_URL = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  LINUXBREW_DEFAULT_PREFIX = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  MAXIMUM_STRING_MATCHES = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  OFFICIAL_CASK_TAPS = ::T.let(nil, ::T.untyped)
 | 
			
		||||
  OFFICIAL_CMD_TAPS = ::T.let(nil, ::T.untyped)
 | 
			
		||||
 | 
			
		||||
@ -186,6 +186,7 @@ class Tab < OpenStruct
 | 
			
		||||
      "compiler"                => DevelopmentTools.default_compiler,
 | 
			
		||||
      "aliases"                 => [],
 | 
			
		||||
      "runtime_dependencies"    => nil,
 | 
			
		||||
      "arch"                    => nil,
 | 
			
		||||
      "source"                  => {
 | 
			
		||||
        "path"     => nil,
 | 
			
		||||
        "tap"      => nil,
 | 
			
		||||
@ -345,6 +346,7 @@ class Tab < OpenStruct
 | 
			
		||||
      "aliases"                 => aliases,
 | 
			
		||||
      "runtime_dependencies"    => runtime_dependencies,
 | 
			
		||||
      "source"                  => source,
 | 
			
		||||
      "arch"                    => Hardware::CPU.arch,
 | 
			
		||||
      "built_on"                => built_on,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -31,10 +31,11 @@ Just extract (or `git clone`) Homebrew wherever you want. Just avoid:
 | 
			
		||||
* `/tmp` subdirectories because Homebrew gets upset.
 | 
			
		||||
* `/sw` and `/opt/local` because build scripts get confused when Homebrew is there instead of Fink or MacPorts, respectively.
 | 
			
		||||
 | 
			
		||||
However do yourself a favour and install to `/usr/local`. Some things may
 | 
			
		||||
However do yourself a favour and install to `/usr/local` on macOS Intel, `/opt/homebrew` on macOS ARM
 | 
			
		||||
and `.home/linuxbrew/.linuxbrew` on Linux. Some things may
 | 
			
		||||
not build when installed elsewhere. One of the reasons Homebrew just
 | 
			
		||||
works relative to the competition is **because** we recommend installing
 | 
			
		||||
to `/usr/local`. *Pick another prefix at your peril!*
 | 
			
		||||
here. *Pick another prefix at your peril!*
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
mkdir homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user