Is it possible to set the Gradle JVM per-project? ...
# intellij
m
Is it possible to set the Gradle JVM per-project? I have some projects requiring 8, 11 and 17 and looks like the setting is global right now?
e
perhaps https://youtrack.jetbrains.com/issue/IDEA-147078/Support-switching-of-JDK-via-jenv (although I'd like to see
direnv
support in general)
๐Ÿ‘€ 1
m
Yup, I do this often
m
It would be great if IntelliJ picks up the JAVA SDK based on JAVA_HOME set by jenv (or similar other tool).
This part is working already right?
I read somewhere that IntelliJ bootstraps a small shell at startup for the single purpose of reading JAVA_HOME
๐Ÿ’™ 1
๐Ÿ™ 1
๐Ÿ˜‰ 2
e
that part of IntelliJ picks up environment variables once at startup, not per project
whereas jenv/direnv/etc. allow for per-directory configuration. I don't think IntelliJ re-reads environment variables when switching projects
๐Ÿ‘ 1
m
I'm happy with specifying the JDK manually and having it stored in .idea somewhere but if there's something even smarter then I'm all for it
m
Do you mean just?
m
Ah maybe that's what I'm missing @mcpiroman
Where do I specify the project SDK?
m
Project Structure > Project But you may set an independent sdk for gradle
๐Ÿ™ 1
m
Thanks a lot! looks like that was what I was looking for!
f
At HelloFresh we have established that every project MUST have a
.java-version
file in the root and our Gradle reads this to set up the project's target JVM. With this it is possible to also configure IntelliJ by manipulating some XML files in the
.idea
directory. More specifically the
.idea/misc.xml
(example for 11):
Copy code
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK" />
And in `.idea/gradle.xml`:
Copy code
<option name="delegatedBuild" value="true" />
        <option name="testRunner" value="GRADLE" />
        <option name="distributionType" value="DEFAULT_WRAPPED" />
I think we also write
.idea/compiler.xml
but that is not really required since we delegate everything to Gradle anyways:
Copy code
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="CompilerConfiguration">
    <bytecodeTargetLevel target="11" />
  </component>
</project>
I might have forgotten one of the steps we perform, but I think that's it. Would be great if IntelliJ can spare us this and just do it on its own. ๐Ÿ˜›
๐Ÿ™ 1
๐Ÿ‘€ 1
m
Side question: what is "project SDK" used for ๐Ÿค” (besides what I'm going to do to use it in the Gradle JVM) ? Is it used to run something when I use Gradle?
f
The project SDK is used for auto-completion.
mind blown 1
m
Gotcha!
That sounds... not what I want? The Java I use for running Gradle isn't always the same that my code actually uses ?
f
We use Gradle tool chains in such situations. This ensures that the user doesn't even need to install the required JDK for a particular module since Gradle just automatically fetches it.
c
^^^ also interops with IntelliJ to get the right JVM based on the Gradle build file (or files, for multi-module).
m
So many JVMs ๐Ÿ˜…
Alright, thanks a lot for all the pointers !
f
In other words, our
.java-version
contains the JDK to run Gradle with (use jEnv) and the default bytecode target. If a subprojects requires something else for whatever reason we use tool chains. This is not as flexible as some might require it in all possible situations, but it works for us at the moment and nobody needed more than that. In fact I wanted to figure out how to get rid of tool chains since 9+ can create bytecode for any previous Java release, but haven't looked into this yet.
e
you can always create bytecode for previous java releases, but (without --release added in java 9) that doesn't prevent you from using newer APIs in the standard class library, which is a problem if you're targeting older releases
f
The problem here is with a project where everything is J17/J11 but one thing needs to be J8 because of reasons (well, that reason is almost always related to Scala with something Kafka because Scala is a broken piece of ๐Ÿ’ฉ or AWS). In such a setup it's not possible to tell IntelliJ that one module should use J8 and all the others J17/J11. That said, for us it makes little difference in daily life since all code is Kotlin and the Java APIs don't matter much, it's mostly about bytecode. And yes,
--release
is what I was referring to in my previous comment. Switching from tool chains to
--release
in our plugins would be much more efficient since no additional JDK needs to be downloaded. The reason we implemented it with tool chains was originally to ensure that it doesn't matter which JDK someone uses to run Gradle, the tests and everything still uses the correct JDK. This also works as intended, but it has the side effect of downloading tool chains in the previously mentioned J17 with J8 submodule case.
c
had to wade through the JavaCompile task source the other day -
--release
is set in any case (toolchain or otherwise).