Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SimulateSystem improvements #13599

Merged
merged 4 commits into from
Jul 28, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 4 additions & 12 deletions Library/Homebrew/extend/on_system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ module OnSystem
def arch_condition_met?(arch)
raise ArgumentError, "Invalid arch condition: #{arch.inspect}" if ARCH_OPTIONS.exclude?(arch)

current_arch = Homebrew::SimulateSystem.arch || Hardware::CPU.type
arch == current_arch
arch == Homebrew::SimulateSystem.current_arch
end

sig { params(os_name: Symbol, or_condition: T.nilable(Symbol)).returns(T::Boolean) }
Expand All @@ -26,25 +25,18 @@ def os_condition_met?(os_name, or_condition = nil)
return true if [:macos, *MacOSVersions::SYMBOLS.keys].include?(os_name)
end

if BASE_OS_OPTIONS.include?(os_name)
if Homebrew::SimulateSystem.none?
return OS.linux? if os_name == :linux
return OS.mac? if os_name == :macos
end

return Homebrew::SimulateSystem.send("#{os_name}?")
end
return Homebrew::SimulateSystem.send("treat_as_#{os_name}?") if BASE_OS_OPTIONS.include?(os_name)

raise ArgumentError, "Invalid OS condition: #{os_name.inspect}" unless MacOSVersions::SYMBOLS.key?(os_name)

if or_condition.present? && [:or_newer, :or_older].exclude?(or_condition)
raise ArgumentError, "Invalid OS `or_*` condition: #{or_condition.inspect}"
end

return false if Homebrew::SimulateSystem.linux? || (Homebrew::SimulateSystem.none? && OS.linux?)
return false if Homebrew::SimulateSystem.treat_as_linux?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return false if Homebrew::SimulateSystem.treat_as_linux?
return false if Homebrew::SimulateSystem.simulating_linux?

is another option

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I prefer the original because if we aren't simulating Linux but are actually on it, we still need to return true. I can see the word "simulate" being misleading

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I really don't understand this then I think 😅. Why not do a OS.linux? check?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do this:

return false if Homebrew::SimulateSystem.os == :linux || OS.linux?

Then the condition will be true when we're simulating macOS on Linux (because Homebrew::SimulateSystem.os will be :macos (or a specific version) and OS.linux? will still be true). We only want this condition to be true when we're simulating Linux or we are on Linux and not simulating anything. So, the full check needs to be:

return false if Homebrew::SimulateSystem.os == :linux || (Homebrew::SimulateSystem.os.blank? && OS.linux?)

The Homebrew::SimulateSystem.treat_as_linux? method is just a shortcut for this longer conditional.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we want some sort of OS.linux_no_really_not_simulated?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH, I don't see why we don't want OS.mac? and OS.linux? to lie when we ask it to (with HOMEBREW_SIMULATE_MACOS_ON_LINUX, or even HOMEBREW_SIMULATE_LINUX_ON_MACOS). But I'll admit to not having thought about this very hard or looked for corner cases.

I also don't really have a problem with #simulating_linux? being true even if the system really is running Linux, and it's not a simulation.

Are there cases where we want to distinguish between a machine that is running Linux with another machine running macOS, but the developer wants to trick brew into thinking its running Linux?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there cases where we want to distinguish between a machine that is running Linux with another machine running macOS, but the developer wants to trick brew into thinking its running Linux?

One instance might be that trying to brew install anything on macOS while simulating Linux might lead to a bad time. But do we really need guardrails here for users in this position? What if they actually really wanted to brew install some Linux software on macOS (perhaps for testing purposes)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But do we really need guardrails here for users in this position?

Probably not...? The only way for a user to activate any simulation stuff is through HOMEBREW_SIMULATE_MACOS_ON_LINUX, and I think it seems pretty clear that using that variable may cause problems if you don't know what you're doing. If we get weird bug reports where people are trying to set that unnecessarily, we can add a warning or undocumented it or something.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which case it seems to me that we should be fine with #simulating_linux?, no? Because we don't really need to distinguish between a real Linux machine and one only pretending to be Linux.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH, I don't see why we don't want OS.mac? and OS.linux? to lie when we ask it to (with HOMEBREW_SIMULATE_MACOS_ON_LINUX, or even HOMEBREW_SIMULATE_LINUX_ON_MACOS). But I'll admit to not having thought about this very hard or looked for corner cases.

I don't think they necessarily should but the argument for them doing so is that it's useful to be able to e.g. generate information for macOS on Linux machines and, less so but still useful, to do Linux on macOS.

Are there cases where we want to distinguish between a machine that is running Linux with another machine running macOS, but the developer wants to trick brew into thinking its running Linux?

I think the differentiation from me is "behaviour like we need to on Linux based on the underlying system" vs. "behaviour that differs on macOS on Linux and we want to generate data (e.g. dependency trees) on one OS from the other".

One instance might be that trying to brew install anything on macOS while simulating Linux might lead to a bad time.

Yeh, specifically this: we shouldn't allow installing in this case. We can either e.g. prevent installation or opt-in to the commands/actions that we want to allow (e.g. brew deps, brew info, etc.)

In which case it seems to me that we should be fine with #simulating_linux?, no?

I'm fine with behaviour, it's just the naming that's weird to me. simulating_or_running_on_linux? is a bit of a mouthful but more accurately describes what's going on. Alternatively, SimulateSystem.linux? is generic enough that it doesn't imply that you're not on Linux right now.


base_os = MacOS::Version.from_symbol(os_name)
current_os = MacOS::Version.from_symbol(Homebrew::SimulateSystem.os || MacOS.version.to_sym)
current_os = MacOS::Version.from_symbol(Homebrew::SimulateSystem.current_os)

return current_os >= base_os if or_condition == :or_newer
return current_os <= base_os if or_condition == :or_older
Expand Down
13 changes: 0 additions & 13 deletions Library/Homebrew/extend/os/linux/formula.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,4 @@ def rpath

sig { params(targets: T.nilable(T.any(Pathname, String))).void }
def deuniversalize_machos(*targets); end

class << self
undef ignore_missing_libraries

def ignore_missing_libraries(*libs)
libraries = libs.flatten
if libraries.any? { |x| !x.is_a?(String) && !x.is_a?(Regexp) }
raise FormulaSpecificationError, "#{__method__} can handle Strings and Regular Expressions only"
end

allowed_missing_libraries.merge(libraries)
end
end
end
27 changes: 0 additions & 27 deletions Library/Homebrew/extend/os/mac/software_spec.rb

This file was deleted.

7 changes: 1 addition & 6 deletions Library/Homebrew/extend/os/software_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
# typed: strict
# frozen_string_literal: true

# This logic will need to be more nuanced if this file includes more than `uses_from_macos`.
if OS.mac? || Homebrew::EnvConfig.simulate_macos_on_linux?
require "extend/os/mac/software_spec"
elsif OS.linux?
require "extend/os/linux/software_spec"
end
require "extend/os/linux/software_spec" if OS.linux?
13 changes: 10 additions & 3 deletions Library/Homebrew/formula.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3214,10 +3214,17 @@ def link_overwrite_paths
end

# Permit links to certain libraries that don't exist. Available on Linux only.
def ignore_missing_libraries(*)
return if Homebrew::SimulateSystem.linux?
def ignore_missing_libraries(*libs)
unless Homebrew::SimulateSystem.treat_as_linux?
raise FormulaSpecificationError, "#{__method__} is available on Linux only"
end

libraries = libs.flatten
if libraries.any? { |x| !x.is_a?(String) && !x.is_a?(Regexp) }
raise FormulaSpecificationError, "#{__method__} can handle Strings and Regular Expressions only"
end

raise FormulaSpecificationError, "#{__method__} is available on Linux only"
allowed_missing_libraries.merge(libraries)
end

# @private
Expand Down
24 changes: 18 additions & 6 deletions Library/Homebrew/simulate_system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,31 @@ def clear
end

sig { returns(T::Boolean) }
def none?
@os.nil? && @arch.nil?
end
def treat_as_macos?
return OS.mac? if @os.blank?

sig { returns(T::Boolean) }
def macos?
[:macos, *MacOSVersions::SYMBOLS.keys].include?(@os)
end

sig { returns(T::Boolean) }
def linux?
def treat_as_linux?
return OS.linux? if @os.blank?

@os == :linux
end

sig { returns(Symbol) }
def current_arch
@arch || Hardware::CPU.type
end

sig { returns(Symbol) }
def current_os
return @os if @os.present?
return :linux if OS.linux?

MacOS.version.to_sym
end
end
end
end
21 changes: 17 additions & 4 deletions Library/Homebrew/software_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,25 @@ def depends_on(spec)
add_dep_option(dep) if dep
end

def uses_from_macos(spec, _bounds = {})
spec = [spec.dup.shift].to_h if spec.is_a?(Hash)
def uses_from_macos(deps, bounds = {})
if deps.is_a?(Hash)
bounds = deps.dup
deps = [bounds.shift].to_h
end

@uses_from_macos_elements << deps

@uses_from_macos_elements << spec
# Linux simulating macOS. Assume oldest macOS version.
return if Homebrew::EnvConfig.simulate_macos_on_linux? && !bounds.key?(:since)
Comment on lines +173 to +174
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me wonder about whether this logic should be in extend/os/linux; it feels a bit weird to be introducing OS-condition logic here (and in formula.rb).


# macOS new enough for dependency to not be required.
if Homebrew::SimulateSystem.treat_as_macos?
current_os = MacOS::Version.from_symbol(Homebrew::SimulateSystem.current_os)
since_os = MacOS::Version.from_symbol(bounds[:since]) if bounds.key?(:since)
return if current_os >= since_os
end

depends_on(spec)
depends_on deps
end

def uses_from_macos_names
Expand Down
48 changes: 48 additions & 0 deletions Library/Homebrew/test/formula_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1845,4 +1845,52 @@ def install
expect(f.test).to eq(2)
end
end

describe "#ignore_missing_libraries" do
after do
Homebrew::SimulateSystem.clear
end

it "adds library to allowed_missing_libraries on Linux", :needs_linux do
Homebrew::SimulateSystem.clear
f = formula do
url "foo-1.0"

ignore_missing_libraries "bar.so"
end
expect(f.class.allowed_missing_libraries.to_a).to eq(["bar.so"])
end

it "adds library to allowed_missing_libraries on macOS when simulating Linux", :needs_macos do
Homebrew::SimulateSystem.os = :linux
f = formula do
url "foo-1.0"

ignore_missing_libraries "bar.so"
end
expect(f.class.allowed_missing_libraries.to_a).to eq(["bar.so"])
end

it "raises an error on macOS", :needs_macos do
Homebrew::SimulateSystem.clear
expect {
formula do
url "foo-1.0"

ignore_missing_libraries "bar.so"
end
}.to raise_error("ignore_missing_libraries is available on Linux only")
end

it "raises an error on Linux when simulating macOS", :needs_linux do
Homebrew::SimulateSystem.os = :macos
expect {
formula do
url "foo-1.0"

ignore_missing_libraries "bar.so"
end
}.to raise_error("ignore_missing_libraries is available on Linux only")
end
end
end
51 changes: 0 additions & 51 deletions Library/Homebrew/test/os/mac/software_spec_spec.rb

This file was deleted.

Loading