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
Fix Language::Java::java_home_cmd for Linux #5333
Conversation
Linuxbrew/brew has been using this fix since 2015-03-07. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this will work on macOS the generic implementations will be broken. Would be good to have a fallback to something that works e.g. using which "java"
or the JavaRequirement. Could be a chance to generally consolidate some logic with the JavaRequirement.
Library/Homebrew/language/java.rb
Outdated
version_flag = " --version #{version}" if version | ||
"/usr/libexec/java_home#{version_flag}" | ||
end | ||
def self.java_home_cmd(_version = nil); end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is a correct implementation. See the uses of this in Homebrew/homebrew-core; they won't work after this. It would be good to use something here that makes sense there.
Library/Homebrew/language/java.rb
Outdated
|
||
def self.java_home_env(version = nil) | ||
{ JAVA_HOME: "$(#{java_home_cmd(version)})" } | ||
def self.java_home_env(_version = nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is a correct implementation. See the uses of this in Homebrew/homebrew-core; they won't work after this. It would be good to use something here that makes sense there.
Library/Homebrew/language/java.rb
Outdated
end | ||
|
||
def self.overridable_java_home_env(version = nil) | ||
{ JAVA_HOME: "${JAVA_HOME:-$(#{java_home_cmd(version)})}" } | ||
def self.overridable_java_home_env(_version = nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is a correct implementation. See the uses of this in Homebrew/homebrew-core; they won't work after this. It would be good to use something here that makes sense there.
a441821
to
0a36c3e
Compare
Library/Homebrew/language/java.rb
Outdated
@@ -2,7 +2,7 @@ module Language | |||
module Java | |||
def self.java_home_cmd(version = nil) | |||
version_flag = " --version #{version}" if version | |||
"/usr/libexec/java_home#{version_flag}" | |||
"#{HOMEBREW_BREW_FILE} java-home#{version_flag}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A new documented command seems pretty overkill? Could perhaps do something like raise NotImplementedError
on the generic/non-Mac implementation? Is this used in Linuxbrew formulae and needed to work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
write_jar_script
uses Language::Java.java_home_cmd
, so for that reason, it does need to work. Making it an option of an existing command doesn't seem as clean to me as a new command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was the existing Linuxbrew implementation of this? We make write_jar_script
use a more generically named function which used java_home_cmd
only on macOS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing implementation of java_home_cmd
returns nil
, and the existing implementations of java_home_env
and overridable_java_home_env
return {}
, which was the first version of this PR that I submitted. When JAVA_HOME
is not defined, most tools will use the java
interpreter found in PATH
, which, when there is only a single Java interpreter installed, is good enough.
One place when I've seen this not work is when building a native JNI library, and the build script expects JAVA_HOME
to be defined to find $JAVA_HOME/include
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing implementation of
java_home_cmd
returnsnil
, and the existing implementations ofjava_home_env
andoverridable_java_home_env
return{}
, which was the first version of this PR that I submitted.
I don't think those versions should be empty no-ops but I think a new command is a bit overkill in the opposite direction. The original implementation with raise NotImplementedError
scattered around where appropriate feels like it may be a good call.
623cbb0
to
fa6c85d
Compare
The shell script created by #!/bin/bash
JAVA_HOME="$(/usr/libexec/java_home --version 1.8)" exec "/usr/local/Cellar/igv/2.4.14/libexec/igv.sh" "$@" rather than being hard coded like for example this: JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home exec "/usr/local/Cellar/igv/2.4.14/libexec/igv.sh" "$@" The former is better, because the latter would break when the Java interpreter is upgraded. I feel that providing a script that is functionally equivalent to macOS's |
I don't like the idea of having a new Homebrew command that's only relevant to make Linux formulae behave a bit more like Homebrew's. There must be a way that e.g. Debian and Fedora already handle something similar. |
This PR implements equivalent functionality to macOS, which I think is the best possible scenario. If your objection is that brew java-home is user-facing and documented, we can find a way to hide this tool so that it's internal to Homebrew. |
@sjackman My objection is a few-fold:
|
cff9ee4
to
4467f4d
Compare
I've pushed take three of this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm liking this approach 👍. Sorry for all the back and forth.
raise NotImplementedError | ||
end | ||
|
||
def self.java_home(version = nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you see this being a new method that's called by formulae? If not, could move it somewhere else less public or add a @private
at least.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
9/14 uses of java_home_cmd
look like…
cmd = Language::Java.java_home_cmd("1.8")
ENV["JAVA_HOME"] = Utils.popen_read(cmd).chomp
A function that immediately evaluates to java_home
(like the Linux implementation) seems useful.
ENV["JAVA_HOME"] = Language::Java.java_home("1.8")
That doesn't however work with the current macOS implementation of java_home
, which evaluates to the string "$(/usr/libexec/java_home …)"
, and not the actual home.
I'll take a stab at making a useful java_home
function and hiding the private one that possibly evaluates to $(…)
on macOS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thought, it's not worth creating a new function for just 9 uses in Homebrew/core. I'll make java_home
private.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm game for it being public if it'd be used for that. I think 9 uses is sufficient 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm game for implementing it, but the current implementation is not sufficient. On macOS,
ENV["JAVA_HOME"] = Language::Java.java_home("1.8")
would evaluate to
ENV["JAVA_HOME"] = "$(/usr/libexec/java_home --version 1.8)"
which is incorrect. It should evaluate to
ENV["JAVA_HOME"] = "/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm game for it being public if it'd be used for that. I think 9 uses is sufficient 👍
Language::Java.java_home
is now implemented, public, and tested.
@@ -1,7 +1,7 @@ | |||
require "language/java" | |||
|
|||
describe Language::Java do | |||
describe "::java_home_env" do | |||
describe "::java_home_env", :needs_macos do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should work on Linux, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current test which searches for the version
string (e.g. "1.8+"
) in java_home
does not work. I can modify the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, the test also fails unless java
is installed. I'll change it to :needs_java
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please 👍. Tests for any new public functions would be good too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. No, :needs_macos
is more correct than :needs_java
.
java_home = described_class.java_home_env("blah")
expect(java_home[:JAVA_HOME]).to include("--version blah")
On macOS this test is fine, but on Linux it fails unless Java version blah
is installed, because on Linux it uses JavaRequirement
to check that that particular version of Java is installed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sjackman Fine with me as long as we have new tests for each of the generic cases that are implemented.
There was a problem hiding this comment.
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 the new Language::Java.java_home
method.
@@ -13,7 +13,7 @@ | |||
end | |||
end | |||
|
|||
describe "::overridable_java_home_env" do | |||
describe "::overridable_java_home_env", :needs_macos do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should work on Linux, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
d241cea
to
a7a68f0
Compare
@MikeMcQuaid Thanks for the feedback. Good to merge? |
version_flag = " --version #{version}" if version | ||
"/usr/libexec/java_home#{version_flag}" | ||
def self.java_home_cmd(_version = nil) | ||
raise NotImplementedError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment might be useful to explain why this is the case.
Library/Homebrew/language/java.rb
Outdated
def self.java_home_cmd(version = nil) | ||
version_flag = " --version #{version}" if version | ||
"/usr/libexec/java_home#{version_flag}" | ||
def self.java_home_cmd(_version = nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_ = nil
Library/Homebrew/test/spec_helper.rb
Outdated
@@ -85,6 +85,10 @@ | |||
skip "Not on macOS." unless OS.mac? | |||
end | |||
|
|||
config.before(:each, :needs_java) do | |||
skip "Java not installed." unless which("java") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will behave oddly on macOS with the java
shim but Java not being installed. Might want to use similar logic to the JavaRequirement
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. Fixed.
/usr/libexec/java_home is specific to macOS. Language::Java::java_home_cmd is not implemented on Linux and raises NotImplementedError. Add private Language::Java::java_home_shell and use it instead of java_home_cmd. Add public Language::Java::java_home for use by formulae.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One final comment: feel free to address or merge as-is, don't feel strongly. Thanks for bearing with me here and sorry for all the back and forth. We're getting close 😍
config.before(:each, :needs_java) do | ||
java_installed = if OS.mac? | ||
Utils.popen_read("/usr/libexec/java_home", "--failfast") | ||
$CHILD_STATUS.success? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to not use system
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used Utils.popen_read
so that it has the standard behaviour of silencing stderr
by default and showing it when HOMEBREW_STDERR
is enabled.
Thanks for the review, Mike. Merged! |
/usr/libexec/java_home
is specific to macOS.brew style
with your changes locally?brew tests
with your changes locally?