Support -Xmodule-path and -Xadd-modules command line arguments
#KT-18598 In Progress #KT-18599 Fixed
This commit is contained in:
+11
@@ -88,6 +88,17 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments {
|
||||
|
||||
// Advanced options
|
||||
|
||||
@Argument(value = "-Xmodule-path", valueDescription = "<path>", description = "Paths where to find Java 9+ modules")
|
||||
public String javaModulePath;
|
||||
|
||||
@Argument(
|
||||
value = "-Xadd-modules",
|
||||
valueDescription = "<module[,]>",
|
||||
description = "Root modules to resolve in addition to the initial modules,\n" +
|
||||
"or all modules on the module path if <module> is ALL-MODULE-PATH"
|
||||
)
|
||||
public String[] additionalJavaModules;
|
||||
|
||||
@Argument(value = "-Xno-call-assertions", description = "Don't generate not-null assertion after each invocation of method returning not-null")
|
||||
public boolean noCallAssertions;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentUtil
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
||||
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
||||
@@ -106,6 +107,9 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
|
||||
val classpath = getClasspath(paths, arguments)
|
||||
configuration.addJvmClasspathRoots(classpath)
|
||||
for (modularRoot in arguments.javaModulePath?.split(File.pathSeparatorChar).orEmpty()) {
|
||||
configuration.add(JVMConfigurationKeys.CONTENT_ROOTS, JvmModulePathRoot(File(modularRoot)))
|
||||
}
|
||||
|
||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, arguments.moduleName ?: JvmAbi.DEFAULT_MODULE_NAME)
|
||||
|
||||
@@ -299,6 +303,10 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
configuration.put(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS, components)
|
||||
}
|
||||
}
|
||||
|
||||
arguments.additionalJavaModules?.let { additionalJavaModules ->
|
||||
configuration.addAll(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES, additionalJavaModules.toList())
|
||||
}
|
||||
}
|
||||
|
||||
override fun createArguments(): K2JVMCompilerArguments = K2JVMCompilerArguments().apply {
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageUtil
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
|
||||
import org.jetbrains.kotlin.config.ContentRoot
|
||||
@@ -41,6 +42,7 @@ import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
|
||||
internal class ClasspathRootsResolver(
|
||||
private val psiManager: PsiManager,
|
||||
private val messageCollector: MessageCollector?,
|
||||
private val additionalModules: List<String>,
|
||||
private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?
|
||||
) {
|
||||
private val javaModuleFinder = CliJavaModuleFinder(VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL))
|
||||
@@ -75,6 +77,15 @@ internal class ClasspathRootsResolver(
|
||||
is JvmClasspathRoot -> {
|
||||
result += JavaRoot(root, JavaRoot.RootType.BINARY)
|
||||
}
|
||||
is JvmModulePathRoot -> {
|
||||
// TODO: sanitize the automatic module name exactly as in javac
|
||||
// TODO: read Automatic-Module-Name manifest entry
|
||||
val module = modularBinaryRoot(root, automaticModuleName = { contentRoot.file.name })
|
||||
if (module != null) {
|
||||
// TODO: report something in case of several modules with the same name?
|
||||
modules += module
|
||||
}
|
||||
}
|
||||
else -> error("Unknown root type: $contentRoot")
|
||||
}
|
||||
}
|
||||
@@ -97,6 +108,17 @@ internal class ClasspathRootsResolver(
|
||||
return JavaModule.Explicit(JavaModuleInfo.create(psiJavaModule), root, moduleInfoFile, isBinary = false)
|
||||
}
|
||||
|
||||
private fun modularBinaryRoot(root: VirtualFile, automaticModuleName: () -> String): JavaModule? {
|
||||
val moduleInfoFile = root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE)
|
||||
return if (moduleInfoFile != null) {
|
||||
val moduleInfo = JavaModuleInfo.read(moduleInfoFile) ?: return null
|
||||
JavaModule.Explicit(moduleInfo, root, moduleInfoFile, isBinary = true)
|
||||
}
|
||||
else {
|
||||
JavaModule.Automatic(automaticModuleName(), root)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addModularRoots(modules: List<JavaModule>, result: MutableList<JavaRoot>) {
|
||||
val sourceModules = modules.filterIsInstance<JavaModule.Explicit>().filterNot(JavaModule::isBinary)
|
||||
if (sourceModules.size > 1) {
|
||||
@@ -113,12 +135,17 @@ internal class ClasspathRootsResolver(
|
||||
|
||||
if (javaModuleFinder.allObservableModules.none()) return
|
||||
|
||||
val rootModules =
|
||||
if (sourceModules.isNotEmpty()) {
|
||||
// TODO: support an option similar to --add-modules
|
||||
listOf(sourceModules.single().name)
|
||||
}
|
||||
else computeDefaultRootModules() // TODO: + everything from module path
|
||||
val addAllModulePathToRoots = "ALL-MODULE-PATH" in additionalModules
|
||||
if (addAllModulePathToRoots && sourceModules.isNotEmpty()) {
|
||||
report(ERROR, "-Xadd-modules=ALL-MODULE-PATH can only be used when compiling the unnamed module")
|
||||
return
|
||||
}
|
||||
|
||||
val rootModules = when {
|
||||
sourceModules.isNotEmpty() -> listOf(sourceModules.single().name) + additionalModules
|
||||
addAllModulePathToRoots -> modules.map(JavaModule::name)
|
||||
else -> computeDefaultRootModules() + modules.map(JavaModule::name)
|
||||
}
|
||||
|
||||
// TODO: if at least one automatic module is added, add all automatic modules as per java.lang.module javadoc
|
||||
val allDependencies = javaModuleGraph.getAllDependencies(rootModules).also { loadedModules ->
|
||||
|
||||
@@ -194,7 +194,11 @@ class KotlinCoreEnvironment private constructor(
|
||||
|
||||
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
|
||||
classpathRootsResolver = ClasspathRootsResolver(PsiManager.getInstance(project), messageCollector, this::contentRootToVirtualFile)
|
||||
classpathRootsResolver = ClasspathRootsResolver(
|
||||
PsiManager.getInstance(project), messageCollector,
|
||||
configuration.getList(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES),
|
||||
this::contentRootToVirtualFile
|
||||
)
|
||||
|
||||
val (initialRoots, javaModules) =
|
||||
classpathRootsResolver.convertClasspathRoots(configuration.getList(JVMConfigurationKeys.CONTENT_ROOTS))
|
||||
@@ -304,7 +308,8 @@ class KotlinCoreEnvironment private constructor(
|
||||
|
||||
private fun contentRootToVirtualFile(root: JvmContentRoot): VirtualFile? {
|
||||
return when (root) {
|
||||
is JvmClasspathRoot -> if (root.file.isFile) findJarRoot(root) else findLocalFile(root)
|
||||
is JvmClasspathRoot -> if (root.file.isFile) findJarRoot(root.file) else findLocalFile(root)
|
||||
is JvmModulePathRoot -> if (root.file.isFile) findJarRoot(root.file) else findLocalFile(root)
|
||||
is JavaSourceRoot -> findLocalFile(root)
|
||||
else -> throw IllegalStateException("Unexpected root: $root")
|
||||
}
|
||||
@@ -320,8 +325,8 @@ class KotlinCoreEnvironment private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun findJarRoot(root: JvmClasspathRoot): VirtualFile? =
|
||||
applicationEnvironment.jarFileSystem.findFileByPath("${root.file}${URLUtil.JAR_SEPARATOR}")
|
||||
private fun findJarRoot(file: File): VirtualFile? =
|
||||
applicationEnvironment.jarFileSystem.findFileByPath("$file${URLUtil.JAR_SEPARATOR}")
|
||||
|
||||
private fun getSourceRootsCheckingForDuplicates(): Collection<String> {
|
||||
val uniqueSourceRoots = linkedSetOf<String>()
|
||||
|
||||
@@ -30,6 +30,8 @@ data class JvmClasspathRoot(override val file: File) : JvmContentRoot
|
||||
|
||||
data class JavaSourceRoot(override val file: File, val packagePrefix: String?) : JvmContentRoot
|
||||
|
||||
data class JvmModulePathRoot(override val file: File) : JvmContentRoot
|
||||
|
||||
fun CompilerConfiguration.addJvmClasspathRoot(file: File) {
|
||||
add(JVMConfigurationKeys.CONTENT_ROOTS, JvmClasspathRoot(file))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user