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.MessageUtil
|
||||
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.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
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.repl.ReplFromTerminal
|
||||
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.metadata.deserialization.BinaryVersion
|
||||
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.PathUtil
|
||||
import java.io.File
|
||||
@@ -72,26 +74,8 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
val pluginLoadResult = loadPlugins(arguments, configuration)
|
||||
if (pluginLoadResult != ExitCode.OK) return pluginLoadResult
|
||||
|
||||
val commonSources = arguments.commonSources?.toSet().orEmpty()
|
||||
if (!arguments.script && arguments.buildFile == null) {
|
||||
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)
|
||||
val moduleName = arguments.moduleName ?: JvmAbi.DEFAULT_MODULE_NAME
|
||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, moduleName)
|
||||
|
||||
configuration.configureExplicitContentRoots(arguments)
|
||||
configuration.configureStandardLibs(paths, arguments)
|
||||
@@ -109,9 +93,26 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
|
||||
messageCollector.report(LOGGING, "Configuring the compilation environment")
|
||||
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) {
|
||||
messageCollector.report(STRONG_WARNING, message)
|
||||
}
|
||||
@@ -126,66 +127,37 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
}
|
||||
|
||||
val sanitizedCollector = FilteringMessageCollector(messageCollector, VERBOSE::contains)
|
||||
val buildFile = File(arguments.buildFile)
|
||||
val moduleChunk = CompileEnvironmentUtil.loadModuleChunk(buildFile, sanitizedCollector)
|
||||
|
||||
configuration.put(JVMConfigurationKeys.MODULE_XML_FILE, buildFile)
|
||||
|
||||
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)
|
||||
CompileEnvironmentUtil.loadModuleChunk(buildFile, sanitizedCollector)
|
||||
} else {
|
||||
if (destination != null) {
|
||||
if (destination.endsWith(".jar")) {
|
||||
configuration.put(JVMConfigurationKeys.OUTPUT_JAR, File(destination))
|
||||
if (destination.path.endsWith(".jar")) {
|
||||
configuration.put(JVMConfigurationKeys.OUTPUT_JAR, destination)
|
||||
} else {
|
||||
configuration.put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File(destination))
|
||||
configuration.put(JVMConfigurationKeys.OUTPUT_DIRECTORY, destination)
|
||||
}
|
||||
}
|
||||
|
||||
val environment = createCoreEnvironment(rootDisposable, configuration, messageCollector)
|
||||
?: return COMPILATION_ERROR
|
||||
val module = ModuleBuilder(moduleName, destination?.path ?: ".", "java-production")
|
||||
module.configureFromArgs(arguments)
|
||||
|
||||
environment.registerJavacIfNeeded(arguments).let {
|
||||
if (!it) return COMPILATION_ERROR
|
||||
}
|
||||
if (module.getSourceFiles().isEmpty()) {
|
||||
if (arguments.version) return OK
|
||||
|
||||
if (environment.getSourceFiles().isEmpty()) {
|
||||
if (arguments.version) {
|
||||
return OK
|
||||
}
|
||||
messageCollector.report(ERROR, "No source files")
|
||||
return COMPILATION_ERROR
|
||||
}
|
||||
|
||||
KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment)
|
||||
|
||||
compileJavaFilesIfNeeded(environment, arguments).let {
|
||||
if (!it) return COMPILATION_ERROR
|
||||
}
|
||||
ModuleChunk(listOf(module))
|
||||
}
|
||||
|
||||
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
|
||||
} catch (e: CompilationException) {
|
||||
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 {
|
||||
var pluginClasspaths: Iterable<String> = arguments.pluginClasspaths?.asIterable() ?: emptyList()
|
||||
val pluginOptions = arguments.pluginOptions?.toMutableList() ?: ArrayList()
|
||||
@@ -240,16 +236,6 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
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(
|
||||
rootDisposable: Disposable,
|
||||
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.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
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()
|
||||
|
||||
val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project)
|
||||
@@ -131,22 +128,37 @@ object KotlinToJVMBytecodeCompiler {
|
||||
|
||||
for (module in chunk) {
|
||||
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)
|
||||
.partition(VirtualFile::isDirectory)
|
||||
|
||||
val ktFiles = environment.getSourceFiles().filter { file ->
|
||||
val virtualFile = file.virtualFile
|
||||
virtualFile in moduleSourceFiles || moduleSourceDirs.any { dir ->
|
||||
VfsUtilCore.isAncestor(dir, virtualFile, true)
|
||||
environment.getSourceFiles().filter { file ->
|
||||
val virtualFile = file.virtualFile
|
||||
virtualFile in moduleSourceFiles || moduleSourceDirs.any { dir ->
|
||||
VfsUtilCore.isAncestor(dir, virtualFile, true)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
environment.getSourceFiles()
|
||||
}
|
||||
|
||||
if (!checkKotlinPackageUsage(environment, ktFiles)) return false
|
||||
|
||||
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)
|
||||
@@ -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) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -226,8 +238,9 @@ object KotlinToJVMBytecodeCompiler {
|
||||
configuration.addAll(JVMConfigurationKeys.MODULES, chunk)
|
||||
}
|
||||
|
||||
private fun getAbsolutePaths(buildFile: File, sourceFilePaths: List<String>): List<String> =
|
||||
sourceFilePaths.map { path ->
|
||||
private fun getBuildFilePaths(buildFile: File?, sourceFilePaths: List<String>): List<String> =
|
||||
if (buildFile == null) sourceFilePaths
|
||||
else sourceFilePaths.map { path ->
|
||||
(File(path).takeIf(File::isAbsolute) ?: buildFile.resolveSibling(path)).absolutePath
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user