intellij-platform-gradle-plugin icon indicating copy to clipboard operation
intellij-platform-gradle-plugin copied to clipboard

ComposedJar task does not get run for submodules which are not using pluginModule dependency helper

Open AlexanderBartash opened this issue 1 year ago • 4 comments

What happened?

I have a plugin consisting of multiple gradle modues:

  • the main (parent) module
  • a sub-module

The dependency from the parent module to the submodule is declared using implementation(project(":submodule:")) instead of pluginModule(implementation(project(":submodule"))) because I do not want the jars to get merged.

I have code instrumentation enabled for all modules (really, I checked).

After I build the plugin with "buildPlugin" task in the resulting zip I see

  • main-module.jar (instrumented)
  • submosude-base.jar (not instrumented) <<< It should be submodule.jar instead, generated by composedJar task

For the submodule the next tasks are run:

  • :instrumentCode
  • :jar

For the main module the next tasks are run:

  • :instrumentCode
  • :jar
  • :instrumentedJar
  • :composedJar

Also I see that only submodule-base.jar (not instrumented) is also get copied into the sandbox.

If I declare the dependency using pluginModule(implementation(project(":submodule"))) it works as expected, i.e. composedJar task is run for the submodule and the correct jar is used.

Relevant log output or stack trace

No response

Steps to reproduce

  • Create a plugin with a sub-module
  • Declare the dependency using implementation(project(":submodule:")) instead of pluginModule(implementation(project(":submodule")))
  • Enable code instrumentation in both modules by using instrumentationTools() helper & setting instrumentCode property to true.
  • run buildPlugin

The expected result:

  • instrumentedJar & composedJar tasks are run for both the submodule & the main module

The actual result:

  • instrumentedJar & composedJar tasks are not run for the submodule

Gradle IntelliJ Plugin version

2.0.0

Gradle version

8.9

Operating System

Linux

Link to build, i.e. failing GitHub Action job

No response

AlexanderBartash avatar Jul 31 '24 13:07 AlexanderBartash

Thanks for reporting, Alexander! Unfortunately, I'm unable to reproduce this issue. Could you please prepare a minimal project and publish it to GitHub so I could run it locally?

hsz avatar Aug 06 '24 13:08 hsz

@hsz I will try to set up something, but I think I've found the root case. There is one more crucial step required to reproduce it, but I will skip that for now and jump to the root cause:

IntelliJPlatformModulePlugin incorrectly (well, correctly but not entirely) sets the target JVM version for the outgoing variant intellijPlatformComposedJar because instead of:

attributeProvider(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, project.provider {
    project.the<JavaPluginExtension>().targetCompatibility.majorVersion.toInt()
})

It should probably do something like this: getDefaultTargetPlatform

It is necessary because target compatibility can be set in multiple ways:

  1. This is what Intellij Platform plugin supports now:
java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}
  1. An alternative way supported by Gradle's getDefaultTargetPlatform but not by this plugin:
tasks {
    withType<JavaCompile> {
        sourceCompatibility = "1.8"
        targetCompatibility = "1.8"
    }

    kotlin {
        compilerOptions {
            jvmTarget = JvmTarget.JVM_1_8
        }
    }
 }

So that missing step required to reproduce it is: you need to have JAVA_HOME set to JDK e.g. 22, while building the plugin for JDK 21. In such case intellijPlatformComposedJar variant will have "org.gradle.jvm.version" set to 22 (the value from JAVA_HOME, which is completely irrelevant to the project being built) instead of whatever was specified in the compiler options. Which makes Gradle select another default variant produced by Gradle, probably apiElements (does not matter which exactly), because that variant respects all possible ways to configure source & target compatibility and can be selected, while intellijPlatformComposedJar is expected to be selected instead for all this to work.

I will add more clear steps later, in case if this is confusing.

AlexanderBartash avatar Aug 16 '24 22:08 AlexanderBartash

Also it may be that https://github.com/JetBrains/intellij-platform-gradle-plugin/blob/main/src/main/kotlin/org/jetbrains/intellij/platform/gradle/attributes/ComposedJarRule.kt has a mistake too, but I am not really sure regarding this one.

That rule says that producer's "jar" is compatible when a consumer requests "composed-jar".

It seems to me, that it should be the other way around.

AlexanderBartash avatar Aug 16 '24 22:08 AlexanderBartash

Relevant documentation https://docs.gradle.org/current/userguide/building_java_projects.html#sec:java_cross_compilation

AlexanderBartash avatar Aug 24 '24 13:08 AlexanderBartash

Closing because opened a new issue with more relevant details https://github.com/JetBrains/intellij-platform-gradle-plugin/issues/1772

AlexanderBartash avatar Sep 24 '24 19:09 AlexanderBartash