I wish the JDK were just another dependency, since it is, really

(Trejkaz (pen name)) #1

With the Gradle wrapper, we have the ability to fix the version of Gradle a build runs against. Having a way to do the same with the JDK would be quite helpful, but all the current ways to do it are not really great.

You could update the Gradle wrapper properties to include it. But this path is going to be different per-platform and per-developer, so you end up with every developer having to manually edit this file after checking things out. You could hack it into the gradlew script so that it uses some other environment variable which has to contain the full path, but this is a little awkward as well.

With Ruby projects, I have a .ruby-version file which specifies which version to use, and rbenv handles running the right ruby executable. For Java projects, a similar tool, jenv, exists. At some point, this tool even added Windows support, though only for PowerShell. :confused: But still, this is just one more executable switcher, much like rbenv, and we’d have to have one per development tool, all run before running the Gradle wrapper, so it’s not perfectly convenient.

But the project has a Gradle build file in it, which is supposed to contain a statement of the build’s dependencies. The JDK is a dependency too, but it’s a bit disappointing that it isn’t possible to treat it like all the other ones.

If only we could specify something like:

  jdk = 'net.java.openjdk:jdk:1.8.0_112'

Gradle could then unpack that somewhere and know where it is, and we wouldn’t have to keep track of so many things.

(Stefan Oehme) #2

That’s a very good point. The first step towards this will be automatic JDK discovery, so that Gradle chooses the right installed JDK based on the targetCompatibility. Downloading a JDK on the fly would be another cool improvement on top of that.

(Trejkaz (pen name)) #3

We customise our JDK, so the version number of ours is the same as the corresponding Oracle one, but it’s important that tests at least run against ours, since some of our fixes meant inserting additional jars or configurations. Over at JetBrains they’re even modifying the code, so being able to pull the JDK from an artifact server would be handy.

About the only thing that isn’t immediately obvious is what to do about different platforms. Maybe the convention would end up being to put “${os}-${arch}” into the classifier, or something like that.

(… Then again, Gradle has never been really great at platform-dependent dependencies, has it? We have a lot of hacks in our builds where we end up doing this sort of thing:

  if (org.gradle.internal.os.OperatingSystem.current().isMacOsX()) {
    runtime libraries.haqua

Even this would have been less bad:

  on "macos" {
    runtime libraries.haqua

So maybe the JDK configuration would end up with us having a big if-block checking the current platform, and the majority of people who don’t even build for more than one platform would not even notice that it’s awful.)

(Benjamin Muschko) #4

We did put down some thoughts on a concept we currently call “build platform”. It likely fits in with what you are looking for. At the moment we do not have any plan to tackle the implementation anytime soon.

(Stefan Oehme) #5

We actually just pushed the infrastructure for variant aware dependency management to master. It’s based on putting attributes on configurations so we can match project dependencies to the correct variant of an upstream project. Based on that you could build a plugin that allows different dependencies per target platform. It’s not documented yet as we are still straightening out the edges, just wanted to let you know this is happening.

At some point this will probably be a standard feature in the Java plugin.

(Bahadır Yağan) #6

Running builds inside docker containers is a good option for handling JDK dependency. It seems there is already a large collection of images on docker hub.

(Trejkaz (pen name)) #7

That sounds like it could get particularly horrific if your build required more than one JDK to do the entire thing. e.g., if you had a component like Derby, where bits of it have to be built against an older version, but didn’t want to build your own stuff under that version.