From d7ff53fa1ddf649ce8ca3910fc5e901ea4aa5b5a Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Sat, 15 Apr 2017 22:05:26 +0800 Subject: [PATCH 1/2] Hardware: add helper to determine if an executable can be run --- Library/Homebrew/hardware.rb | 12 +++++++ Library/Homebrew/test/hardware_spec.rb | 47 ++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/Library/Homebrew/hardware.rb b/Library/Homebrew/hardware.rb index fe07aee9d3..997598def4 100644 --- a/Library/Homebrew/hardware.rb +++ b/Library/Homebrew/hardware.rb @@ -80,6 +80,18 @@ module Hardware def feature?(name) features.include?(name) end + + def can_run?(arch) + if is_32_bit? + arch_32_bit == arch + elsif intel? + [:i386, :x86_64].include? arch + elsif ppc? + [:ppc, :ppc64].include? arch + else + false + end + end end end diff --git a/Library/Homebrew/test/hardware_spec.rb b/Library/Homebrew/test/hardware_spec.rb index c5f8daf4e0..de8d77e680 100644 --- a/Library/Homebrew/test/hardware_spec.rb +++ b/Library/Homebrew/test/hardware_spec.rb @@ -36,5 +36,52 @@ module Hardware ).to include(described_class.family) end end + + describe "::can_run?" do + it "reports that Intel machines can run Intel executables" do + allow(Hardware::CPU).to receive(:type).and_return :intel + allow(Hardware::CPU).to receive(:bits).and_return 64 + expect(Hardware::CPU.can_run?(:i386)).to be true + expect(Hardware::CPU.can_run?(:x86_64)).to be true + end + + it "reports that PowerPC machines can run PowerPC executables" do + allow(Hardware::CPU).to receive(:type).and_return :ppc + allow(Hardware::CPU).to receive(:bits).and_return 64 + expect(Hardware::CPU.can_run?(:ppc)).to be true + expect(Hardware::CPU.can_run?(:ppc64)).to be true + end + + it "reports that 32-bit Intel machines can't run x86_64 executables" do + allow(Hardware::CPU).to receive(:type).and_return :intel + allow(Hardware::CPU).to receive(:bits).and_return 32 + expect(Hardware::CPU.can_run?(:x86_64)).to be false + end + + it "reports that 32-bit PowerPC machines can't run ppc64 executables" do + allow(Hardware::CPU).to receive(:type).and_return :ppc + allow(Hardware::CPU).to receive(:bits).and_return 32 + expect(Hardware::CPU.can_run?(:ppc64)).to be false + end + + it "identifies that Intel and PowerPC machines can't run each others' executables" do + allow(Hardware::CPU).to receive(:type).and_return :ppc + expect(Hardware::CPU.can_run?(:i386)).to be false + expect(Hardware::CPU.can_run?(:x86_64)).to be false + + allow(Hardware::CPU).to receive(:type).and_return :intel + expect(Hardware::CPU.can_run?(:ppc)).to be false + expect(Hardware::CPU.can_run?(:ppc64)).to be false + end + + it "returns false for unknown CPU types" do + allow(Hardware::CPU).to receive(:type).and_return :dunno + expect(Hardware::CPU.can_run?(:i386)).to be false + end + + it "returns false for unknown arches" do + expect(Hardware::CPU.can_run?(:blah)).to be false + end + end end end From 944bff4de2ec3821480ee9097e06016cce2b2925 Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Sat, 15 Apr 2017 22:05:56 +0800 Subject: [PATCH 2/2] Mac Hardware: provide a more Mac-specific implementation of can_run? --- .../Homebrew/extend/os/mac/hardware/cpu.rb | 43 ++++++++++++++ Library/Homebrew/test/os/mac/hardware_spec.rb | 56 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 Library/Homebrew/test/os/mac/hardware_spec.rb diff --git a/Library/Homebrew/extend/os/mac/hardware/cpu.rb b/Library/Homebrew/extend/os/mac/hardware/cpu.rb index f180995fbb..22d118e1a5 100644 --- a/Library/Homebrew/extend/os/mac/hardware/cpu.rb +++ b/Library/Homebrew/extend/os/mac/hardware/cpu.rb @@ -107,6 +107,20 @@ module Hardware end end + # Determines whether the current CPU and macOS combination + # can run an executable of the specified architecture. + # `arch` is a symbol in the same format returned by + # Hardware::CPU.family + def can_run?(arch) + if Hardware::CPU.intel? + intel_can_run? arch + elsif Hardware::CPU.ppc? + ppc_can_run? arch + else + false + end + end + def features @features ||= sysctl_n( "machdep.cpu.features", @@ -162,6 +176,35 @@ module Hardware @properties[keys] = Utils.popen_read("/usr/sbin/sysctl", "-n", *keys) end end + + def intel_can_run?(arch) + case arch + when :ppc + # Rosetta is still available + MacOS.version < :lion + when :ppc64 + # Rosetta never supported PPC64 + false + when :x86_64 + Hardware::CPU.is_64_bit? + when :i386 + true + else # dunno + false + end + end + + def ppc_can_run?(arch) + case arch + when :ppc + true + when :ppc64 + Hardware::CPU.is_64_bit? + else + # Intel is never supported + false + end + end end end end diff --git a/Library/Homebrew/test/os/mac/hardware_spec.rb b/Library/Homebrew/test/os/mac/hardware_spec.rb new file mode 100644 index 0000000000..fa577ba7d6 --- /dev/null +++ b/Library/Homebrew/test/os/mac/hardware_spec.rb @@ -0,0 +1,56 @@ +require "hardware" +require "extend/os/mac/hardware/cpu" + +describe Hardware::CPU do + describe "::can_run?" do + it "reports that Intel Macs can run Intel executables" do + allow(Hardware::CPU).to receive(:type).and_return :intel + allow(Hardware::CPU).to receive(:bits).and_return 64 + expect(Hardware::CPU.can_run?(:i386)).to be true + expect(Hardware::CPU.can_run?(:x86_64)).to be true + end + + it "reports that PowerPC Macs can run PowerPC executables" do + allow(Hardware::CPU).to receive(:type).and_return :ppc + allow(Hardware::CPU).to receive(:bits).and_return 64 + expect(Hardware::CPU.can_run?(:ppc)).to be true + expect(Hardware::CPU.can_run?(:ppc64)).to be true + end + + it "reports that 32-bit Intel Macs can't run x86_64 executables" do + allow(Hardware::CPU).to receive(:type).and_return :intel + allow(Hardware::CPU).to receive(:bits).and_return 32 + expect(Hardware::CPU.can_run?(:x86_64)).to be false + end + + it "reports that 32-bit PowerPC Macs can't run ppc64 executables" do + allow(Hardware::CPU).to receive(:type).and_return :ppc + allow(Hardware::CPU).to receive(:bits).and_return 32 + expect(Hardware::CPU.can_run?(:ppc64)).to be false + end + + it "reports that Intel Macs can only run 32-bit PowerPC executables on 10.6 and older" do + allow(Hardware::CPU).to receive(:type).and_return :intel + allow(OS::Mac).to receive(:version).and_return OS::Mac::Version.new "10.6" + expect(Hardware::CPU.can_run?(:ppc)).to be true + + allow(OS::Mac).to receive(:version).and_return OS::Mac::Version.new "10.7" + expect(Hardware::CPU.can_run?(:ppc)).to be false + end + + it "reports that PowerPC Macs can't run Intel executables" do + allow(Hardware::CPU).to receive(:type).and_return :ppc + expect(Hardware::CPU.can_run?(:i386)).to be false + expect(Hardware::CPU.can_run?(:x86_64)).to be false + end + + it "returns false for unknown CPU types" do + allow(Hardware::CPU).to receive(:type).and_return :dunno + expect(Hardware::CPU.can_run?(:i386)).to be false + end + + it "returns false for unknown arches" do + expect(Hardware::CPU.can_run?(:blah)).to be false + end + end +end