Unify JVM compilation with and without -Xbuild-file
This commit is contained in:
@@ -29,11 +29,12 @@ import org.jetbrains.kotlin.cli.common.messages.FilteringMessageCollector
|
|||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageUtil
|
import org.jetbrains.kotlin.cli.common.messages.MessageUtil
|
||||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||||
|
import org.jetbrains.kotlin.cli.common.modules.ModuleBuilder
|
||||||
|
import org.jetbrains.kotlin.cli.common.modules.ModuleChunk
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentUtil
|
import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentUtil
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoot
|
|
||||||
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
|
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
|
||||||
import org.jetbrains.kotlin.cli.jvm.repl.ReplFromTerminal
|
import org.jetbrains.kotlin.cli.jvm.repl.ReplFromTerminal
|
||||||
import org.jetbrains.kotlin.codegen.CompilationException
|
import org.jetbrains.kotlin.codegen.CompilationException
|
||||||
@@ -46,6 +47,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi
|
|||||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||||
|
import org.jetbrains.kotlin.modules.JavaRootPath
|
||||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -72,26 +74,8 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
val pluginLoadResult = loadPlugins(arguments, configuration)
|
val pluginLoadResult = loadPlugins(arguments, configuration)
|
||||||
if (pluginLoadResult != ExitCode.OK) return pluginLoadResult
|
if (pluginLoadResult != ExitCode.OK) return pluginLoadResult
|
||||||
|
|
||||||
val commonSources = arguments.commonSources?.toSet().orEmpty()
|
val moduleName = arguments.moduleName ?: JvmAbi.DEFAULT_MODULE_NAME
|
||||||
if (!arguments.script && arguments.buildFile == null) {
|
configuration.put(CommonConfigurationKeys.MODULE_NAME, moduleName)
|
||||||
for (arg in arguments.freeArgs) {
|
|
||||||
val file = File(arg)
|
|
||||||
if (file.extension == JavaFileType.DEFAULT_EXTENSION) {
|
|
||||||
configuration.addJavaSourceRoot(file, arguments.javaPackagePrefix)
|
|
||||||
} else {
|
|
||||||
configuration.addKotlinSourceRoot(arg, isCommon = arg in commonSources)
|
|
||||||
if (file.isDirectory) {
|
|
||||||
configuration.addJavaSourceRoot(file, arguments.javaPackagePrefix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (path in arguments.javaSourceRoots ?: emptyArray()) {
|
|
||||||
configuration.addJavaSourceRoot(File(path), arguments.javaPackagePrefix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, arguments.moduleName ?: JvmAbi.DEFAULT_MODULE_NAME)
|
|
||||||
|
|
||||||
configuration.configureExplicitContentRoots(arguments)
|
configuration.configureExplicitContentRoots(arguments)
|
||||||
configuration.configureStandardLibs(paths, arguments)
|
configuration.configureStandardLibs(paths, arguments)
|
||||||
@@ -109,9 +93,26 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
|
|
||||||
messageCollector.report(LOGGING, "Configuring the compilation environment")
|
messageCollector.report(LOGGING, "Configuring the compilation environment")
|
||||||
try {
|
try {
|
||||||
val destination = arguments.destination
|
if (arguments.script) {
|
||||||
|
val sourcePath = arguments.freeArgs.first()
|
||||||
|
configuration.addKotlinSourceRoot(sourcePath)
|
||||||
|
|
||||||
if (arguments.buildFile != null) {
|
val environment = createCoreEnvironment(rootDisposable, configuration, messageCollector)
|
||||||
|
?: return COMPILATION_ERROR
|
||||||
|
|
||||||
|
val scriptingEvaluator = ScriptEvaluationExtension.getInstances(environment.project).find { it.isAccepted(arguments) }
|
||||||
|
if (scriptingEvaluator == null) {
|
||||||
|
messageCollector.report(ERROR, "Unable to evaluate script, no scripting plugin found")
|
||||||
|
return COMPILATION_ERROR
|
||||||
|
}
|
||||||
|
|
||||||
|
return scriptingEvaluator.eval(arguments, environment)
|
||||||
|
}
|
||||||
|
|
||||||
|
val destination = arguments.destination?.let { File(it) }
|
||||||
|
val buildFile = arguments.buildFile?.let { File(it) }
|
||||||
|
|
||||||
|
val moduleChunk = if (buildFile != null) {
|
||||||
fun strongWarning(message: String) {
|
fun strongWarning(message: String) {
|
||||||
messageCollector.report(STRONG_WARNING, message)
|
messageCollector.report(STRONG_WARNING, message)
|
||||||
}
|
}
|
||||||
@@ -126,66 +127,37 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val sanitizedCollector = FilteringMessageCollector(messageCollector, VERBOSE::contains)
|
val sanitizedCollector = FilteringMessageCollector(messageCollector, VERBOSE::contains)
|
||||||
val buildFile = File(arguments.buildFile)
|
|
||||||
val moduleChunk = CompileEnvironmentUtil.loadModuleChunk(buildFile, sanitizedCollector)
|
|
||||||
|
|
||||||
configuration.put(JVMConfigurationKeys.MODULE_XML_FILE, buildFile)
|
configuration.put(JVMConfigurationKeys.MODULE_XML_FILE, buildFile)
|
||||||
|
CompileEnvironmentUtil.loadModuleChunk(buildFile, sanitizedCollector)
|
||||||
KotlinToJVMBytecodeCompiler.configureSourceRoots(configuration, moduleChunk.modules, buildFile)
|
|
||||||
|
|
||||||
val environment = createCoreEnvironment(rootDisposable, configuration, messageCollector)
|
|
||||||
?: return COMPILATION_ERROR
|
|
||||||
|
|
||||||
environment.registerJavacIfNeeded(arguments).let {
|
|
||||||
if (!it) return COMPILATION_ERROR
|
|
||||||
}
|
|
||||||
|
|
||||||
KotlinToJVMBytecodeCompiler.compileModules(environment, buildFile, moduleChunk.modules)
|
|
||||||
} else if (arguments.script) {
|
|
||||||
val sourcePath = arguments.freeArgs.first()
|
|
||||||
configuration.addKotlinSourceRoot(sourcePath)
|
|
||||||
|
|
||||||
val environment = createCoreEnvironment(rootDisposable, configuration, messageCollector)
|
|
||||||
?: return COMPILATION_ERROR
|
|
||||||
|
|
||||||
val scriptingEvaluator = ScriptEvaluationExtension.getInstances(environment.project).find { it.isAccepted(arguments) }
|
|
||||||
if (scriptingEvaluator == null) {
|
|
||||||
messageCollector.report(ERROR, "Unable to evaluate script, no scripting plugin found")
|
|
||||||
return COMPILATION_ERROR
|
|
||||||
}
|
|
||||||
|
|
||||||
return scriptingEvaluator.eval(arguments, environment)
|
|
||||||
} else {
|
} else {
|
||||||
if (destination != null) {
|
if (destination != null) {
|
||||||
if (destination.endsWith(".jar")) {
|
if (destination.path.endsWith(".jar")) {
|
||||||
configuration.put(JVMConfigurationKeys.OUTPUT_JAR, File(destination))
|
configuration.put(JVMConfigurationKeys.OUTPUT_JAR, destination)
|
||||||
} else {
|
} else {
|
||||||
configuration.put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File(destination))
|
configuration.put(JVMConfigurationKeys.OUTPUT_DIRECTORY, destination)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val environment = createCoreEnvironment(rootDisposable, configuration, messageCollector)
|
val module = ModuleBuilder(moduleName, destination?.path ?: ".", "java-production")
|
||||||
?: return COMPILATION_ERROR
|
module.configureFromArgs(arguments)
|
||||||
|
|
||||||
environment.registerJavacIfNeeded(arguments).let {
|
if (module.getSourceFiles().isEmpty()) {
|
||||||
if (!it) return COMPILATION_ERROR
|
if (arguments.version) return OK
|
||||||
}
|
|
||||||
|
|
||||||
if (environment.getSourceFiles().isEmpty()) {
|
|
||||||
if (arguments.version) {
|
|
||||||
return OK
|
|
||||||
}
|
|
||||||
messageCollector.report(ERROR, "No source files")
|
messageCollector.report(ERROR, "No source files")
|
||||||
return COMPILATION_ERROR
|
return COMPILATION_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment)
|
ModuleChunk(listOf(module))
|
||||||
|
|
||||||
compileJavaFilesIfNeeded(environment, arguments).let {
|
|
||||||
if (!it) return COMPILATION_ERROR
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KotlinToJVMBytecodeCompiler.configureSourceRoots(configuration, moduleChunk.modules, buildFile)
|
||||||
|
val environment = createCoreEnvironment(rootDisposable, configuration, messageCollector)
|
||||||
|
?: return COMPILATION_ERROR
|
||||||
|
environment.registerJavacIfNeeded(arguments).let {
|
||||||
|
if (!it) return COMPILATION_ERROR
|
||||||
|
}
|
||||||
|
KotlinToJVMBytecodeCompiler.compileModules(environment, buildFile, moduleChunk.modules)
|
||||||
return OK
|
return OK
|
||||||
} catch (e: CompilationException) {
|
} catch (e: CompilationException) {
|
||||||
messageCollector.report(
|
messageCollector.report(
|
||||||
@@ -197,6 +169,30 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ModuleBuilder.configureFromArgs(args: K2JVMCompilerArguments) {
|
||||||
|
args.friendPaths?.forEach { addFriendDir(it) }
|
||||||
|
args.classpath?.split(File.pathSeparator)?.forEach { addClasspathEntry(it) }
|
||||||
|
args.javaSourceRoots?.forEach {
|
||||||
|
addJavaSourceRoot(JavaRootPath(it, args.javaPackagePrefix))
|
||||||
|
}
|
||||||
|
|
||||||
|
val commonSources = args.commonSources?.toSet().orEmpty()
|
||||||
|
for (arg in args.freeArgs) {
|
||||||
|
if (arg.endsWith(JavaFileType.DOT_DEFAULT_EXTENSION)) {
|
||||||
|
addJavaSourceRoot(JavaRootPath(arg, args.javaPackagePrefix))
|
||||||
|
} else {
|
||||||
|
addSourceFiles(arg)
|
||||||
|
if (arg in commonSources) {
|
||||||
|
addCommonSourceFiles(arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File(arg).isDirectory) {
|
||||||
|
addJavaSourceRoot(JavaRootPath(arg, args.javaPackagePrefix))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadPlugins(arguments: K2JVMCompilerArguments, configuration: CompilerConfiguration): ExitCode {
|
private fun loadPlugins(arguments: K2JVMCompilerArguments, configuration: CompilerConfiguration): ExitCode {
|
||||||
var pluginClasspaths: Iterable<String> = arguments.pluginClasspaths?.asIterable() ?: emptyList()
|
var pluginClasspaths: Iterable<String> = arguments.pluginClasspaths?.asIterable() ?: emptyList()
|
||||||
val pluginOptions = arguments.pluginOptions?.toMutableList() ?: ArrayList()
|
val pluginOptions = arguments.pluginOptions?.toMutableList() ?: ArrayList()
|
||||||
@@ -240,16 +236,6 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
return PluginCliParser.loadPluginsSafe(pluginClasspaths, pluginOptions, configuration)
|
return PluginCliParser.loadPluginsSafe(pluginClasspaths, pluginOptions, configuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun compileJavaFilesIfNeeded(
|
|
||||||
environment: KotlinCoreEnvironment,
|
|
||||||
arguments: K2JVMCompilerArguments
|
|
||||||
): Boolean {
|
|
||||||
if (arguments.compileJava) {
|
|
||||||
return JavacWrapper.getInstance(environment.project).use { it.compile() }
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createCoreEnvironment(
|
private fun createCoreEnvironment(
|
||||||
rootDisposable: Disposable,
|
rootDisposable: Disposable,
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
|
|||||||
+30
-17
@@ -45,10 +45,7 @@ import org.jetbrains.kotlin.cli.jvm.config.*
|
|||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback
|
import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.*
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
|
||||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||||
@@ -101,7 +98,7 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun compileModules(environment: KotlinCoreEnvironment, buildFile: File, chunk: List<Module>): Boolean {
|
internal fun compileModules(environment: KotlinCoreEnvironment, buildFile: File?, chunk: List<Module>): Boolean {
|
||||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||||
|
|
||||||
val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project)
|
val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project)
|
||||||
@@ -131,22 +128,37 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
|
|
||||||
for (module in chunk) {
|
for (module in chunk) {
|
||||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||||
val (moduleSourceDirs, moduleSourceFiles) =
|
|
||||||
getAbsolutePaths(buildFile, module.getSourceFiles())
|
val ktFiles = if (chunk.size > 1) {
|
||||||
|
// filter out source files from other modules
|
||||||
|
assert(buildFile != null) { "Compiling multiple modules, but build file is null" }
|
||||||
|
val (moduleSourceDirs, moduleSourceFiles) =
|
||||||
|
getBuildFilePaths(buildFile, module.getSourceFiles())
|
||||||
.mapNotNull(localFileSystem::findFileByPath)
|
.mapNotNull(localFileSystem::findFileByPath)
|
||||||
.partition(VirtualFile::isDirectory)
|
.partition(VirtualFile::isDirectory)
|
||||||
|
|
||||||
val ktFiles = environment.getSourceFiles().filter { file ->
|
environment.getSourceFiles().filter { file ->
|
||||||
val virtualFile = file.virtualFile
|
val virtualFile = file.virtualFile
|
||||||
virtualFile in moduleSourceFiles || moduleSourceDirs.any { dir ->
|
virtualFile in moduleSourceFiles || moduleSourceDirs.any { dir ->
|
||||||
VfsUtilCore.isAncestor(dir, virtualFile, true)
|
VfsUtilCore.isAncestor(dir, virtualFile, true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
environment.getSourceFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkKotlinPackageUsage(environment, ktFiles)) return false
|
if (!checkKotlinPackageUsage(environment, ktFiles)) return false
|
||||||
|
|
||||||
val moduleConfiguration = projectConfiguration.copy().apply {
|
val moduleConfiguration = projectConfiguration.copy().apply {
|
||||||
put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File(module.getOutputDirectory()))
|
if (buildFile != null) {
|
||||||
|
fun checkKeyIsNull(key: CompilerConfigurationKey<*>, name: String) {
|
||||||
|
assert(get(key) == null) { "$name should be null, when buildFile is used" }
|
||||||
|
}
|
||||||
|
|
||||||
|
checkKeyIsNull(JVMConfigurationKeys.OUTPUT_DIRECTORY, "OUTPUT_DIRECTORY")
|
||||||
|
checkKeyIsNull(JVMConfigurationKeys.OUTPUT_JAR, "OUTPUT_JAR")
|
||||||
|
put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File(module.getOutputDirectory()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outputs[module] = generate(environment, moduleConfiguration, result, ktFiles, module)
|
outputs[module] = generate(environment, moduleConfiguration, result, ktFiles, module)
|
||||||
@@ -180,11 +192,11 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun configureSourceRoots(configuration: CompilerConfiguration, chunk: List<Module>, buildFile: File) {
|
internal fun configureSourceRoots(configuration: CompilerConfiguration, chunk: List<Module>, buildFile: File? = null) {
|
||||||
for (module in chunk) {
|
for (module in chunk) {
|
||||||
val commonSources = getAbsolutePaths(buildFile, module.getCommonSourceFiles()).toSet()
|
val commonSources = getBuildFilePaths(buildFile, module.getCommonSourceFiles()).toSet()
|
||||||
|
|
||||||
for (path in getAbsolutePaths(buildFile, module.getSourceFiles())) {
|
for (path in getBuildFilePaths(buildFile, module.getSourceFiles())) {
|
||||||
configuration.addKotlinSourceRoot(path, isCommon = path in commonSources)
|
configuration.addKotlinSourceRoot(path, isCommon = path in commonSources)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,8 +238,9 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
configuration.addAll(JVMConfigurationKeys.MODULES, chunk)
|
configuration.addAll(JVMConfigurationKeys.MODULES, chunk)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAbsolutePaths(buildFile: File, sourceFilePaths: List<String>): List<String> =
|
private fun getBuildFilePaths(buildFile: File?, sourceFilePaths: List<String>): List<String> =
|
||||||
sourceFilePaths.map { path ->
|
if (buildFile == null) sourceFilePaths
|
||||||
|
else sourceFilePaths.map { path ->
|
||||||
(File(path).takeIf(File::isAbsolute) ?: buildFile.resolveSibling(path)).absolutePath
|
(File(path).takeIf(File::isAbsolute) ?: buildFile.resolveSibling(path)).absolutePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user