I\'m working on a mixed java and kotlin project by using maven.
The problem I\'m facing right now is, maven-compiler-plugin
runs before compiling kotl
In case you are open to using a different build system, dependent projects are easy to set up with Kobalt:
val p1 = javaProject { ... }
val p2 = kotlinProject(p1) { ... }
This makes project p2
depend on p1
. You can also mix Java and Kotlin projects.
A simple but effective solution would be to change the two phases (the <phase>
element) applied to the executions of the Kotlin Maven Plugin, from compile
to process-sources
and from test-compile
to process-test-sources
.
You want the Kotlin part to be executed before the Java one. Maven by default will invoke the Maven Compiler Plugin as part of the compile
phase for source code, and test-compile
for test code. Moving the Kotlin part to their previous phases would then make the flow as you wished.
If you wanted the opposite (first Java then Kotlin), then you could have moved the Kotlin part to the next phases (as an example: from compile
to process-classes
and from test-compile
to process-test-classes
).
For further details about Maven phases, check the official documentation.
Although it's more verbose, you can compile both Java and Kotlin sources in the compile
phase with the following configuration:
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>kotlin-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>kotlin-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5</version>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
Normally, plugins are executed in the order they are declared in the POM, but the executions of default-compile
and default-testCompile
are special because they're built-in, so they always go first. The above configuration gets around that by disabling the default compile executions, and declaring maven-compiler-plugin
with new compilation executions after the kotlin-maven-plugin
. In this way, you can get all compilation to properly occur during the compile
phase of the build lifecycle.
The Kotlin documentation on Using Maven suggests explicitly binding the kotlin-maven-plugin
execution to the process-sources
phase. Since maven-compiler-plugin
is bound to the compile
phase, binding kotlin-maven-plugin
to the process-sources
phase makes it run first.
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>test-compile</id>
<phase>process-test-sources</phase>
<goals> <goal>test-compile</goal> </goals>
</execution>
</executions>
</plugin>