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

Implement X11Requirement for Linux #3483

Merged
merged 1 commit into from
Dec 8, 2017
Merged

Conversation

sjackman
Copy link
Member

@sjackman sjackman commented Nov 26, 2017

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes? Here's an example.
  • Have you successfully run brew tests with your changes locally?

Move the XQuartz implementation to extend/os/mac/requirements.

@@ -5,8 +5,7 @@ class X11Requirement < Requirement
attr_reader :min_version

fatal true
cask "xquartz"
download "https://xquartz.macosforge.org"
default_formula "linuxbrew/xorg/xorg"
Copy link
Contributor

Choose a reason for hiding this comment

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

having a default formula in a non-core tap seems like asking for trouble

Copy link
Member

Choose a reason for hiding this comment

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

Yeh, I'd rather avoid linuxbrew tap usage for now until we're closer to merging the projects.

Copy link
Member Author

Choose a reason for hiding this comment

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

Okay. How about default_formula "linuxbrew/xorg/xorg" in extend/os/linux/requirements/x11_requirement.rb?

Copy link
Contributor

Choose a reason for hiding this comment

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

How does that change anything? It's still a non-core (i.e. not Linuxbrew/homebrew-core) tap.

@@ -0,0 +1,49 @@
require "requirement"

Object.send(:remove_const, :X11Requirement)
Copy link
Member

Choose a reason for hiding this comment

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

This is a bit weird.

Copy link
Member Author

@sjackman sjackman Nov 27, 2017

Choose a reason for hiding this comment

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

This line removes the class X11Requirement so that extend/os/mac/requirements/x11_requirement.rb can redefine it. Creating a new class with a new name like XQuartzRequirement and then assigning it with X11Requirement = XQuartzRequirement causes a test to fail because be_an_instance_of(X11Requirement) is false. We could make X11Requirement be a base class, and have XQuartzRequirement inherit from it. Alternatively, we could remove this test. Your thoughts?

Copy link
Member Author

@sjackman sjackman Nov 27, 2017

Choose a reason for hiding this comment

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

I replaced it with X11Requirement = XQuartzRequirement.

def initialize(name = "x11", tags = [])
@name = name
if /(\d\.)+\d/ =~ tags.first
@min_version = Version.create(tags.shift)
Copy link
Member

Choose a reason for hiding this comment

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

Do XQuartz versions map to X11/Xorg versions at all? Would be good to share the version logic if possible.

Copy link
Member

Choose a reason for hiding this comment

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

The About window in my xquartz says: "XQuartz 2.7.11 (xorg-server 1.18.4)"

Copy link
Member Author

@sjackman sjackman Nov 27, 2017

Choose a reason for hiding this comment

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

I haven't yet found a need in Linuxbrew for a version check in the X11Requirement. This code is here primarily so that this Requirement exposes the same version API as the XQuartz Requirement, so that the tests pass. I can instead remove this version logic and make that particular test :needs_macos.

Copy link
Contributor

Choose a reason for hiding this comment

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

The point is when it's satisfied by something other than the default formula (which will be forced to be up to date regardless), which I'm assuming remains untested.

Copy link
Member Author

Choose a reason for hiding this comment

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

Before the xorg formula existed, I used Linuxbrew with the host's X11 implementation. When installing a bottle that depends on :x11, the default_formula is used. The host's Xorg may be used when installing something from source that depends on :x11.

Copy link
Member Author

@sjackman sjackman Dec 1, 2017

Choose a reason for hiding this comment

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

Headless Linux servers don't usually have the X server installed (/usr/bin/X), just the X client libraries and executables. The X server is run on your local machine (which is not necessarily running Linuxbrew), whereas the X client is run on the headless server (which is running Linuxbrew). For this reason, I'm checking the version of a X client executable (/usr/bin/xdpyinfo) rather than the X server. The X client libraries are needed to build software that depends on X11, but the X server is not needed at build time.

The most recent complete release of Xorg X11R7.7 shipped with xdpyinfo 1.3.0.
The previous release of Xorg X11R7.6 shipped with xdpyinfo 1.2.0.
See https://www.x.org/releases/X11R7.7/changelog.html

Copy link
Member

Choose a reason for hiding this comment

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

That's the xdpyinfo version rather than the X11 version, though; it's not particularly useful in this case. Can you see if there's anything else that provides the actual X11 version even with the X server not installed? If not, I think this should just assume the server is not headless and the Linux requirement can always override that.

Copy link
Contributor

@ilovezfs ilovezfs Dec 1, 2017

Choose a reason for hiding this comment

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

The katamari 7.7 had server version 1.12.2 and xdpyinfo 1.3.0. So I think starting with Xorg -version >= 1.12.2 makes sense, and then if the Xorg command isn't available, fall back on xdpyinfo -version > = 1.3.0.

Linux:

openzfs ~ # Xorg -version 2>&1|grep Server
X.Org X Server 1.19.3
openzfs ~ # xdpyinfo -version
xdpyinfo 1.3.2

macOS with XQuartz 2.7.11:

iMac-TMP:~ joe$ Xorg -version 2>&1|grep Server
X.Org X Server 1.18.4
iMac-TMP:~ joe$ xdpyinfo -version
xdpyinfo 1.3.2

Copy link
Contributor

Choose a reason for hiding this comment

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

@sjackman are you planning on actually using the satisfy block from this upstreamed code or just continuing to use

  satisfy build_env: false do
    Formula["linuxbrew/xorg/xorg"].installed?
  end

in Linuxbrew itself?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, once it's merged into Homebrew/brew, and then after that, merged into Linuxbrew/brew.

@@ -0,0 +1,3 @@
class X11Requirement
default_formula "linuxbrew/xorg/xorg"
Copy link
Member

Choose a reason for hiding this comment

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

I'd rather avoid any linuxbrew tap references until we are further along with the migration to merge Linuxbrew/brew and Homebrew/brew.

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've removed extend/os/linux/requirements/x11_requirement.rb

@MikeMcQuaid
Copy link
Member

@sjackman My apologies but I misunderstood my conversation previously with @ilovezfs. Instead of needing a version tag that can be passed through let's just make the requirement enforce a minimum X -version and, if not available, xdpyinfo -version within the requirement to a value you're happy with. I'd suggest after that (doesn't need to be part of this PR) we remove the existing version that's passed through as part of the requirement to make it a no-op and then remove it from formulae. Sorry about all the back and forth 😭

@ilovezfs
Copy link
Contributor

ilovezfs commented Dec 1, 2017

minor thing: I don't think X command prints a version for XQuartz but Xorg command does.

iMac-TMP:~ joe$ X -version
iMac-TMP:~ joe$ Xorg -version

X.Org X Server 1.18.4
Release Date: 2016-07-19
X Protocol Version 11, Revision 0
Build Operating System: Darwin 14.0 x86_64 
Current Operating System: Darwin iMac-TMP.local 15.6.0 Darwin Kernel Version 15.6.0: Sun Jun  4 21:43:07 PDT 2017; root:xnu-3248.70.3~1/RELEASE_X86_64 x86_64
Build Date: 25 October 2016  10:12:52PM
 
Current version of pixman: 0.34.0
	Before reporting problems, check http://wiki.x.org
	to make sure that you have the latest version.
iMac-TMP:~ joe$ 

@@ -20,7 +20,7 @@
expect(subject).not_to eql(other)
end

it "returns false if the minimum version differs" do
it "returns false if the minimum version differs", :needs_macos do
Copy link
Member

Choose a reason for hiding this comment

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

Can you instead modify this test so it does something on Linux?

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've added a test for Linux.

@@ -61,6 +61,10 @@
skip "Needs official command Taps." unless ENV["HOMEBREW_TEST_OFFICIAL_CMD_TAPS"]
end

config.before(:each, :needs_linux) do
Copy link
Member

Choose a reason for hiding this comment

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

I'd rather we didn't have these as they show up as pending tests on macOS (I realise the inverse is the case on Linux). Here's a solution for pending tests (that I think we should do for Linux and, I guess, macOS): rspec/rspec-core#2377 (comment) but in this particular case I think an if/else within the test itself is better as they are testing essentially the same functionality. CC @reitermarkus for RSpec thoughts.

Copy link
Member

Choose a reason for hiding this comment

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

I've tweaked the macOS underlying code so this may no longer be needed.

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've tweaked the macOS underlying code so this may no longer be needed.

Meaning the PR is good as is, or you'd prefer the if/else instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, I think you're referring to 8b9ac2b x11_requirement: remove custom minimum version. I'll rebase onto master.

@sjackman
Copy link
Member Author

sjackman commented Dec 4, 2017

I've rebased this PR onto master.

@sjackman
Copy link
Member Author

sjackman commented Dec 4, 2017

Thanks for the reorganization of the macOS X11Requirement, Mike.


def initialize(name = "x11", tags = [])
@name = name
# no-op on version specified as a tag argument
Copy link
Member

Choose a reason for hiding this comment

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

Let's do the same thing on the generic X11 requirement; they should have the same interface. I think the only thing they should probably differ on is the satisfy and min_version stuff (and would be good to have a min_version method there too).

Copy link
Member Author

@sjackman sjackman Dec 4, 2017

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Apologies, I misread this.

@@ -17,32 +13,26 @@ def initialize(name = "x11", tags = [])
end

def min_version
Copy link
Member

Choose a reason for hiding this comment

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

Maybe a min_xdpyinfo_version method too would be good.

return Version::NULL unless OS.mac?

MacOS::XQuartz.minimum_version
Version.new "1.12.2"
Copy link
Member

Choose a reason for hiding this comment

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

Don't think this actually needs a Version.new given you're always comparing them to Versions below.

s
end

def <=>(other)
Copy link
Member

Choose a reason for hiding this comment

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

Want to keep this method in some form for API compatability

min_version <= MacOS::XQuartz.version
end

def message
Copy link
Member

Choose a reason for hiding this comment

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

Want to keep this method in some form.

@sjackman
Copy link
Member Author

sjackman commented Dec 4, 2017

Fixed up.


def initialize(name = "x11", tags = [])
@name = name
# no-op on version specified as a tag argument
Copy link
Member

Choose a reason for hiding this comment

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

Apologies, I misread this.

s = "XQuartz #{min_version} (or newer) is required to install this formula."
s += super
s
"X11 is required to install this formula.\n"
Copy link
Member

Choose a reason for hiding this comment

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

Insert #{min_version} in here somewhere and may as well += super, too.


def inspect
"#<#{self.class.name}: #{name.inspect} #{tags.inspect}>"
end
Copy link
Member

Choose a reason for hiding this comment

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

Let's keep this method as-is.

next false unless MacOS::XQuartz.installed?
min_version <= MacOS::XQuartz.version
if which "Xorg"
version = Utils.popen_read "Xorg", "-version", err: :out
Copy link
Contributor

Choose a reason for hiding this comment

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

@sjackman I think this needs to pass the return value of which "Xorg" to Utils.popen_read, otherwise when env filtering is enabled, it will end up with command not found: Xorg. Ditto xdpyinfo below.

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 believe that both which and Utils.popen_read will experience the same PATH. Either they'll both succeed, or they'll both fail. Do you believe that one of the two experiences env filtering, while the other does not? When Xorg and xdpyinfo are in the standard system path, both which and Utils.popen_read should work with env filtering enabled.

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe that both which and Utils.popen_read will experience the same PATH.

They will not. My comment was not speculative but based on testing. which is Homebrew's custom which, which brings back in the ORIGINAL_PATH.

Other requirements use Homebrew's which for this reason. There's no guarantee things used to satisfy requirements are in the env filtered PATH.

Copy link
Member Author

Choose a reason for hiding this comment

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

Please point me to the relevant code.
which uses PATH
https://github.com/Homebrew/brew/blob/master/Library/Homebrew/utils.rb#L309
popen_read uses PATH
https://github.com/Homebrew/brew/blob/master/Library/Homebrew/utils/popen.rb#L18
What you're saying may well be true, but it's not evident from the code.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed. Thanks for the feedback, Joe.

@ilovezfs
Copy link
Contributor

ilovezfs commented Dec 6, 2017

@sjackman once this is merged, non-formulae (i.e. x11 other than linuxbrew/xorg/xorg) will be allowed to satisfy the x11 requirement. But as far as I can tell, Linuxbrew doesn't have an ENV.x11 implementation. So won't non-formulae satisfiers cause a problem until ENV.x11 is actually implemented?

It's not relevant to whether this PR gets merged in Homebrew/brew now as-is, but it does seem like in its current form it can't be merged into Linuxbrew/brew.

@sjackman
Copy link
Member Author

sjackman commented Dec 6, 2017

With stdenv, the default no-op dev x11; end is sufficient. Linuxbrew/brew has an implementation of ENV.x11 for superenv, but superenv hasn't yet been contributed back to Homebrew/brew. It's coming.

Move the XQuartz implementation to extend/os/mac/requirements.
@MikeMcQuaid MikeMcQuaid merged commit 5055c31 into Homebrew:master Dec 8, 2017
@MikeMcQuaid
Copy link
Member

Thanks again @sjackman!

@sjackman
Copy link
Member Author

sjackman commented Dec 8, 2017

Thanks again for merging, Mike! Thanks for the feedback, @ilovezfs!

@sjackman sjackman deleted the x11 branch December 8, 2017 15:50
@MikeMcQuaid
Copy link
Member

$ brew tests --only=x11_requirement 
Using recorded test runtime
1 processes for 1 specs, ~ 1 specs per process
/usr/local/Homebrew/Library/Homebrew/extend/os/mac/requirements/x11_requirement.rb:42: warning: already initialized constant X11Requirement
/usr/local/Homebrew/Library/Homebrew/requirements/x11_requirement.rb:3: warning: previous definition of X11Requirement was here

@sjackman can you address this (today if possible of I may need to revert)? Check out how JavaRequirement avoids this.

@sjackman
Copy link
Member Author

sjackman commented Dec 8, 2017

Yes, I can address it now.

@sjackman
Copy link
Member Author

sjackman commented Dec 8, 2017

Fixed.

@Homebrew Homebrew locked and limited conversation to collaborators May 4, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants