Merge pull request #9117 from MikeMcQuaid/handle-arm

Handle macOS Homebrew on ARM
This commit is contained in:
Mike McQuaid 2020-11-12 20:14:30 +00:00 committed by GitHub
commit b43c0fed78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 102 additions and 36 deletions

View File

@ -12,6 +12,7 @@ Style/Documentation:
- 'keg_relocate.rb' - 'keg_relocate.rb'
- 'os/linux/global.rb' - 'os/linux/global.rb'
- 'os/mac/architecture_list.rb' - 'os/mac/architecture_list.rb'
- 'os/mac/global.rb'
- 'os/mac/keg.rb' - 'os/mac/keg.rb'
- 'reinstall.rb' - 'reinstall.rb'
- 'software_spec.rb' - 'software_spec.rb'

View File

@ -164,7 +164,7 @@ rescue BuildError => e
if e.formula.head? || e.formula.deprecated? || e.formula.disabled? if e.formula.head? || e.formula.deprecated? || e.formula.disabled?
$stderr.puts <<~EOS $stderr.puts <<~EOS
Please create pull requests instead of asking for help on Homebrew's GitHub, 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 EOS
end end

View File

@ -15,7 +15,9 @@ BOTTLE_ERB = <<-EOS
<% if root_url != "#{HOMEBREW_BOTTLE_DEFAULT_DOMAIN}/bottles" %> <% if root_url != "#{HOMEBREW_BOTTLE_DEFAULT_DOMAIN}/bottles" %>
root_url "<%= root_url %>" root_url "<%= root_url %>"
<% end %> <% 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 %>" prefix "<%= prefix %>"
<% end %> <% end %>
<% if cellar.is_a? Symbol %> <% if cellar.is_a? Symbol %>

View File

@ -112,8 +112,9 @@ module Homebrew
<<~EOS <<~EOS
You will encounter build failures with some formulae. You will encounter build failures with some formulae.
Please create pull requests instead of asking for help on Homebrew's GitHub, 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 Discourse, Twitter or any other official channels. You are responsible for
experience while you are running this #{what}. resolving any issues you experience while you are running this
#{what}.
EOS EOS
end end

View File

@ -63,6 +63,7 @@ module Homebrew
def supported_configuration_checks def supported_configuration_checks
%w[ %w[
check_for_unsupported_arch
check_for_unsupported_macos check_for_unsupported_macos
].freeze ].freeze
end end
@ -90,21 +91,35 @@ module Homebrew
nil nil
end 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 def check_for_unsupported_macos
return if Homebrew::EnvConfig.developer? 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" who = +"We"
if OS::Mac.prerelease? # TODO: remove when Big Sur is supported.
what = "pre-release version" 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? elsif OS::Mac.outdated_release?
who << " (and Apple)" who << " (and Apple)"
what = "old version" "old version"
else
return
end end
return if what.blank?
who.freeze who.freeze
<<~EOS <<~EOS

View File

@ -64,11 +64,11 @@ module Hardware
[arch_64_bit, arch_32_bit].extend ArchitectureListExtension [arch_64_bit, arch_32_bit].extend ArchitectureListExtension
end 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 # Apple Silicon Mac. This can be detected via seeing if there's a
# conflict between what `uname` reports and the underlying `sysctl` flags, # conflict between what `uname` reports and the underlying `sysctl` flags,
# since the `sysctl` flags don't change behaviour under Rosetta. # since the `sysctl` flags don't change behaviour under Rosetta 2.
def in_rosetta? def in_rosetta2?
intel? && physical_cpu_arm64? intel? && physical_cpu_arm64?
end end
@ -116,14 +116,14 @@ module Hardware
sysctl_bool("hw.optional.sse4_2") sysctl_bool("hw.optional.sse4_2")
end end
private
# Note: this is more reliable than checking uname. # 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? def physical_cpu_arm64?
sysctl_bool("hw.optional.arm64") sysctl_bool("hw.optional.arm64")
end end
private
def sysctl_bool(key) def sysctl_bool(key)
sysctl_int(key) == 1 sysctl_int(key) == 1
end end

View File

@ -51,6 +51,7 @@ module SystemConfig
f.puts "CLT: #{clt || "N/A"}" f.puts "CLT: #{clt || "N/A"}"
f.puts "Xcode: #{xcode || "N/A"}" f.puts "Xcode: #{xcode || "N/A"}"
f.puts "XQuartz: #{xquartz}" if xquartz f.puts "XQuartz: #{xquartz}" if xquartz
f.puts "Rosetta 2: #{Hardware::CPU.in_rosetta2?}" if Hardware::CPU.physical_cpu_arm64?
end end
end end
end end

View File

@ -235,12 +235,17 @@ class FormulaInstaller
recursive_formulae = recursive_deps.map(&:to_formula) recursive_formulae = recursive_deps.map(&:to_formula)
recursive_dependencies = [] recursive_dependencies = []
invalid_arch_dependencies = []
recursive_formulae.each do |dep| recursive_formulae.each do |dep|
dep_recursive_dependencies = dep.recursive_dependencies.map(&:to_s) dep_recursive_dependencies = dep.recursive_dependencies.map(&:to_s)
if dep_recursive_dependencies.include?(formula.name) if dep_recursive_dependencies.include?(formula.name)
recursive_dependencies << "#{formula.full_name} depends on #{dep.full_name}" recursive_dependencies << "#{formula.full_name} depends on #{dep.full_name}"
recursive_dependencies << "#{dep.full_name} depends on #{formula.full_name}" recursive_dependencies << "#{dep.full_name} depends on #{formula.full_name}"
end 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 end
unless recursive_dependencies.empty? unless recursive_dependencies.empty?
@ -258,6 +263,13 @@ class FormulaInstaller
EOS EOS
end 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| pinned_unsatisfied_deps = recursive_deps.select do |dep|
dep.to_formula.pinned? && !dep.satisfied?(inherited_options_for(dep)) dep.to_formula.pinned? && !dep.satisfied?(inherited_options_for(dep))
end end

View File

@ -69,7 +69,8 @@ HOMEBREW_USER_AGENT_FAKE_SAFARI =
"(KHTML, like Gecko) Version/10.0.3 Safari/602.4.8" "(KHTML, like Gecko) Version/10.0.3 Safari/602.4.8"
HOMEBREW_DEFAULT_PREFIX = "/usr/local" 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 "fileutils"
require "os/global" require "os/global"

View File

@ -156,7 +156,7 @@ module Hardware
"-march=#{arch}" "-march=#{arch}"
end end
def in_rosetta? def in_rosetta2?
false false
end end
end end

View File

@ -14,6 +14,7 @@ module Homebrew
module_function module_function
def perform_preinstall_checks(all_fatal: false, cc: nil) def perform_preinstall_checks(all_fatal: false, cc: nil)
check_prefix
check_cpu check_cpu
attempt_directory_creation attempt_directory_creation
check_cc_argv(cc) check_cc_argv(cc)
@ -28,21 +29,35 @@ module Homebrew
Diagnostic.checks(:build_from_source_checks, fatal: all_fatal) Diagnostic.checks(:build_from_source_checks, fatal: all_fatal)
end end
def check_prefix
if Hardware::CPU.intel? && HOMEBREW_PREFIX.to_s == 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.to_s == HOMEBREW_DEFAULT_PREFIX
odie <<~EOS
Cannot install in Homebrew on ARM processor in Intel default prefix (#{HOMEBREW_PREFIX})!
Please create a new installation in #{HOMEBREW_MACOS_ARM_DEFAULT_PREFIX} using one of the
"Alternative Installs" from:
#{Formatter.url("https://docs.brew.sh/Installation")}
You can migrate your previously installed formula list with:
brew bundle dump
EOS
end
end
def check_cpu def check_cpu
return if Hardware::CPU.intel? && Hardware::CPU.is_64_bit? return if Hardware::CPU.intel? && Hardware::CPU.is_64_bit?
message = "Sorry, Homebrew does not support your computer's CPU architecture!" # Handled by check_for_unsupported_arch in extend/os/mac/diagnostic.rb
if Hardware::CPU.arm? return if Hardware::CPU.arm?
opoo message
return return unless Hardware::CPU.ppc?
elsif Hardware::CPU.ppc?
message += <<~EOS odie <<~EOS
Sorry, Homebrew does not support your computer's CPU architecture!
For PowerPC Mac (PPC32/PPC64BE) support, see: For PowerPC Mac (PPC32/PPC64BE) support, see:
#{Formatter.url("https://github.com/mistydemeo/tigerbrew")} #{Formatter.url("https://github.com/mistydemeo/tigerbrew")}
EOS EOS
end end
abort message
end
private_class_method :check_cpu private_class_method :check_cpu
def attempt_directory_creation def attempt_directory_creation

View File

@ -1,4 +1,8 @@
# typed: strict # typed: strict
# frozen_string_literal: true # 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

View File

@ -12,6 +12,6 @@ module Homebrew
DEFAULT_PREFIX ||= if Homebrew::EnvConfig.force_homebrew_on_linux? DEFAULT_PREFIX ||= if Homebrew::EnvConfig.force_homebrew_on_linux?
HOMEBREW_DEFAULT_PREFIX HOMEBREW_DEFAULT_PREFIX
else else
LINUXBREW_DEFAULT_PREFIX HOMEBREW_LINUX_DEFAULT_PREFIX
end.freeze end.freeze
end end

View 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

View File

@ -13404,8 +13404,10 @@ class Object
HOMEBREW_LIBRARY = ::T.let(nil, ::T.untyped) HOMEBREW_LIBRARY = ::T.let(nil, ::T.untyped)
HOMEBREW_LIBRARY_PATH = ::T.let(nil, ::T.untyped) HOMEBREW_LIBRARY_PATH = ::T.let(nil, ::T.untyped)
HOMEBREW_LINKED_KEGS = ::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_LOCKS = ::T.let(nil, ::T.untyped)
HOMEBREW_LOGS = ::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_OFFICIAL_REPO_PREFIXES_REGEX = ::T.let(nil, ::T.untyped)
HOMEBREW_PATCHELF_RB_WRITE = ::T.let(nil, ::T.untyped) HOMEBREW_PATCHELF_RB_WRITE = ::T.let(nil, ::T.untyped)
HOMEBREW_PINNED_KEGS = ::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_VERSION = ::T.let(nil, ::T.untyped)
HOMEBREW_WWW = ::T.let(nil, ::T.untyped) HOMEBREW_WWW = ::T.let(nil, ::T.untyped)
HOMEPAGE_URL = ::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) MAXIMUM_STRING_MATCHES = ::T.let(nil, ::T.untyped)
OFFICIAL_CASK_TAPS = ::T.let(nil, ::T.untyped) OFFICIAL_CASK_TAPS = ::T.let(nil, ::T.untyped)
OFFICIAL_CMD_TAPS = ::T.let(nil, ::T.untyped) OFFICIAL_CMD_TAPS = ::T.let(nil, ::T.untyped)

View File

@ -186,6 +186,7 @@ class Tab < OpenStruct
"compiler" => DevelopmentTools.default_compiler, "compiler" => DevelopmentTools.default_compiler,
"aliases" => [], "aliases" => [],
"runtime_dependencies" => nil, "runtime_dependencies" => nil,
"arch" => nil,
"source" => { "source" => {
"path" => nil, "path" => nil,
"tap" => nil, "tap" => nil,
@ -345,6 +346,7 @@ class Tab < OpenStruct
"aliases" => aliases, "aliases" => aliases,
"runtime_dependencies" => runtime_dependencies, "runtime_dependencies" => runtime_dependencies,
"source" => source, "source" => source,
"arch" => Hardware::CPU.arch,
"built_on" => built_on, "built_on" => built_on,
} }

View File

@ -31,10 +31,11 @@ Just extract (or `git clone`) Homebrew wherever you want. Just avoid:
* `/tmp` subdirectories because Homebrew gets upset. * `/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. * `/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 not build when installed elsewhere. One of the reasons Homebrew just
works relative to the competition is **because** we recommend installing 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 ```sh
mkdir homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew mkdir homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew