Skip to content

[Xamarin.Android.Tools.AndroidSdk] Prefer JAVA_HOME #86

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

Merged
merged 2 commits into from
Jun 4, 2020

Conversation

jonpryor
Copy link
Contributor

@jonpryor jonpryor commented Jun 3, 2020

Context: dotnet/android#4567

JdkInfo.GetKnownSystemJdkInfos() returns a list of "known JDK
locations", and the order of the returned paths was, basically,
"locations that Xamarin/Microsoft controls come first."

AndroidSdkWindows.GetJdkInfos() reads the Windows registry and is
"controlled by" Visual Studio (unless someone is editing the Registry
by hand…). If not on Windows, GetConfiguredJdks() reads
monodroid-config.xml (managed by Visual Studio for Mac); failing
that we probe some "well known Microsoft-controlled" directory
locations…

…and only failing that do we try the $JAVA_HOME environment
variable, the "de-facto" way to tell software where Java is
installed, and if $JAVA_HOME isn't set we further fallback to
checking directories in $PATH and other mechanisms.

The problem with this approach is that it isn't overridable, which is
a usefully important feature if you want to test new JDK versions,
as is the case in dotnet/android#4567. The "obvious" way to
"try out" a new JDK would be to export the JAVA_HOME environment
variable to the location of the JDK to use, but that won't work
because JdkInfo.GetKnownSystemJdkInfos() explicitly prefers
locations that aren't easily controllable in a CI environment.

Given that existing convention is for JDK installs to set the
JAVA_HOME environment variable -- and thus JAVA_HOME may very
well refer to a JDK which Xamarin.Android doesn't support -- we are
leery of making JAVA_HOME the "primary" override.

Instead, add support for a new JI_JAVA_HOME environment variable
which, if set, is the preferred JDK to use within Xamarin.Android
(unless otherwise overridden by e.g. $(JavaSdkDirectory)).
This will allow CI to export the JAVA_HOME environment variable,
allowing it to be preferred over others.

Additionally, remove some JAVA_HOME "duplication" between JdkInfo
and AndroidSdkWindows, so that things are easier to reason about.

Context: dotnet/android#4567

`JdkInfo.GetKnownSystemJdkInfos()` returns a list of "known JDK
locations", and the order of the returned paths was, basically,
"locations that Xamarin/Microsoft controls come first."

`AndroidSdkWindows.GetJdkInfos()` reads the Windows registry and is
"controlled by" Visual Studio (unless someone is editing the Registry
by hand…).  If not on Windows, `GetConfiguredJdks()` reads
`monodroid-config.xml` (managed by Visual Studio for Mac); failing
that we probe some "well known Microsoft-controlled" directory
locations…

…and only failing *that* do we try the `$JAVA_HOME` environment
variable, the ["de-facto" way][0] to tell software where Java is
installed, and if `$JAVA_HOME` isn't set we further fallback to
checking directories in `$PATH` and other mechanisms.

The problem with this approach is that it isn't overridable, which is
a usefully important feature if you want to *test new JDK versions*,
as is the case in xamarin/xamarin-androi#4567.  The "obvious" way to
"try out" a new JDK would be to export the `JAVA_HOME` environment
variable to the location of the JDK to use, but *that won't work*
because `JdkInfo.GetKnownSystemJdkInfos()` *explicitly prefers*
locations that aren't easily controllable in a CI environment.

We *could* add a new environment variable to override all the others,
but this is needless complexity.

Update `JdkInfo.GetKnownSystemJdkInfos()` to check `$JAVA_HOME`
*first*, not 4th.  This will allow CI to export the `JAVA_HOME`
environment variable, allowing it to be preferred over others.

[0]: https://docs.oracle.com/cd/E19182-01/821-0917/inst_jdk_javahome_t/index.html
Copy link
Member

@jonathanpeppers jonathanpeppers left a comment

Choose a reason for hiding this comment

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

@jonathanpeppers
Copy link
Member

@jpobst
Copy link
Contributor

jpobst commented Jun 3, 2020

My concern is that we don't know who all is setting JAVA_HOME. What if some installer out there is setting it to a Java distro or version we don't support? Today we would do the "right thing" for the user and use a supported Java. With this change they will have to go change their JAVA_HOME (and perhaps that other program they use needed it set the way it was).

It feels like it might be safer to introduce a XA_JAVA_HOME so the user can override our preferred JDK if they want, but it won't be overridden by another Java installer?

@jonpryor
Copy link
Contributor Author

jonpryor commented Jun 3, 2020

Can we remove the [Ignore] from this test now?

We could, if we used JAVA_HOME, but it looks like @jpobst and @pjcollins would prefer using XA_JAVA_HOME instead.

I should certainly add a test for whatever env var is used.

@jonpryor
Copy link
Contributor Author

jonpryor commented Jun 3, 2020

It looks like this is also in two places?

Hilarious. I should remove that. :-)

Context: dotnet#86 (comment)

@jpobst wrote:

> My concern is that we don't know who all is setting `JAVA_HOME`.
> What if some installer out there is setting it to a Java distro
> or version we don't support?

This is almost certainly the case, and an excellent point.

Instead of preferring the `JAVA_HOME` environment variable, prefer the
`JI_HAVE_HOME` environment variable.  This will allow CI to override
*something* "reasonable" so that the JDK can be controlled, without
stepping into an unknowable minefield of JDK installs which already
set `JAVA_HOME` to something that won't work with Xamarin.Android.
@jonpryor
Copy link
Contributor Author

jonpryor commented Jun 3, 2020

The "extra" GetEnvironmentJdkPaths() invocation within AndroidSdkWindows should now be removed, and the AndroidSdkInfo unit test will now attempt to override JI_JAVA_HOME.

All comments should thus be resolved (I hope).

@jonpryor jonpryor merged commit 13cc497 into dotnet:master Jun 4, 2020
jonpryor added a commit that referenced this pull request Jun 4, 2020
Context: dotnet/android#4567

`JdkInfo.GetKnownSystemJdkInfos()` returns a list of "known JDK
locations", and the order of the returned paths was, basically,
"locations that Xamarin/Microsoft controls come first."

`AndroidSdkWindows.GetJdkInfos()` reads the Windows registry and is
"controlled by" Visual Studio (unless someone is editing the Registry
by hand…).  If not on Windows, `GetConfiguredJdks()` reads
`monodroid-config.xml` (managed by Visual Studio for Mac); failing
that we probe some "well known Microsoft-controlled" directory
locations…

…and only failing *that* do we try the `$JAVA_HOME` environment
variable, the ["de-facto" way][0] to tell software where Java is
installed, and if `$JAVA_HOME` isn't set we further fallback to
checking directories in `$PATH` and other mechanisms.

The problem with this approach is that it isn't overridable, which is
a usefully important feature if you want to *test new JDK versions*,
as is the case in dotnet/android#4567.  The "obvious" way to
"try out" a new JDK would be to export the `JAVA_HOME` environment
variable to the location of the JDK to use, but *that won't work*
because `JdkInfo.GetKnownSystemJdkInfos()` *explicitly prefers*
locations that aren't easily controllable in a CI environment.

Given that *existing convention* is for JDK installs to set the
`JAVA_HOME` environment variable -- and thus `JAVA_HOME` may very
well refer to a JDK which Xamarin.Android doesn't support -- we are
leery of making `JAVA_HOME` the "primary" override.

Instead, add support for a new `JI_JAVA_HOME` environment variable
which, if set, is the *preferred* JDK to use within Xamarin.Android
(unless otherwise overridden by e.g. `$(JavaSdkDirectory)`).
This will allow CI to export the `JAVA_HOME` environment variable,
allowing it to be preferred over others.

Additionally, remove some `JAVA_HOME` "duplication" between `JdkInfo`
and `AndroidSdkWindows`, so that things are easier to reason about.

[0]: https://docs.oracle.com/cd/E19182-01/821-0917/inst_jdk_javahome_t/index.html
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants