JPS, -Xcommon-sources: don't iterate on all sources, use root info from DirtySourceFilesHolder. Cleanup code.
Also:
- Pass `-Xcommon-sources` argument to JS compiler.
- Calculate all sources list only when needed (after change it is not required to calculate common-sources)
- Remove `chunk: ModuleChunk` parameter from some `KotlinModuleBuildTarget` functions.
Original commit: 8cd3b46f05
This commit is contained in:
@@ -125,7 +125,8 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
|
|||||||
k2jsArguments: K2JSCompilerArguments,
|
k2jsArguments: K2JSCompilerArguments,
|
||||||
compilerSettings: CompilerSettings,
|
compilerSettings: CompilerSettings,
|
||||||
environment: JpsCompilerEnvironment,
|
environment: JpsCompilerEnvironment,
|
||||||
sourceFiles: Collection<File>,
|
allSourceFiles: Collection<File>,
|
||||||
|
commonSources: Collection<File>,
|
||||||
sourceMapRoots: Collection<File>,
|
sourceMapRoots: Collection<File>,
|
||||||
libraries: List<String>,
|
libraries: List<String>,
|
||||||
friendModules: List<String>,
|
friendModules: List<String>,
|
||||||
@@ -137,7 +138,7 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
|
|||||||
val arguments = mergeBeans(commonArguments, XmlSerializerUtil.createCopy(k2jsArguments))
|
val arguments = mergeBeans(commonArguments, XmlSerializerUtil.createCopy(k2jsArguments))
|
||||||
log.debug("K2JS: merged arguments: " + ArgumentUtils.convertArgumentsToStringList(arguments))
|
log.debug("K2JS: merged arguments: " + ArgumentUtils.convertArgumentsToStringList(arguments))
|
||||||
|
|
||||||
setupK2JsArguments(outputFile, sourceFiles, libraries, friendModules, arguments)
|
setupK2JsArguments(outputFile, allSourceFiles, commonSources, libraries, friendModules, arguments)
|
||||||
if (arguments.sourceMap) {
|
if (arguments.sourceMap) {
|
||||||
arguments.sourceMapBaseDirs = sourceMapRoots.joinToString(File.pathSeparator) { it.path }
|
arguments.sourceMapBaseDirs = sourceMapRoots.joinToString(File.pathSeparator) { it.path }
|
||||||
}
|
}
|
||||||
@@ -290,14 +291,16 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
|
|||||||
|
|
||||||
private fun setupK2JsArguments(
|
private fun setupK2JsArguments(
|
||||||
_outputFile: File,
|
_outputFile: File,
|
||||||
sourceFiles: Collection<File>,
|
allSourceFiles: Collection<File>,
|
||||||
|
_commonSources: Collection<File>,
|
||||||
_libraries: List<String>,
|
_libraries: List<String>,
|
||||||
_friendModules: List<String>,
|
_friendModules: List<String>,
|
||||||
settings: K2JSCompilerArguments
|
settings: K2JSCompilerArguments
|
||||||
) {
|
) {
|
||||||
with(settings) {
|
with(settings) {
|
||||||
noStdlib = true
|
noStdlib = true
|
||||||
freeArgs = sourceFiles.map { it.path }.toMutableList()
|
freeArgs = allSourceFiles.map { it.path }.toMutableList()
|
||||||
|
commonSources = _commonSources.map { it.path }.toTypedArray()
|
||||||
outputFile = _outputFile.path
|
outputFile = _outputFile.path
|
||||||
metaInfo = true
|
metaInfo = true
|
||||||
libraries = _libraries.joinToString(File.pathSeparator)
|
libraries = _libraries.joinToString(File.pathSeparator)
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class FSOperationsHelper(
|
|||||||
internal fun markFilesForCurrentRound(files: Iterable<File>) {
|
internal fun markFilesForCurrentRound(files: Iterable<File>) {
|
||||||
files.forEach {
|
files.forEach {
|
||||||
val root = compileContext.projectDescriptor.buildRootIndex.findJavaRootDescriptor(compileContext, it)
|
val root = compileContext.projectDescriptor.buildRootIndex.findJavaRootDescriptor(compileContext, it)
|
||||||
if (root != null) dirtyFilesHolder.byTarget[root.target]?._markDirty(it)
|
if (root != null) dirtyFilesHolder.byTarget[root.target]?._markDirty(it, root)
|
||||||
}
|
}
|
||||||
|
|
||||||
markFilesImpl(files, currentRound = true) { it.exists() && moduleBasedFilter.accept(it) }
|
markFilesImpl(files, currentRound = true) { it.exists() && moduleBasedFilter.accept(it) }
|
||||||
@@ -78,7 +78,8 @@ class FSOperationsHelper(
|
|||||||
|
|
||||||
val targetDirtyFiles = dirtyFilesHolder.byTarget[target]!!
|
val targetDirtyFiles = dirtyFilesHolder.byTarget[target]!!
|
||||||
files.forEach {
|
files.forEach {
|
||||||
targetDirtyFiles._markDirty(it)
|
val root = compileContext.projectDescriptor.buildRootIndex.findJavaRootDescriptor(compileContext, it)!!
|
||||||
|
targetDirtyFiles._markDirty(it, root)
|
||||||
}
|
}
|
||||||
|
|
||||||
markFilesImpl(files, currentRound = true) { it.exists() }
|
markFilesImpl(files, currentRound = true) { it.exists() }
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
|
|||||||
val removedClasses = HashSet<String>()
|
val removedClasses = HashSet<String>()
|
||||||
for (target in kotlinChunk.targets) {
|
for (target in kotlinChunk.targets) {
|
||||||
val cache = incrementalCaches[target] ?: continue
|
val cache = incrementalCaches[target] ?: continue
|
||||||
val dirtyFiles = dirtyFilesHolder.getDirtyFiles(target.jpsModuleBuildTarget)
|
val dirtyFiles = dirtyFilesHolder.getDirtyFiles(target.jpsModuleBuildTarget).keys
|
||||||
val removedFiles = dirtyFilesHolder.getRemovedFiles(target.jpsModuleBuildTarget)
|
val removedFiles = dirtyFilesHolder.getRemovedFiles(target.jpsModuleBuildTarget)
|
||||||
|
|
||||||
val existingClasses = JpsKotlinCompilerRunner().classesFqNamesByFiles(environment, dirtyFiles)
|
val existingClasses = JpsKotlinCompilerRunner().classesFqNamesByFiles(environment, dirtyFiles)
|
||||||
@@ -497,17 +497,17 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
|
|||||||
|
|
||||||
if (cache != null && targetDirtyFiles != null) {
|
if (cache != null && targetDirtyFiles != null) {
|
||||||
val complementaryFiles = cache.clearComplementaryFilesMapping(
|
val complementaryFiles = cache.clearComplementaryFilesMapping(
|
||||||
targetDirtyFiles.dirty + targetDirtyFiles.removed
|
targetDirtyFiles.dirty.keys + targetDirtyFiles.removed
|
||||||
)
|
)
|
||||||
|
|
||||||
fsOperations.markFilesForCurrentRound(jpsTarget, complementaryFiles)
|
fsOperations.markFilesForCurrentRound(jpsTarget, complementaryFiles)
|
||||||
|
|
||||||
cache.markDirty(targetDirtyFiles.dirty + targetDirtyFiles.removed)
|
cache.markDirty(targetDirtyFiles.dirty.keys + targetDirtyFiles.removed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val isDoneSomething = representativeTarget.compileModuleChunk(chunk, commonArguments, dirtyFilesHolder, environment)
|
val isDoneSomething = representativeTarget.compileModuleChunk(commonArguments, dirtyFilesHolder, environment)
|
||||||
|
|
||||||
return if (isDoneSomething) environment.outputItemsCollector else null
|
return if (isDoneSomething) environment.outputItemsCollector else null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.jetbrains.jps.builders.DirtyFilesHolder
|
|||||||
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor
|
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor
|
||||||
import org.jetbrains.jps.incremental.CompileContext
|
import org.jetbrains.jps.incremental.CompileContext
|
||||||
import org.jetbrains.jps.incremental.ModuleBuildTarget
|
import org.jetbrains.jps.incremental.ModuleBuildTarget
|
||||||
|
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,17 +39,17 @@ class KotlinDirtySourceFilesHolder(
|
|||||||
val byTarget: Map<ModuleBuildTarget, TargetFiles>
|
val byTarget: Map<ModuleBuildTarget, TargetFiles>
|
||||||
|
|
||||||
inner class TargetFiles(val target: ModuleBuildTarget, val removed: Collection<File>) {
|
inner class TargetFiles(val target: ModuleBuildTarget, val removed: Collection<File>) {
|
||||||
private val _dirty: MutableSet<File> = mutableSetOf()
|
private val _dirty: MutableMap<File, KotlinModuleBuildTarget.Source> = mutableMapOf()
|
||||||
|
|
||||||
val dirty: Set<File>
|
val dirty: Map<File, KotlinModuleBuildTarget.Source>
|
||||||
get() = _dirty
|
get() = _dirty
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should be called only from [FSOperationsHelper.markFilesForCurrentRound]
|
* Should be called only from [FSOperationsHelper.markFilesForCurrentRound]
|
||||||
* and during KotlinDirtySourceFilesHolder initialization.
|
* and during KotlinDirtySourceFilesHolder initialization.
|
||||||
*/
|
*/
|
||||||
internal fun _markDirty(file: File) {
|
internal fun _markDirty(file: File, root: JavaSourceRootDescriptor) {
|
||||||
_dirty.add(file.canonicalFile)
|
_dirty[file.canonicalFile] = KotlinModuleBuildTarget.Source(file, root is KotlinIncludedModuleSourceRoot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ class KotlinDirtySourceFilesHolder(
|
|||||||
?: error("processDirtyFiles should callback only on chunk `$chunk` targets (`$target` is not)")
|
?: error("processDirtyFiles should callback only on chunk `$chunk` targets (`$target` is not)")
|
||||||
|
|
||||||
if (file.isKotlinSourceFile) {
|
if (file.isKotlinSourceFile) {
|
||||||
targetInfo._markDirty(file)
|
targetInfo._markDirty(file, root)
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
@@ -83,14 +84,14 @@ class KotlinDirtySourceFilesHolder(
|
|||||||
this.byTarget = byTarget
|
this.byTarget = byTarget
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDirtyFiles(target: ModuleBuildTarget): Set<File> =
|
fun getDirtyFiles(target: ModuleBuildTarget): Map<File, KotlinModuleBuildTarget.Source> =
|
||||||
byTarget[target]?.dirty ?: setOf()
|
byTarget[target]?.dirty ?: mapOf()
|
||||||
|
|
||||||
fun getRemovedFiles(target: ModuleBuildTarget): Collection<File> =
|
fun getRemovedFiles(target: ModuleBuildTarget): Collection<File> =
|
||||||
byTarget[target]?.removed ?: listOf()
|
byTarget[target]?.removed ?: listOf()
|
||||||
|
|
||||||
val allDirtyFiles: Set<File>
|
val allDirtyFiles: Set<File>
|
||||||
get() = byTarget.flatMapTo(mutableSetOf()) { it.value.dirty }
|
get() = byTarget.flatMapTo(mutableSetOf()) { it.value.dirty.keys }
|
||||||
|
|
||||||
val allRemovedFilesFiles: Set<File>
|
val allRemovedFilesFiles: Set<File>
|
||||||
get() = byTarget.flatMapTo(mutableSetOf()) { it.value.removed }
|
get() = byTarget.flatMapTo(mutableSetOf()) { it.value.removed }
|
||||||
|
|||||||
+3
-3
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.jps.targets
|
package org.jetbrains.kotlin.jps.targets
|
||||||
|
|
||||||
import org.jetbrains.jps.ModuleChunk
|
|
||||||
import org.jetbrains.jps.builders.storage.BuildDataPaths
|
import org.jetbrains.jps.builders.storage.BuildDataPaths
|
||||||
import org.jetbrains.jps.incremental.ModuleBuildTarget
|
import org.jetbrains.jps.incremental.ModuleBuildTarget
|
||||||
import org.jetbrains.jps.model.library.JpsOrderRootType
|
import org.jetbrains.jps.model.library.JpsOrderRootType
|
||||||
@@ -45,12 +44,13 @@ class KotlinCommonModuleBuildTarget(kotlinContext: KotlinCompileContext, jpsModu
|
|||||||
get() = "metadata-compiler"
|
get() = "metadata-compiler"
|
||||||
|
|
||||||
override fun compileModuleChunk(
|
override fun compileModuleChunk(
|
||||||
chunk: ModuleChunk,
|
|
||||||
commonArguments: CommonCompilerArguments,
|
commonArguments: CommonCompilerArguments,
|
||||||
dirtyFilesHolder: KotlinDirtySourceFilesHolder,
|
dirtyFilesHolder: KotlinDirtySourceFilesHolder,
|
||||||
environment: JpsCompilerEnvironment
|
environment: JpsCompilerEnvironment
|
||||||
): Boolean {
|
): Boolean {
|
||||||
reportAndSkipCircular(chunk, environment)
|
require(chunk.representativeTarget == this)
|
||||||
|
|
||||||
|
reportAndSkipCircular(environment)
|
||||||
|
|
||||||
JpsKotlinCompilerRunner().runK2MetadataCompiler(
|
JpsKotlinCompilerRunner().runK2MetadataCompiler(
|
||||||
commonArguments,
|
commonArguments,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.jps.targets
|
package org.jetbrains.kotlin.jps.targets
|
||||||
|
|
||||||
import org.jetbrains.jps.ModuleChunk
|
|
||||||
import org.jetbrains.jps.builders.storage.BuildDataPaths
|
import org.jetbrains.jps.builders.storage.BuildDataPaths
|
||||||
import org.jetbrains.jps.incremental.ModuleBuildTarget
|
import org.jetbrains.jps.incremental.ModuleBuildTarget
|
||||||
import org.jetbrains.jps.model.library.JpsOrderRootType
|
import org.jetbrains.jps.model.library.JpsOrderRootType
|
||||||
@@ -86,16 +85,19 @@ class KotlinJsModuleBuildTarget(kotlinContext: KotlinCompileContext, jpsModuleBu
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun compileModuleChunk(
|
override fun compileModuleChunk(
|
||||||
chunk: ModuleChunk,
|
|
||||||
commonArguments: CommonCompilerArguments,
|
commonArguments: CommonCompilerArguments,
|
||||||
dirtyFilesHolder: KotlinDirtySourceFilesHolder,
|
dirtyFilesHolder: KotlinDirtySourceFilesHolder,
|
||||||
environment: JpsCompilerEnvironment
|
environment: JpsCompilerEnvironment
|
||||||
): Boolean {
|
): Boolean {
|
||||||
require(chunk.representativeTarget() == jpsModuleBuildTarget)
|
require(chunk.representativeTarget == this)
|
||||||
if (reportAndSkipCircular(chunk, environment)) return false
|
|
||||||
|
if (reportAndSkipCircular(environment)) return false
|
||||||
|
|
||||||
val sources = collectSourcesToCompile(dirtyFilesHolder)
|
val sources = collectSourcesToCompile(dirtyFilesHolder)
|
||||||
if (!checkShouldCompileAndLog(dirtyFilesHolder, sources)) return false
|
|
||||||
|
if (!sources.logFiles()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
val libraries = libraryFiles + dependenciesMetaFiles
|
val libraries = libraryFiles + dependenciesMetaFiles
|
||||||
|
|
||||||
@@ -104,7 +106,8 @@ class KotlinJsModuleBuildTarget(kotlinContext: KotlinCompileContext, jpsModuleBu
|
|||||||
module.k2JsCompilerArguments,
|
module.k2JsCompilerArguments,
|
||||||
module.kotlinCompilerSettings,
|
module.kotlinCompilerSettings,
|
||||||
environment,
|
environment,
|
||||||
sources,
|
sources.allFiles,
|
||||||
|
sources.crossCompiledFiles,
|
||||||
sourceMapRoots,
|
sourceMapRoots,
|
||||||
libraries,
|
libraries,
|
||||||
friendBuildTargetsMetaFiles,
|
friendBuildTargetsMetaFiles,
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class KotlinJvmModuleBuildTarget(kotlinContext: KotlinCompileContext, jpsModuleB
|
|||||||
with(builder) {
|
with(builder) {
|
||||||
register(
|
register(
|
||||||
IncrementalCompilationComponents::class.java,
|
IncrementalCompilationComponents::class.java,
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
IncrementalCompilationComponentsImpl(
|
IncrementalCompilationComponentsImpl(
|
||||||
incrementalCaches.mapKeys { it.key.targetId } as Map<TargetId, IncrementalCache>
|
incrementalCaches.mapKeys { it.key.targetId } as Map<TargetId, IncrementalCache>
|
||||||
)
|
)
|
||||||
@@ -82,27 +83,28 @@ class KotlinJvmModuleBuildTarget(kotlinContext: KotlinCompileContext, jpsModuleB
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun compileModuleChunk(
|
override fun compileModuleChunk(
|
||||||
chunk: ModuleChunk,
|
|
||||||
commonArguments: CommonCompilerArguments,
|
commonArguments: CommonCompilerArguments,
|
||||||
dirtyFilesHolder: KotlinDirtySourceFilesHolder,
|
dirtyFilesHolder: KotlinDirtySourceFilesHolder,
|
||||||
environment: JpsCompilerEnvironment
|
environment: JpsCompilerEnvironment
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (chunk.modules.size > 1) {
|
require(chunk.representativeTarget == this)
|
||||||
|
|
||||||
|
if (chunk.targets.size > 1) {
|
||||||
environment.messageCollector.report(
|
environment.messageCollector.report(
|
||||||
CompilerMessageSeverity.STRONG_WARNING,
|
CompilerMessageSeverity.STRONG_WARNING,
|
||||||
"Circular dependencies are only partially supported. The following modules depend on each other: "
|
"Circular dependencies are only partially supported. " +
|
||||||
+ chunk.modules.joinToString(", ") { it.name } + " "
|
"The following modules depend on each other: ${chunk.presentableShortName}. " +
|
||||||
+ "Kotlin will compile them, but some strange effect may happen"
|
"Kotlin will compile them, but some strange effect may happen"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val filesSet = dirtyFilesHolder.allDirtyFiles
|
val filesSet = dirtyFilesHolder.allDirtyFiles
|
||||||
|
|
||||||
val moduleFile = generateModuleDescription(chunk, dirtyFilesHolder)
|
val moduleFile = generateChunkModuleDescription(dirtyFilesHolder)
|
||||||
if (moduleFile == null) {
|
if (moduleFile == null) {
|
||||||
if (KotlinBuilder.LOG.isDebugEnabled) {
|
if (KotlinBuilder.LOG.isDebugEnabled) {
|
||||||
KotlinBuilder.LOG.debug(
|
KotlinBuilder.LOG.debug(
|
||||||
"Not compiling, because no files affected: " + chunk.targets.joinToString { it.presentableName }
|
"Not compiling, because no files affected: " + chunk.presentableShortName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,13 +112,15 @@ class KotlinJvmModuleBuildTarget(kotlinContext: KotlinCompileContext, jpsModuleB
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val module = chunk.representativeTarget().module
|
val module = chunk.representativeTarget.module
|
||||||
|
|
||||||
if (KotlinBuilder.LOG.isDebugEnabled) {
|
if (KotlinBuilder.LOG.isDebugEnabled) {
|
||||||
val totalRemovedFiles = dirtyFilesHolder.allRemovedFilesFiles.size
|
val totalRemovedFiles = dirtyFilesHolder.allRemovedFilesFiles.size
|
||||||
KotlinBuilder.LOG.debug("Compiling to JVM ${filesSet.size} files"
|
KotlinBuilder.LOG.debug(
|
||||||
+ (if (totalRemovedFiles == 0) "" else " ($totalRemovedFiles removed files)")
|
"Compiling to JVM ${filesSet.size} files"
|
||||||
+ " in " + chunk.targets.joinToString { it.presentableName })
|
+ (if (totalRemovedFiles == 0) "" else " ($totalRemovedFiles removed files)")
|
||||||
|
+ " in " + chunk.presentableShortName
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -137,35 +141,35 @@ class KotlinJvmModuleBuildTarget(kotlinContext: KotlinCompileContext, jpsModuleB
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateModuleDescription(chunk: ModuleChunk, dirtyFilesHolder: KotlinDirtySourceFilesHolder): File? {
|
private fun generateChunkModuleDescription(dirtyFilesHolder: KotlinDirtySourceFilesHolder): File? {
|
||||||
val builder = KotlinModuleXmlBuilder()
|
val builder = KotlinModuleXmlBuilder()
|
||||||
|
|
||||||
var hasDirtySources = false
|
var hasDirtySources = false
|
||||||
|
|
||||||
val targets = chunk.targets.mapNotNull { kotlinContext.targetsBinding[it] as? KotlinJvmModuleBuildTarget }
|
val targets = chunk.targets
|
||||||
|
|
||||||
val outputDirs = targets.map { it.outputDir }.toSet()
|
val outputDirs = targets.map { it.outputDir }.toSet()
|
||||||
|
|
||||||
for (target in targets) {
|
for (target in targets) {
|
||||||
|
target as KotlinJvmModuleBuildTarget
|
||||||
|
|
||||||
val outputDir = target.outputDir
|
val outputDir = target.outputDir
|
||||||
val friendDirs = target.friendOutputDirs
|
val friendDirs = target.friendOutputDirs
|
||||||
|
|
||||||
val moduleSources = collectSourcesToCompile(target, dirtyFilesHolder).toSet()
|
val sources = target.collectSourcesToCompile(dirtyFilesHolder)
|
||||||
val commonSources = sources
|
|
||||||
.filter { it.value.isIncludedSourceRoot && it.key in moduleSources }
|
|
||||||
.map { it.key }
|
|
||||||
|
|
||||||
val hasDirtyOrRemovedSources = checkShouldCompileAndLog(target, dirtyFilesHolder, moduleSources)
|
if (sources.logFiles()) {
|
||||||
if (hasDirtyOrRemovedSources) hasDirtySources = true
|
hasDirtySources = true
|
||||||
|
}
|
||||||
|
|
||||||
val kotlinModuleId = target.targetId
|
val kotlinModuleId = target.targetId
|
||||||
builder.addModule(
|
builder.addModule(
|
||||||
kotlinModuleId.name,
|
kotlinModuleId.name,
|
||||||
outputDir.absolutePath,
|
outputDir.absolutePath,
|
||||||
moduleSources,
|
sources.allFiles,
|
||||||
target.findSourceRoots(dirtyFilesHolder.context),
|
target.findSourceRoots(dirtyFilesHolder.context),
|
||||||
target.findClassPathRoots(),
|
target.findClassPathRoots(),
|
||||||
commonSources,
|
sources.crossCompiledFiles,
|
||||||
target.findModularJdkRoot(),
|
target.findModularJdkRoot(),
|
||||||
kotlinModuleId.type,
|
kotlinModuleId.type,
|
||||||
isTests,
|
isTests,
|
||||||
@@ -177,15 +181,15 @@ class KotlinJvmModuleBuildTarget(kotlinContext: KotlinCompileContext, jpsModuleB
|
|||||||
|
|
||||||
if (!hasDirtySources) return null
|
if (!hasDirtySources) return null
|
||||||
|
|
||||||
val scriptFile = createTempFileForModuleDesc(chunk)
|
val scriptFile = createTempFileForChunkModuleDesc()
|
||||||
FileUtil.writeToFile(scriptFile, builder.asText().toString())
|
FileUtil.writeToFile(scriptFile, builder.asText().toString())
|
||||||
return scriptFile
|
return scriptFile
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTempFileForModuleDesc(chunk: ModuleChunk): File {
|
private fun createTempFileForChunkModuleDesc(): File {
|
||||||
val readableSuffix = buildString {
|
val readableSuffix = buildString {
|
||||||
append(StringUtil.sanitizeJavaIdentifier(chunk.representativeTarget().module.name))
|
append(StringUtil.sanitizeJavaIdentifier(chunk.representativeTarget.module.name))
|
||||||
if (chunk.containsTests()) {
|
if (chunk.containsTests) {
|
||||||
append("-test")
|
append("-test")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,7 +280,7 @@ class KotlinJvmModuleBuildTarget(kotlinContext: KotlinCompileContext, jpsModuleB
|
|||||||
val targetDirtyFiles: Map<ModuleBuildTarget, Set<File>> = chunk.targets.keysToMap {
|
val targetDirtyFiles: Map<ModuleBuildTarget, Set<File>> = chunk.targets.keysToMap {
|
||||||
val files = HashSet<File>()
|
val files = HashSet<File>()
|
||||||
files.addAll(dirtyFilesHolder.getRemovedFiles(it))
|
files.addAll(dirtyFilesHolder.getRemovedFiles(it))
|
||||||
files.addAll(dirtyFilesHolder.getDirtyFiles(it))
|
files.addAll(dirtyFilesHolder.getDirtyFiles(it).keys)
|
||||||
files
|
files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,21 +137,25 @@ abstract class KotlinModuleBuildTarget<BuildMetaInfoType : BuildMetaInfo> intern
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* All sources of this target (including non dirty).
|
* All sources of this target (including non dirty).
|
||||||
* Initialized lazily based on global context and will be updated on each round based on round local context.
|
|
||||||
*
|
*
|
||||||
|
* Lazy initialization is required since value is required only in rare cases.
|
||||||
|
*
|
||||||
|
* Before first round initialized lazily based on global context.
|
||||||
|
* This is required for friend build targets, when friends are not compiled in this build run.
|
||||||
|
*
|
||||||
|
* Lazy value will be invalidated on each round (should be recalculated based on round local context).
|
||||||
* Update required since source roots can be changed, for example groovy can provide new temporary source roots with stubs.
|
* Update required since source roots can be changed, for example groovy can provide new temporary source roots with stubs.
|
||||||
* Lazy initialization is required for friend build targets, when friends are not compiled in this build run.
|
*
|
||||||
|
* Ugly delegation to lazy is used to capture local compile context and reset calculated value.
|
||||||
*/
|
*/
|
||||||
val sources: Map<File, Source>
|
val sources: Map<File, Source>
|
||||||
get() = _sources ?: synchronized(this) {
|
get() = _sources.value
|
||||||
_sources ?: updateSourcesList(jpsGlobalContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
private var _sources: Map<File, Source>? = null
|
private var _sources: Lazy<Map<File, Source>> = lazy { updateSourcesList(jpsGlobalContext) }
|
||||||
|
|
||||||
fun nextRound(localContext: CompileContext) {
|
fun nextRound(localContext: CompileContext) {
|
||||||
updateSourcesList(localContext)
|
_sources = lazy { updateSourcesList(localContext) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateSourcesList(localContext: CompileContext): Map<File, Source> {
|
private fun updateSourcesList(localContext: CompileContext): Map<File, Source> {
|
||||||
@@ -165,34 +169,33 @@ abstract class KotlinModuleBuildTarget<BuildMetaInfoType : BuildMetaInfo> intern
|
|||||||
val buildRootIndex = localContext.projectDescriptor.buildRootIndex
|
val buildRootIndex = localContext.projectDescriptor.buildRootIndex
|
||||||
val roots = buildRootIndex.getTargetRoots(jpsModuleBuildTarget, localContext)
|
val roots = buildRootIndex.getTargetRoots(jpsModuleBuildTarget, localContext)
|
||||||
roots.forEach { rootDescriptor ->
|
roots.forEach { rootDescriptor ->
|
||||||
val isIncludedSourceRoot = rootDescriptor is KotlinIncludedModuleSourceRoot
|
val isCrossCompiled = rootDescriptor is KotlinIncludedModuleSourceRoot
|
||||||
|
|
||||||
rootDescriptor.root.walkTopDown()
|
rootDescriptor.root.walkTopDown()
|
||||||
.onEnter { file -> file !in moduleExcludes }
|
.onEnter { file -> file !in moduleExcludes }
|
||||||
.forEach { file ->
|
.forEach { file ->
|
||||||
if (!compilerExcludes.isExcluded(file) && file.isFile && file.isKotlinSourceFile) {
|
if (!compilerExcludes.isExcluded(file) && file.isFile && file.isKotlinSourceFile) {
|
||||||
result[file] = Source(file, isIncludedSourceRoot)
|
result[file] = Source(file, isCrossCompiled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._sources = result
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property isIncludedSourceRoot sources that are cross-compiled to multiple targets
|
* @property isCrossCompiled sources that are cross-compiled to multiple targets
|
||||||
*/
|
*/
|
||||||
class Source(
|
class Source(
|
||||||
val file: File,
|
val file: File,
|
||||||
val isIncludedSourceRoot: Boolean
|
val isCrossCompiled: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
fun isFromIncludedSourceRoot(file: File): Boolean = sources[file]?.isIncludedSourceRoot == true
|
fun isFromIncludedSourceRoot(file: File): Boolean = sources[file]?.isCrossCompiled == true
|
||||||
|
|
||||||
val sourceFiles: Collection<File>
|
val sourceFiles: Collection<File>
|
||||||
get() = sources.values.map { it.file }
|
get() = sources.keys
|
||||||
|
|
||||||
override fun toString() = jpsModuleBuildTarget.toString()
|
override fun toString() = jpsModuleBuildTarget.toString()
|
||||||
|
|
||||||
@@ -200,23 +203,19 @@ abstract class KotlinModuleBuildTarget<BuildMetaInfoType : BuildMetaInfo> intern
|
|||||||
* Called for `ModuleChunk.representativeTarget`
|
* Called for `ModuleChunk.representativeTarget`
|
||||||
*/
|
*/
|
||||||
abstract fun compileModuleChunk(
|
abstract fun compileModuleChunk(
|
||||||
chunk: ModuleChunk,
|
|
||||||
commonArguments: CommonCompilerArguments,
|
commonArguments: CommonCompilerArguments,
|
||||||
dirtyFilesHolder: KotlinDirtySourceFilesHolder,
|
dirtyFilesHolder: KotlinDirtySourceFilesHolder,
|
||||||
environment: JpsCompilerEnvironment
|
environment: JpsCompilerEnvironment
|
||||||
): Boolean
|
): Boolean
|
||||||
|
|
||||||
protected fun reportAndSkipCircular(
|
protected fun reportAndSkipCircular(environment: JpsCompilerEnvironment): Boolean {
|
||||||
chunk: ModuleChunk,
|
if (chunk.targets.size > 1) {
|
||||||
environment: JpsCompilerEnvironment
|
|
||||||
): Boolean {
|
|
||||||
if (chunk.modules.size > 1) {
|
|
||||||
// We do not support circular dependencies, but if they are present, we do our best should not break the build,
|
// We do not support circular dependencies, but if they are present, we do our best should not break the build,
|
||||||
// so we simply yield a warning and report NOTHING_DONE
|
// so we simply yield a warning and report NOTHING_DONE
|
||||||
environment.messageCollector.report(
|
environment.messageCollector.report(
|
||||||
CompilerMessageSeverity.STRONG_WARNING,
|
CompilerMessageSeverity.STRONG_WARNING,
|
||||||
"Circular dependencies are not supported. The following modules depend on each other: "
|
"Circular dependencies are not supported. The following modules depend on each other: "
|
||||||
+ chunk.modules.joinToString(", ") { it.name } + " "
|
+ chunk.presentableShortName + " "
|
||||||
+ "Kotlin is not compiled for these modules"
|
+ "Kotlin is not compiled for these modules"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -273,46 +272,45 @@ abstract class KotlinModuleBuildTarget<BuildMetaInfoType : BuildMetaInfo> intern
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun collectSourcesToCompile(dirtyFilesHolder: KotlinDirtySourceFilesHolder) =
|
|
||||||
collectSourcesToCompile(this, dirtyFilesHolder)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should be used only for particular target in chunk (jvm)
|
* Should be used only for particular target in chunk (jvm)
|
||||||
|
*
|
||||||
|
* Should not be cached since may be vary in different rounds.
|
||||||
*/
|
*/
|
||||||
protected fun collectSourcesToCompile(
|
protected fun collectSourcesToCompile(
|
||||||
target: KotlinModuleBuildTarget<BuildMetaInfoType>,
|
|
||||||
dirtyFilesHolder: KotlinDirtySourceFilesHolder
|
dirtyFilesHolder: KotlinDirtySourceFilesHolder
|
||||||
): Collection<File> {
|
) = SourcesToCompile(
|
||||||
// Should not be cached since may be vary in different rounds
|
sources = when {
|
||||||
|
chunk.representativeTarget.isIncrementalCompilationEnabled ->
|
||||||
|
dirtyFilesHolder.getDirtyFiles(jpsModuleBuildTarget).values
|
||||||
|
else -> sources.values
|
||||||
|
},
|
||||||
|
removedFiles = dirtyFilesHolder.getRemovedFiles(jpsModuleBuildTarget)
|
||||||
|
)
|
||||||
|
|
||||||
val jpsModuleTarget = target.jpsModuleBuildTarget
|
inner class SourcesToCompile(
|
||||||
return when {
|
sources: Collection<KotlinModuleBuildTarget.Source>,
|
||||||
isIncrementalCompilationEnabled -> dirtyFilesHolder.getDirtyFiles(jpsModuleTarget)
|
val removedFiles: Collection<File>
|
||||||
else -> target.sourceFiles
|
) {
|
||||||
}
|
val allFiles = sources.map { it.file }
|
||||||
}
|
val crossCompiledFiles = sources.filter { it.isCrossCompiled }.map { it.file }
|
||||||
|
|
||||||
protected fun checkShouldCompileAndLog(dirtyFilesHolder: KotlinDirtySourceFilesHolder, moduleSources: Collection<File>) =
|
/**
|
||||||
checkShouldCompileAndLog(this, dirtyFilesHolder, moduleSources)
|
* @return true, if there are removed files or files to compile
|
||||||
|
*/
|
||||||
|
fun logFiles(): Boolean {
|
||||||
|
val hasRemovedSources = removedFiles.isNotEmpty()
|
||||||
|
val hasDirtyOrRemovedSources = allFiles.isNotEmpty() || hasRemovedSources
|
||||||
|
|
||||||
/**
|
if (hasDirtyOrRemovedSources) {
|
||||||
* Should be used only for particular target in chunk (jvm)
|
val logger = jpsGlobalContext.loggingManager.projectBuilderLogger
|
||||||
*/
|
if (logger.isEnabled) {
|
||||||
protected fun checkShouldCompileAndLog(
|
logger.logCompiledFiles(allFiles, KotlinBuilder.KOTLIN_BUILDER_NAME, "Compiling files:")
|
||||||
target: KotlinModuleBuildTarget<BuildMetaInfoType>,
|
}
|
||||||
dirtyFilesHolder: KotlinDirtySourceFilesHolder,
|
|
||||||
moduleSources: Collection<File>
|
|
||||||
): Boolean {
|
|
||||||
val hasRemovedSources = dirtyFilesHolder.getRemovedFiles(target.jpsModuleBuildTarget).isNotEmpty()
|
|
||||||
val hasDirtyOrRemovedSources = moduleSources.isNotEmpty() || hasRemovedSources
|
|
||||||
if (hasDirtyOrRemovedSources) {
|
|
||||||
val logger = jpsGlobalContext.loggingManager.projectBuilderLogger
|
|
||||||
if (logger.isEnabled) {
|
|
||||||
logger.logCompiledFiles(moduleSources, KotlinBuilder.KOTLIN_BUILDER_NAME, "Compiling files:")
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return hasDirtyOrRemovedSources
|
return hasDirtyOrRemovedSources
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract val buildMetaInfoFactory: BuildMetaInfoFactory<BuildMetaInfoType>
|
abstract val buildMetaInfoFactory: BuildMetaInfoFactory<BuildMetaInfoType>
|
||||||
|
|||||||
Reference in New Issue
Block a user