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

[JEP 238] Multirelease support #265

Open
laeubi opened this issue Jul 27, 2022 · 5 comments
Open

[JEP 238] Multirelease support #265

laeubi opened this issue Jul 27, 2022 · 5 comments
Milestone

Comments

@laeubi
Copy link
Contributor

laeubi commented Jul 27, 2022

JEP 238: Multi-Release JAR Files describes the structure of Multirelease jars and when I add such a jar to my classpath it shows the corresponding selected classes so this looks fine.

Nerveless I have not found yet a way to produce such jar with JDT and maven indicates

Up until the moment of writing all IDEs can only have one JDK per Maven Project, whereas with multi release you want to specify it per source folder.

We recently have a similar request at m2e where it would be useful to specify different target release.

Because of this I'd like to propose preliminary support for JEP 238 in JDT in the following way:

  1. The project VM must be the highest of all release settings
  2. on a classpathentry entry, allow beside a different output folder (what would be required in such a case), to specify the release like this <classpathentry kind="src" output="bin17" path="src17" release="17">
  3. when compiling code for such a source folder, use the appropriate release setting for the given source files

The advantage of this would be, that there is no need to duplicate all settings (so I'm not aiming for different compiler settings for each folder) and map 1:1 for a setup you could use in maven with different executions defined for each release used and thus m2e could also leverage this later on.

@stephan-herrmann
Copy link
Contributor

Let's briefly check whether or not there is a connection to #614.

I see a bit of contention between your statements:

  1. on a classpathentry entry, allow [...] to specify the release
  2. when compiling code for such a source folder, use the appropriate release setting for the given source files

vs.

I'm not aiming for different compiler settings for each folder

--release is of course a compiler setting. The question here seems to be, can we use different --release settings within the same build? I strongly doubt that's feasible. All of ecj's LookupEnvironment would need to provide different (release dependent) versions of each class of the JRE. If you ask me, that sounds like a huge refactoring (like adding one parameter to "50%" of methods of ecj). Not sure this is manageable.

So, if we have different source folders with different requirements, wouldn't that bring us back to multiple builds even in the IDE, where each build uses a specific classpath filter a la #614 ? To me this sounds like a situation, where calls to the isEnabled() test must provide a token to identify the build target. Am I missing anything?

@laeubi
Copy link
Contributor Author

laeubi commented Jan 15, 2023

I think I falsely though #614 can be used here but thinking a bit further this won't work out well... so this is probably not related.

When I develop a MR jar, I usually have the same Class (CompileUnit?) with different content, you can take a look here for a live example https://github.com/ClickHouse/clickhouse-jdbc/tree/master/clickhouse-http-client/src/main but of course it is not feasible to edit all of them in parallel.

Yes, --release is a compiler setting, but I meant that I'm not for changing all settings, this would be the only one, again you can look here: https://github.com/ClickHouse/clickhouse-jdbc/blob/5cf13b27902c33ddefb801e34989b2d8ca96ff6e/pom.xml#L540-L590 for how it is configured in maven:

  • each source folder gets an own compiler invocation
  • each source folder has a different output folder
  • each source folder has a different --release configured

So what JDT needs to do would be (this is only hypothetical because I'm not familiar enough with JDT internals, I can only tell from Tycho side where we call the batch-compiler for a folder and pass a configured target level):

  • it builds a list of used targets (lets say 8, 9, 11 as with clickhouse)
  • it starts at the lowest level and compile everything with 8 into the default output folder
  • it starts another compile with 9 (using the one from the previous stage in the classpath according to MR rules) into default output folder under META-INF/versions/9 (if not configured differently)
  • it starts another compile with 11 (using the one from the previous stages in the classpath according to MR rules) into default output folder under META-INF/versions/11 (if not configured differently)

As mentioned above, there is currently no IDE that support such thing out-of-the-box, so this could be something unique to Eclipse/JDT so it might require some effort, but also very valuable from users point of view.

@stephan-herrmann
Copy link
Contributor

When I develop a MR jar, I usually have the same Class (CompileUnit?) with different content

I wouldn't call it the "same" class then, but variants of the same class, where each variant sits in a dedicated source folder, right? So source folders seem to be a factor in this (like src/main/java9 and src/main/java11)

Everything else you describe looks very similar to my multi-build proposal in #614. Please help me see the difference you are seeing.

To extend my pseudo-code sketch:

interface IBuildConfiguration {
    default Map<String,String> getAdditionalCompilerOptions() { return emptySet(); } // (1)
    String getName();
}
List<Set<IBuildConfiguration>> configurations = getAndCombineConfigurationsFromExtensions(); // (2)
for (Set<IBuildConfiguration> configuration : configurations) { 
     resolvedClasspath = applyExtensionFilters(resolvedClasspath, configuration); // (3)
     setCompilerOptions(configuration.getAdditionalCompilerOptions()); // (4)
     build (resolvedClasspath);
}

At (1) I have extended the configuration memento to enable different compiler options per build.

At (2) we'd get the configurations for java8, java9, java11 to loop over.

At (3) we'd select the source folders to compile in this iteration.

At (4) we'd set the correct release version

With source folders configured to compile into different target folders we'd compile all versions in one regular IDE build, where the build loop over configurations is generically implemented.

In this case I guess the "extension" would be implemented by JDT itself, but it would use the same strategy as we're discussing in #614 , where item (3) above is the key connection.

@laeubi
Copy link
Contributor Author

laeubi commented Jan 16, 2023

I wouldn't call it the "same" class then, but variants of the same class, where each variant sits in a dedicated source folder, right? So source folders seem to be a factor in this (like src/main/java9 and src/main/java11)

Correct, of course such a source folder can also contain classes only for this version, so not each folder must contain a variant, in this example HttpClientConnectionImpl is present in the default version and in version 11

Everything else you describe looks very similar to my multi-build proposal in #614. Please help me see the difference you are seeing.

Yes seems very similar; I just wanted to mention that my idea to solve this issue by enable/disable single items won't work because here we have really different build configs and not a simple on/off...

In this case I guess the "extension" would be implemented by JDT itself, but it would use the same strategy as we're discussing in #614 , where item (3) above is the key connection.

Probably that's possible as well, you previously said it would be very complex and requires a lot of refactoring and probably can't be done, does this still apply here or do you think it would be manageable even it is some larger task?
If we have a quite good understanding I think I'll suggest this issue to the WG for sponsoring the dev-effort.

To extend my pseudo-code sketch:

Maybe one could even extend this a bit more like this:

interface IBuildConfiguration {
    
    IClasspath[] resolveClasspath(IJavaProject project);

    Map<String,String> getCompilerOptions():  // (1)

    String getName();

}
List<Set<IBuildConfiguration>> configurations = getConfigurationsFromExtensionsOrderdByPriority(); // (2)
for (Set<IBuildConfiguration> configuration : configurations) { 
     resolvedClasspath = configuration.getClasspath(): // (3)
     compileOptions = configuration.getCompilerOptions; // (4)
     build (resolvedClasspath, compileOptions);
}

WDYT?

@laeubi
Copy link
Contributor Author

laeubi commented Feb 8, 2024

@stephan-herrmann I just noticed that the feature "compile different source folders with different target releases" could be useful here as well:

actually the source folder https://github.com/eclipse-jdt/eclipse.jdt.debug/tree/master/org.eclipse.jdt.debug.ui/Snippet%20Support/org/eclipse/jdt/internal/debug/ui/snippeteditor should be compiled with 1.7 even in the IDE, curently this is "enforced" by a javadoc comment:

https://github.com/eclipse-jdt/eclipse.jdt.debug/blob/b291934c39c6f4ed33e9997911dbd0d9f0966786/org.eclipse.jdt.debug.ui/Snippet%20Support/org/eclipse/jdt/internal/debug/ui/snippeteditor/ScrapbookMain.java#L32

but of course the IDE will happily suggest and compile any Java 17 features...

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

No branches or pull requests

3 participants