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

Use of eclipse settings "org.eclipse.jdt.core.prefs" #17

Closed
dovogt opened this issue Nov 15, 2023 · 7 comments
Closed

Use of eclipse settings "org.eclipse.jdt.core.prefs" #17

dovogt opened this issue Nov 15, 2023 · 7 comments
Assignees
Labels
a:question Further information is requested

Comments

@dovogt
Copy link

dovogt commented Nov 15, 2023

I am currently using your plugin and previously used the plugin de.set.ecj. The Eclipse settings were used there. Can I configure your plugin so that the Eclipse settings are used?

compileJava {
options.compilerArgs << '-properties' << '$projectDir/.settings/org.eclipse.jdt.core.prefs'
}

The background is that I need source compatibility on Java 11, but target compatibility on 17 and compliance on Java 17. Unfortunately, this cannot be mapped with the Gradle settings.
The goal is that my library can be used in Java 11 projects

@TheMrMilchmann
Copy link
Owner

Hi @dovogt,

the good news is that the compiler should pick up the properties just fine with the code you specified above. Did you try this and run into any issues?

The bad news is that, from your description, there is different problem with your approach. So let's dive into this:

The background is that I need source compatibility on Java 11, but target compatibility on 17 and compliance on Java 17. [...] The goal is that my library can be used in Java 11 projects

Source compatibility (i.e. javac's -source parameter) determines the language version the compiler will use to read your library's source code. For example, if you have text blocks in your sources, the source compatibility needs to be at least 14.
The target compatibility (-target) essentially configures the bytecode version for your compiled classes.

Java is not forward-compatible. This means, that in Java X, you cannot read bytecode from any Java version that was released after version X.1 Specifically, in your case, you target Java 17 bytecode which cannot be used from Java 11.

Instead, Java is backward-compatible. This means that bytecode from Java Y can be read in any Java version released after version Y. So what you want to do here, is setting -target to Java 11. This way, the compiler outputs Java 11-compatible bytecode and your library can be used from any version starting from 11.

Just one more thing to keep in mind: Using -source and -target is discouraged. While -target instructs the compiler to produce bytecode compatible with Java 11, the compiler does not restrict which APIs you are using. If you are referencing a class introduced in Java 16, your code will compile fine but still won't be able to run on 11.
The -release parameter was introduced to solve this. Using this parameter you set the version of the accepted source code, and the targeted bytecode version at once. However, you also get the additional benefit that the compiler checks that you are only using APIs available to the desired release.

So, finally, what I recommend in your case, is ditching -source and -target, and setting -release 11 instead. This can be done in Gradle too and will be respected by the compiler:

compileJava {
    options.release = 11
}

Footnotes

  1. This is not entirely correct, because the bytecode version is technically independent from the Java version, but the assumption is good enough.

@TheMrMilchmann TheMrMilchmann self-assigned this Nov 15, 2023
@TheMrMilchmann TheMrMilchmann added the a:question Further information is requested label Nov 15, 2023
@dovogt
Copy link
Author

dovogt commented Nov 15, 2023

Thank you very much for your detailed help.

I have entered the following in the Eclipse settings:
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.source=11

and in the build.grade
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
or
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11

After creating the classes, the classes either had bytecode 61 or, in the second case, bytecode 55
The settings from Eclipse do not seem to be taken into account. I may have included them incorrectly.

compileJava {
options.compilerArgs << '-properties' << '$projectDir/.settings/org.eclipse.jdt.core.prefs'
}

  1. I use a library that forces me to switch to Java 17. I have asked again what exactly the requirements are. Again, my library is used by projects that are still on Java 11.
    I'll try again with the release switch.

@TheMrMilchmann
Copy link
Owner

I just checked and can confirm it works. However, if you are specifying sourceCompatibility and targetCompatibility in Gradle, you are overwriting the settings read from the properties file.

@dovogt
Copy link
Author

dovogt commented Nov 16, 2023

I have created the following configuration. If I set options.relase=11, will the configuration from the settings still be loaded? Or do I have to leave out release that it uses the settings?

	project.tasks.named("compileJava").configure {
		options.fork = true
		options.release = 11
		options.encoding = "UTF-8"
		options.warnings = false
	        options.compilerArgs << '-properties' << '.settings/org.eclipse.jdt.core.prefs' << '-proc:none' << '-log' << new File(project.buildDir, "compiler.xml").getAbsolutePath()
	}

@TheMrMilchmann
Copy link
Owner

TheMrMilchmann commented Nov 16, 2023

I have created the following configuration. If I set options.relase=11, will the configuration from the settings still be loaded? Or do I have to leave out release that it uses the settings?

	project.tasks.named("compileJava").configure {
		options.fork = true
		options.release = 11
		options.encoding = "UTF-8"
		options.warnings = false
	        options.compilerArgs << '-properties' << '.settings/org.eclipse.jdt.core.prefs' << '-proc:none' << '-log' << new File(project.buildDir, "compiler.xml").getAbsolutePath()
	}

I didn't check this specifically, but -release will probably overwrite the properties just like -source and -target do. You could test this by setting -release to a different version compared to the settings and checking the bytecode of the compiled classes. However, if this configuration works for you, I recommend keeping it as-is.

@dovogt
Copy link
Author

dovogt commented Nov 20, 2023

When I set the release parameter, it seems to use this and no longer the settings from the Eclipse. I have removed it and then it seems to work. Thanks again for your support

@dovogt
Copy link
Author

dovogt commented Nov 22, 2023

I had to set the options.release= 11 after all. By using Java 17 for execution, Java 17 is entered as the minimum version in the modules file for publish. As a result, an error occurs when downloading the dependency.
However, this change then leads to gradle changing the settings file in Eclipse and overwriting the compiler compliance level with 11. I have included the Eclipse plugin in build.gradle and set sourceCompatibility=17 and targetCompatibility= 11 so that it can be used for us.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants