diff options
Diffstat (limited to 'plugins/kotlin/jps/jps-plugin/src/org/jetbrains/kotlin/jps/targets/KotlinModuleBuildTarget.kt')
-rw-r--r-- | plugins/kotlin/jps/jps-plugin/src/org/jetbrains/kotlin/jps/targets/KotlinModuleBuildTarget.kt | 379 |
1 files changed, 0 insertions, 379 deletions
diff --git a/plugins/kotlin/jps/jps-plugin/src/org/jetbrains/kotlin/jps/targets/KotlinModuleBuildTarget.kt b/plugins/kotlin/jps/jps-plugin/src/org/jetbrains/kotlin/jps/targets/KotlinModuleBuildTarget.kt deleted file mode 100644 index 905eabf285a9..000000000000 --- a/plugins/kotlin/jps/jps-plugin/src/org/jetbrains/kotlin/jps/targets/KotlinModuleBuildTarget.kt +++ /dev/null @@ -1,379 +0,0 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - -package org.jetbrains.kotlin.jps.targets - -import org.jetbrains.jps.ModuleChunk -import org.jetbrains.jps.builders.storage.BuildDataPaths -import org.jetbrains.jps.incremental.CompileContext -import org.jetbrains.jps.incremental.ModuleBuildTarget -import org.jetbrains.jps.incremental.ModuleLevelBuilder -import org.jetbrains.jps.incremental.ProjectBuildException -import org.jetbrains.jps.model.java.JpsJavaClasspathKind -import org.jetbrains.jps.model.java.JpsJavaExtensionService -import org.jetbrains.jps.model.module.JpsModule -import org.jetbrains.jps.util.JpsPathUtil -import org.jetbrains.kotlin.build.BuildMetaInfo -import org.jetbrains.kotlin.build.BuildMetaInfoFactory -import org.jetbrains.kotlin.build.GeneratedFile -import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -import org.jetbrains.kotlin.compilerRunner.JpsCompilerEnvironment -import org.jetbrains.kotlin.config.ApiVersion -import org.jetbrains.kotlin.config.LanguageVersion -import org.jetbrains.kotlin.config.Services -import org.jetbrains.kotlin.incremental.ChangesCollector -import org.jetbrains.kotlin.incremental.ExpectActualTrackerImpl -import org.jetbrains.kotlin.incremental.components.ExpectActualTracker -import org.jetbrains.kotlin.incremental.components.InlineConstTracker -import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.jps.KotlinJpsBundle -import org.jetbrains.kotlin.jps.build.* -import org.jetbrains.kotlin.jps.incremental.CacheAttributesDiff -import org.jetbrains.kotlin.jps.incremental.JpsIncrementalCache -import org.jetbrains.kotlin.jps.incremental.loadDiff -import org.jetbrains.kotlin.jps.incremental.localCacheVersionManager -import org.jetbrains.kotlin.jps.model.productionOutputFilePath -import org.jetbrains.kotlin.jps.model.testOutputFilePath -import org.jetbrains.kotlin.modules.TargetId -import org.jetbrains.kotlin.progress.CompilationCanceledException -import org.jetbrains.kotlin.progress.CompilationCanceledStatus -import org.jetbrains.kotlin.utils.addIfNotNull -import java.io.File -import kotlin.io.path.notExists -import kotlin.io.path.readText - -/** - * Properties and actions for Kotlin test / production module build target. - */ -abstract class KotlinModuleBuildTarget<BuildMetaInfoType : BuildMetaInfo> internal constructor( - val kotlinContext: KotlinCompileContext, - val jpsModuleBuildTarget: ModuleBuildTarget -) { - /** - * Note: beware of using this context for getting compilation round dependent data: - * for example groovy can provide temp source roots with stubs, and it will be visible - * only in round local compile context. - * - * TODO(1.2.80): got rid of jpsGlobalContext and replace it with kotlinContext - */ - val jpsGlobalContext: CompileContext - get() = kotlinContext.jpsContext - - // Initialized in KotlinCompileContext.loadTargets - lateinit var chunk: KotlinChunk - - abstract val globalLookupCacheId: String - - abstract val isIncrementalCompilationEnabled: Boolean - - open fun isEnabled(chunkCompilerArguments: CommonCompilerArguments): Boolean = true - - @Suppress("LeakingThis") - val localCacheVersionManager = localCacheVersionManager( - kotlinContext.dataPaths.getTargetDataRoot(jpsModuleBuildTarget).toPath(), - isIncrementalCompilationEnabled - ) - - val initialLocalCacheAttributesDiff: CacheAttributesDiff<*> = localCacheVersionManager.loadDiff() - - val module: JpsModule - get() = jpsModuleBuildTarget.module - - val isTests: Boolean - get() = jpsModuleBuildTarget.isTests - - open val targetId: TargetId - get() { - // Since IDEA 2016 each gradle source root is imported as a separate module. - // One gradle module X is imported as two JPS modules: - // 1. X-production with one production target; - // 2. X-test with one test target. - // This breaks kotlin code since internal members' names are mangled using module name. - // For example, a declaration of a function 'f' in 'X-production' becomes 'fXProduction', but a call 'f' in 'X-test' becomes 'fXTest()'. - // The workaround is to replace a name of such test target with the name of corresponding production module. - // See KT-11993. - val name = relatedProductionModule?.name ?: jpsModuleBuildTarget.id - return TargetId(name, jpsModuleBuildTarget.targetType.typeId) - } - - val outputDir by lazy { - val explicitOutputPath = if (isTests) module.testOutputFilePath else module.productionOutputFilePath - val explicitOutputDir = explicitOutputPath?.let { File(it).absoluteFile.parentFile } - return@lazy explicitOutputDir - ?: jpsModuleBuildTarget.outputDir - ?: throw ProjectBuildException(KotlinJpsBundle.message("error.message.no.output.directory.found.for.0", this)) - } - - val friendBuildTargets: List<KotlinModuleBuildTarget<*>> - get() { - val result = mutableListOf<KotlinModuleBuildTarget<*>>() - - if (isTests) { - result.addIfNotNull(kotlinContext.targetsBinding[module.productionBuildTarget]) - result.addIfNotNull(kotlinContext.targetsBinding[relatedProductionModule?.productionBuildTarget]) - } - - return result.filter { it.sources.isNotEmpty() } - } - - val friendOutputDirs: List<File> - get() = friendBuildTargets.mapNotNull { - JpsJavaExtensionService.getInstance().getOutputDirectory(it.module, false) - } - - private val relatedProductionModule: JpsModule? - get() = JpsJavaExtensionService.getInstance().getTestModuleProperties(module)?.productionModule - - data class Dependency( - val src: KotlinModuleBuildTarget<*>, - val target: KotlinModuleBuildTarget<*>, - val exported: Boolean - ) - - // TODO(1.2.80): try replace allDependencies with KotlinChunk.collectDependentChunksRecursivelyExportedOnly - @Deprecated("Consider using precalculated KotlinChunk.collectDependentChunksRecursivelyExportedOnly") - val allDependencies by lazy { - JpsJavaExtensionService.dependencies(module).recursively().exportedOnly() - .includedIn(JpsJavaClasspathKind.compile(isTests)) - } - - /** - * All sources of this target (including non dirty). - * - * 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. - * - * Ugly delegation to lazy is used to capture local compile context and reset calculated value. - */ - val sources: Map<File, Source> - get() = _sources.value - - @Volatile - private var _sources: Lazy<Map<File, Source>> = lazy { computeSourcesList(jpsGlobalContext) } - - fun nextRound(localContext: CompileContext) { - _sources = lazy { computeSourcesList(localContext) } - } - - private fun computeSourcesList(localContext: CompileContext): Map<File, Source> { - val result = mutableMapOf<File, Source>() - val moduleExcludes = module.excludeRootsList.urls.mapTo(java.util.HashSet(), JpsPathUtil::urlToFile) - - val compilerExcludes = JpsJavaExtensionService.getInstance() - .getOrCreateCompilerConfiguration(module.project) - .compilerExcludes - - val buildRootIndex = localContext.projectDescriptor.buildRootIndex - val roots = buildRootIndex.getTargetRoots(jpsModuleBuildTarget, localContext) - roots.forEach { rootDescriptor -> - val isCrossCompiled = rootDescriptor is KotlinIncludedModuleSourceRoot - - rootDescriptor.root.walkTopDown() - .onEnter { file -> file !in moduleExcludes } - .forEach { file -> - if (!compilerExcludes.isExcluded(file) && file.isFile && file.isKotlinSourceFile) { - result[file] = Source(file, isCrossCompiled) - } - } - - } - - return result - } - - /** - * @property isCrossCompiled sources that are cross-compiled to multiple targets - */ - class Source( - val file: File, - val isCrossCompiled: Boolean - ) - - fun isFromIncludedSourceRoot(file: File): Boolean = sources[file]?.isCrossCompiled == true - - val sourceFiles: Collection<File> - get() = sources.keys - - override fun toString() = jpsModuleBuildTarget.toString() - - /** - * Called for `ModuleChunk.representativeTarget` - */ - abstract fun compileModuleChunk( - commonArguments: CommonCompilerArguments, - dirtyFilesHolder: KotlinDirtySourceFilesHolder, - environment: JpsCompilerEnvironment - ): Boolean - - open fun registerOutputItems(outputConsumer: ModuleLevelBuilder.OutputConsumer, outputItems: List<GeneratedFile>) { - for (output in outputItems) { - outputConsumer.registerOutputFile(jpsModuleBuildTarget, output.outputFile, output.sourceFiles.map { it.path }) - } - } - - protected fun reportAndSkipCircular(environment: JpsCompilerEnvironment): Boolean { - if (chunk.targets.size > 1) { - // 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 - environment.messageCollector.report( - CompilerMessageSeverity.STRONG_WARNING, - "Circular dependencies are not supported. The following modules depend on each other: " - + chunk.presentableShortName + " " - + "Kotlin is not compiled for these modules" - ) - - return true - } - - return false - } - - open fun doAfterBuild() { - } - - open val hasCaches: Boolean = true - - abstract fun createCacheStorage(paths: BuildDataPaths): JpsIncrementalCache - - /** - * Called for `ModuleChunk.representativeTarget` - */ - open fun updateChunkMappings( - localContext: CompileContext, - chunk: ModuleChunk, - dirtyFilesHolder: KotlinDirtySourceFilesHolder, - outputItems: Map<ModuleBuildTarget, Iterable<GeneratedFile>>, - incrementalCaches: Map<KotlinModuleBuildTarget<*>, JpsIncrementalCache>, - environment: JpsCompilerEnvironment - ) { - // by default do nothing - } - - open fun updateCaches( - dirtyFilesHolder: KotlinDirtySourceFilesHolder, - jpsIncrementalCache: JpsIncrementalCache, - files: List<GeneratedFile>, - changesCollector: ChangesCollector, - environment: JpsCompilerEnvironment - ) { - val changedAndRemovedFiles = dirtyFilesHolder.getDirtyFiles(jpsModuleBuildTarget).keys + - dirtyFilesHolder.getRemovedFiles(jpsModuleBuildTarget) - val expectActualTracker = environment.services[ExpectActualTracker::class.java] as ExpectActualTrackerImpl - - jpsIncrementalCache.updateComplementaryFiles(changedAndRemovedFiles, expectActualTracker) - } - - open fun makeServices( - builder: Services.Builder, - incrementalCaches: Map<KotlinModuleBuildTarget<*>, JpsIncrementalCache>, - lookupTracker: LookupTracker, - exceptActualTracer: ExpectActualTracker, - inlineConstTracker: InlineConstTracker - ) { - with(builder) { - register(LookupTracker::class.java, lookupTracker) - register(ExpectActualTracker::class.java, exceptActualTracer) - register(CompilationCanceledStatus::class.java, object : CompilationCanceledStatus { - override fun checkCanceled() { - if (jpsGlobalContext.cancelStatus.isCanceled) throw CompilationCanceledException() - } - }) - register(InlineConstTracker::class.java, inlineConstTracker) - } - } - - /** - * Should be used only for particular target in chunk (jvm) - * - * Should not be cached since may be vary in different rounds. - */ - protected fun collectSourcesToCompile( - dirtyFilesHolder: KotlinDirtySourceFilesHolder - ) = SourcesToCompile( - sources = when { - chunk.representativeTarget.isIncrementalCompilationEnabled -> - dirtyFilesHolder.getDirtyFiles(jpsModuleBuildTarget).values - else -> sources.values - }, - removedFiles = dirtyFilesHolder.getRemovedFiles(jpsModuleBuildTarget) - ) - - inner class SourcesToCompile( - sources: Collection<KotlinModuleBuildTarget.Source>, - val removedFiles: Collection<File> - ) { - val allFiles = sources.map { it.file } - val crossCompiledFiles = sources.filter { it.isCrossCompiled }.map { it.file } - - /** - * @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) { - val logger = jpsGlobalContext.loggingManager.projectBuilderLogger - if (logger.isEnabled) { - logger.logCompiledFiles(allFiles, KotlinBuilder.KOTLIN_BUILDER_NAME, "Compiling files:") - } - } - - return hasDirtyOrRemovedSources - } - } - - abstract val buildMetaInfoFactory: BuildMetaInfoFactory<BuildMetaInfoType> - - abstract val buildMetaInfoFileName: String - - fun isVersionChanged(chunk: KotlinChunk, buildMetaInfo: BuildMetaInfo): Boolean { - val file = chunk.buildMetaInfoFile(jpsModuleBuildTarget) - if (file.notExists()) return false - - val prevBuildMetaInfo = - try { - buildMetaInfoFactory.deserializeFromString(file.readText()) ?: return false - } catch (e: Exception) { - KotlinBuilder.LOG.error("Could not deserialize build meta info", e) - return false - } - - val prevLangVersion = LanguageVersion.fromVersionString(prevBuildMetaInfo.languageVersionString) - val prevApiVersion = ApiVersion.parse(prevBuildMetaInfo.apiVersionString) - - val reasonToRebuild = when { - chunk.langVersion != prevLangVersion -> "Language version was changed ($prevLangVersion -> ${chunk.langVersion})" - chunk.apiVersion != prevApiVersion -> "Api version was changed ($prevApiVersion -> ${chunk.apiVersion})" - prevLangVersion != LanguageVersion.KOTLIN_1_0 && prevBuildMetaInfo.isEAP && !buildMetaInfo.isEAP -> { - // If EAP->Non-EAP build with IC, then rebuild all kotlin - "Last build was compiled with EAP-plugin" - } - else -> null - } - - if (reasonToRebuild != null) { - KotlinBuilder.LOG.info("$reasonToRebuild. Performing non-incremental rebuild (kotlin only)") - return true - } - - return false - } - - private fun checkRepresentativeTarget(chunk: KotlinChunk) { - check(chunk.representativeTarget == this) - } - - private fun checkRepresentativeTarget(chunk: ModuleChunk) { - check(chunk.representativeTarget() == jpsModuleBuildTarget) - } - - private fun checkRepresentativeTarget(chunk: List<KotlinModuleBuildTarget<*>>) { - check(chunk.first() == this) - } -}
\ No newline at end of file |