gradlex-org / reproducible-builds

Reproducibility settings applied to some of Gradle's built-in task, that should really be the default.
Apache License 2.0
15 stars 0 forks source link

Ensure consistency for module-info.class files #8

Open tg-freigmbh opened 4 days ago

tg-freigmbh commented 4 days ago

I just had the realization that for whatever reason the javacompiler compiles the minor java version into the module-info.class, therefore making the build unreprodible unless on has exactly the same java version... grafik

jjohannes commented 4 days ago

Unfortunately, there is no good solution (I can think of) to implement it in this plugin.

The ability to define the exact Java version is a missing feature in Gradle's toolchain support: https://github.com/gradle/gradle/issues/16628#issuecomment-2097540617

I also reported the issue you have with module-info.class files a while back: https://github.com/gradle/gradle/issues/28806#issuecomment-2056998992

Feel free to upvote or comment on the Gradle issues.


What we could still do in this plugin is:

Like this: https://github.com/hiero-ledger/hiero-gradle-conventions/blob/6eb6f3ed13d0949a343ca0d7a3175c1caae9c685/src/main/kotlin/org.hiero.gradle.feature.java-compile.gradle.kts#L23-L45

tg-freigmbh commented 4 days ago

I am still somewhat perplexed by this... So I guess its really absolutely not possible to not have the bugfix version appear in the class file? what does the minor version even do?

jjohannes commented 4 days ago

This would be a question for the JDK folks. I don't really understand why there are versions in the class file at all. For me it looks like theses are the versions of the modules that are required. So the version you happen to have on the compile Module Path when your module is compiled. For JDK internal modules, this is the full version of the JDK itself. But since the Module System is not looking at versions, I don't think this information is used by that Java runtime.

jjohannes commented 4 days ago

In the spec it says

requires_version_index

The value of the requires_version_index item must be either zero or a valid index into the constant_pool table. If the value of the item is zero, then no version information about the dependence is present. If the value of the item is nonzero, then the constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the version of the module specified by requires_index.

My interpretation of that is that the value could be 0 and things would still work. I don't see any indication that the value is used for anything in the Java runtime.

If we look at the source code of the Java compiler, the value is read from the module-info we compile against. And the value could be 0. This is the case, for example, for other modules we build ourselves, if we do not write version information (if you do not set JavaCompile.options.javaModuleVersion).

Unfortunately, there is no option to tell the compile to ignore version values. I could imagine rewriting the module-info.class file after it has been compiled. Gradle is already doing that for ModuleMainClass, because that is not added by the compiler, but later by the Jar tool (if you would use plain JDK tooling).

I could imagine an option in Gradle core for that. 🤔 One could also do that in the build configuration or a (this?) plugin through an additional task action on JavaCompile. (Some folks might consider this "a dirty hack" though...)

tg-freigmbh commented 4 days ago

I think you "can" query these generated versions at runtime using ModuleDescriptor#requires#compiledVersion/rawCompiledVersion.

So its technically visible meta-info, but I am not aware of anyone doing anything with this information