我有一个Java / Kotlin项目,其中包含多个子项目(模块)。这是基本模块的module-info.java
:
module ir.openuniverse {
requires java.desktop;
requires kotlin.stdlib;
requires transitive org.apache.logging.log4j;
requires org.apache.logging.log4j.core;
exports ir.openuniverse; // Base module has exported here.
}
对于消费者模块,我有:
module ir.openuniverse.watchservice {
requires kotlin.stdlib;
requires gson;
requires ir.openuniverse; // Base module has imported here
exports ir.openuniverse.watchservice;
}
现在,我在使用者模块中插入一个测试文件:
package ir.openuniverse.watchservice;
import ir.openuniverse.UtilKt;
import ir.openuniverse.JUtil;
import ir.openuniverse.Entry;
public class Test {}
,然后尝试对其进行编译:
> Task :watch-service:compileJava FAILED
[...]\watch-service\src\main\ir\openuniverse\watchservice\Test.java:3: error: cannot find symbol
import ir.openuniverse.UtilKt;
^
symbol: class UtilKt
location: package ir.openuniverse
[...]\watch-service\src\main\ir\openuniverse\watchservice\Test.java:5: error: cannot find symbol
import ir.openuniverse.Entry;
^
symbol: class Entry
location: package ir.openuniverse
2 errors
FAILURE: Build failed with an exception.
所有三个类(UtilKt
,JUtil
,Entry
)都在基本模块中。但是JUtil
是Java(JUtil.java
),另外两个是Kotlin(Util.kt
和Entry.kt
)。
如您所见,导入JUtil
并没有问题,但是无法解析其在Kotlin中来源的类。 (无需导入两个Kotlin类,我就可以成功编译模块)。
此外,如果我完全不使用Java 9模块系统,那也没有问题。
我使用Gradle并通过以下两个插件进行了测试:
gradle.plugin.org.gradle.java:experimental-jigsaw:0.1.1
异或:
gradle.plugin.rgoldberg:experimental-jigsaw:0.4.1-SNAPSHOT
更新1:
由于@nullpointer的评论,我试图检查classpath
。这是执行带有--debug
选项的任务的一部分,该选项显示-classpath
为空并且--module-path
具有正确的值(特别是看这两个:D:\Devel\IdeaProjects\Tinifier\base\build\classes\java\main;D:\Devel\IdeaProjects\Tinifier\base\build\classes\kotlin\main;
):
05:40:29.575 [DEBUG] [org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler] Compiler arguments: -source 11 -target 11 -d D:\Devel\IdeaProjects\Tinifier\watch-service\build\classes\java\main -g -sourcepath -proc:none -XDuseUnsharedTable=true -classpath --module-path D:\Devel\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk8\1.3.10\71d0fa967493eb76648b575edf1762cb2d0c7f10\kotlin-stdlib-jdk8-1.3.10.jar;D:\Devel\.gradle\caches\modules-2\files-2.1\com.google.code.gson\gson\2.8.5\f645ed69d595b24d4cf8b3fbb64cc505bede8829\gson-2.8.5.jar;D:\Devel\IdeaProjects\Tinifier\base\build\classes\java\main;D:\Devel\IdeaProjects\Tinifier\base\build\classes\kotlin\main;D:\Devel\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk7\1.3.10\4d147bf43060dc43d61b096e24da1e67dfe0c032\kotlin-stdlib-jdk7-1.3.10.jar;D:\Devel\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.3.10\b178c1501609c6e4ee8be635513cb023a466457d\kotlin-stdlib-1.3.10.jar;D:\Devel\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.11.1\268f0fe4df3eefe052b57c87ec48517d64fb2a10\log4j-api-2.11.1.jar;D:\Devel\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-common\1.3.10\1b19d99229dcedad7caf50534dce38fe82845269\kotlin-stdlib-common-1.3.10.jar;D:\Devel\.gradle\caches\modules-2\files-2.1\org.jetbrains\annotations\13.0\919f0dfe192fb4e063e7dacadee7f8bb9a2672a9\annotations-13.0.jar;D:\Devel\IdeaProjects\Tinifier\watch-service\build\classes\kotlin\main D:\Devel\IdeaProjects\Tinifier\watch-service\src\main\ir\openuniverse\watchservice\T.java D:\Devel\IdeaProjects\Tinifier\watch-service\src\main\module-info.java
05:40:29.576 [INFO] [org.gradle.api.internal.tasks.compile.JdkJavaCompiler] Compiling with JDK Java compiler API.
05:40:30.138 [ERROR] [system.err] D:\Devel\IdeaProjects\Tinifier\watch-service\src\main\ir\openuniverse\watchservice\T.java:3: error: cannot find symbol
05:40:30.139 [ERROR] [system.err] import ir.openuniverse.UtilKt;
05:40:30.139 [ERROR] [system.err] ^
05:40:30.139 [ERROR] [system.err] symbol: class UtilKt
05:40:30.139 [ERROR] [system.err] location: package ir.openuniverse
05:40:30.142 [ERROR] [system.err] D:\Devel\IdeaProjects\Tinifier\watch-service\src\main\ir\openuniverse\watchservice\T.java:5: error: cannot find symbol
05:40:30.142 [ERROR] [system.err] import ir.openuniverse.Entry;
05:40:30.143 [ERROR] [system.err] ^
05:40:30.143 [ERROR] [system.err] symbol: class Entry
05:40:30.143 [ERROR] [system.err] location: package ir.openuniverse
05:40:30.164 [ERROR] [system.err] 2 errors
不幸的是,即使我从上面的日志中知道Compiler arguments
,我也不知道如何手动编译源代码。仅运行javac <compiler-arguments>
无效。
更新2:
将Kotlin .class
文件的副本复制到Java .class
文件的路径即可解决此问题。请参阅我的答案以获取简单的Gradle配置来执行此操作。但是我知道这不是根本的解决方案。
更新3:
我发现了一个更根本的问题!如果我从一个模块中删除所有Java源代码(即使它不依赖于另一个模块;例如我的基本模块),而只是保留Kotlin源代码,那么该模块的编译将抛出该程序包的位置(仅包含Kotlin源代码)导出(在module-info.java
中),并说该包为空!:
> Task :base:compileJava FAILED
D:\Devel\IdeaProjects\Tinifier\base\src\main\module-info.java:9: error: package is empty or does not exist: ir.openuniverse
exports ir.openuniverse;
^
1 error
FAILURE: Build failed with an exception.
答案 0 :(得分:1)
将Kotlin .class
文件的副本复制到Java .class
文件的路径即可解决此问题。但是我知道这不是根本的解决方案(例如,请参见问题的UPDATE 3)。您可以更改Kotlin编译的目标路径。在Gradle中:
sourceSets {
main {
// Optional: Removing `java` directory from output path that usually is `build/classes/java/main/`:
java.outputDir = file(java.outputDir.toString().replaceAll("\\${File.separatorChar}java", ""))
// Mandatory:
kotlin.outputDir = java.outputDir
}
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
// Unfortunately setting `main.kotlin.outputDir` isn't enough. See: https://stackoverflow.com/questions/49638136/kotlin-gradle-plugin-how-to-use-custom-output-directory#comment95108749_49638136 and https://youtrack.jetbrains.com/issue/KT-23807
destinationDir = sourceSets.main.kotlin.outputDir
}
compileTestKotlin {
// ...
}