[K/N][gradle] Supported friend modules for two stage compilation

Fixes https://youtrack.jetbrains.com/issue/KT-49248
This commit is contained in:
Igor Chevdar
2021-11-09 09:09:28 +05:00
parent e7680ddbff
commit b474b570a4
6 changed files with 63 additions and 74 deletions
@@ -5,6 +5,7 @@ import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMo
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.storage.StorageManager
@@ -29,23 +30,25 @@ interface KlibResolvedModuleDescriptorsFactory {
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
languageVersionSettings: LanguageVersionSettings,
customAction: ((KotlinLibrary, ModuleDescriptorImpl) -> Unit)? = null,
friendModuleFiles: Set<File>,
includedLibraryFiles: Set<File>,
additionalDependencyModules: Iterable<ModuleDescriptorImpl>
): KotlinResolvedModuleDescriptors
}
class KotlinResolvedModuleDescriptors(
/**
* The list of modules each representing an individual Kotlin/Native library. All modules
* in this list have properly installed dependencies, i.e. module has all necessary dependencies
* on other modules plus a dependency on the [forwardDeclarationsModule].
*/
val resolvedDescriptors: List<ModuleDescriptorImpl>,
/**
* The list of modules each representing an individual Kotlin/Native library. All modules
* in this list have properly installed dependencies, i.e. module has all necessary dependencies
* on other modules plus a dependency on the [forwardDeclarationsModule].
*/
val resolvedDescriptors: List<ModuleDescriptorImpl>,
/**
* This is a module which "contains" forward declarations.
* Note: this module should be unique per compilation and should always be the last dependency of any module.
*/
val forwardDeclarationsModule: ModuleDescriptorImpl,
/**
* This is a module which "contains" forward declarations.
* Note: this module should be unique per compilation and should always be the last dependency of any module.
*/
val forwardDeclarationsModule: ModuleDescriptorImpl
val friendModules: Set<ModuleDescriptorImpl>
)
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.SyntheticModulesOrigin
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.util.profile
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.PackageAccessHandler
@@ -37,14 +38,19 @@ class KlibResolvedModuleDescriptorsFactoryImpl(
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
languageVersionSettings: LanguageVersionSettings,
customAction: ((KotlinLibrary, ModuleDescriptorImpl) -> Unit)?,
friendModuleFiles: Set<File>,
includedLibraryFiles: Set<File>,
additionalDependencyModules: Iterable<ModuleDescriptorImpl>
): KotlinResolvedModuleDescriptors {
val moduleDescriptors = mutableListOf<ModuleDescriptorImpl>()
@Suppress("NAME_SHADOWING")
var builtIns = builtIns
val friendModuleDescriptors = mutableSetOf<ModuleDescriptorImpl>()
val includedLibraryDescriptors = mutableSetOf<ModuleDescriptorImpl>()
// Build module descriptors.
resolvedLibraries.forEach { library, packageAccessHandler ->
profile("Loading ${library.libraryName}") {
@@ -56,7 +62,10 @@ class KlibResolvedModuleDescriptorsFactoryImpl(
builtIns = moduleDescriptor.builtIns
moduleDescriptors.add(moduleDescriptor)
customAction?.invoke(library, moduleDescriptor)
if (friendModuleFiles.contains(library.libraryFile))
friendModuleDescriptors.add(moduleDescriptor)
if (includedLibraryFiles.contains(library.libraryFile))
includedLibraryDescriptors.add(moduleDescriptor)
}
}
@@ -64,14 +73,17 @@ class KlibResolvedModuleDescriptorsFactoryImpl(
// Set inter-dependencies between module descriptors, add forwarding declarations module.
for (module in moduleDescriptors) {
// Yes, just to all of them.
val friends = additionalDependencyModules.toMutableSet()
if (module in includedLibraryDescriptors)
friends.addAll(friendModuleDescriptors)
module.setDependencies(
// Yes, just to all of them.
moduleDescriptors + additionalDependencyModules + forwardDeclarationsModule,
additionalDependencyModules.toSet()
friends
)
}
return KotlinResolvedModuleDescriptors(moduleDescriptors, forwardDeclarationsModule)
return KotlinResolvedModuleDescriptors(moduleDescriptors, forwardDeclarationsModule, friendModuleDescriptors)
}
fun createForwardDeclarationsModule(
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.linkage.IrDeserializer
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.library.uniqueName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
@@ -94,7 +95,14 @@ internal fun Context.psiToIr(
get() = generatorContext.irBuiltIns
}
val friendModules = emptyMap<String, Collection<String>>() // TODO: provide friend modules
val friendModules = config.resolvedLibraries.getFullList()
.filter { it.libraryFile in config.friendModuleFiles }
.map { it.uniqueName }
val friendModulesMap = (
listOf(moduleDescriptor.name.asStringStripSpecialMarkers()) +
config.resolve.includedLibraries.map { it.uniqueName }
).associateWith { friendModules }
KonanIrLinker(
moduleDescriptor,
@@ -102,7 +110,7 @@ internal fun Context.psiToIr(
messageLogger,
generatorContext.irBuiltIns,
symbolTable,
friendModules,
friendModulesMap,
forwardDeclarationsModuleDescriptor,
stubGenerator,
irProviderForCEnumsAndCStructs,
@@ -6,60 +6,49 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.context.MutableModuleContextImpl
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.CurrentKlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.util.KlibMetadataFactories
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.NativeTypeTransformer
import org.jetbrains.kotlin.library.metadata.NullFlexibleTypeDeserializer
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.extensions.AnalysisHandlerExtension
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.serialization.konan.KotlinResolvedModuleDescriptors
import org.jetbrains.kotlin.storage.StorageManager
internal object TopDownAnalyzerFacadeForKonan {
private val nativeFactories = KlibMetadataFactories(::KonanBuiltIns, NullFlexibleTypeDeserializer, NativeTypeTransformer())
fun analyzeFiles(files: Collection<KtFile>, context: Context): AnalysisResult {
val config = context.config
val moduleName = Name.special("<${config.moduleId}>")
val projectContext = ProjectContext(config.project, "TopDownAnalyzer for Konan")
val module = NativeFactories.DefaultDescriptorFactory.createDescriptorAndNewBuiltIns(
val module = nativeFactories.DefaultDescriptorFactory.createDescriptorAndNewBuiltIns(
moduleName, projectContext.storageManager, origin = CurrentKlibModuleOrigin)
val moduleContext = MutableModuleContextImpl(module, projectContext)
val resolvedDependencies = ResolvedDependencies(
config.resolvedLibraries,
projectContext.storageManager,
module.builtIns,
config.languageVersionSettings,
config.friendModuleFiles,
module
)
val resolvedModuleDescriptors = nativeFactories.DefaultResolvedDescriptorsFactory.createResolved(
config.resolvedLibraries, projectContext.storageManager, module.builtIns, config.languageVersionSettings,
config.friendModuleFiles, config.resolve.includedLibraries.map { it.libraryFile }.toSet(), listOf(module))
val additionalPackages = mutableListOf<PackageFragmentProvider>()
if (!module.isNativeStdlib()) {
val dependencies = listOf(module) + resolvedDependencies.moduleDescriptors.resolvedDescriptors + resolvedDependencies.moduleDescriptors.forwardDeclarationsModule
module.setDependencies(dependencies, resolvedDependencies.friends)
val dependencies = listOf(module) + resolvedModuleDescriptors.resolvedDescriptors + resolvedModuleDescriptors.forwardDeclarationsModule
module.setDependencies(dependencies, resolvedModuleDescriptors.friendModules)
} else {
assert (resolvedDependencies.moduleDescriptors.resolvedDescriptors.isEmpty())
assert(resolvedModuleDescriptors.resolvedDescriptors.isEmpty())
moduleContext.setDependencies(module)
// [K][Suspend]FunctionN belong to stdlib.
additionalPackages += functionInterfacePackageFragmentProvider(projectContext.storageManager, module)
@@ -122,34 +111,3 @@ internal object TopDownAnalyzerFacadeForKonan {
}
}
}
private class ResolvedDependencies(
resolvedLibraries: KotlinLibraryResolveResult,
storageManager: StorageManager,
builtIns: KotlinBuiltIns,
specifics: LanguageVersionSettings,
friendModuleFiles: Set<File>,
currentModuleDescriptor: ModuleDescriptorImpl
) {
val moduleDescriptors: KotlinResolvedModuleDescriptors
val friends: Set<ModuleDescriptorImpl>
init {
val collectedFriends = mutableListOf<ModuleDescriptorImpl>()
val customAction: (KotlinLibrary, ModuleDescriptorImpl) -> Unit = { library, moduleDescriptor ->
if (friendModuleFiles.contains(library.libraryFile)) {
collectedFriends.add(moduleDescriptor)
}
}
this.moduleDescriptors = NativeFactories.DefaultResolvedDescriptorsFactory.createResolved(
resolvedLibraries, storageManager, builtIns, specifics, customAction, listOf(currentModuleDescriptor))
this.friends = collectedFriends.toSet()
}
}
val NativeFactories = KlibMetadataFactories(::KonanBuiltIns, NullFlexibleTypeDeserializer, NativeTypeTransformer())
@@ -77,6 +77,7 @@ internal fun buildKotlinNativeBinaryLinkerArgs(
target: KonanTarget,
outputKind: CompilerOutputKind,
libraries: List<File>,
friendModule: FileCollection,
languageSettings: LanguageSettings,
enableEndorsedLibs: Boolean,
@@ -111,6 +112,11 @@ internal fun buildKotlinNativeBinaryLinkerArgs(
exportLibraries.forEach { add("-Xexport-library=${it.absolutePath}") }
includeLibraries.forEach { add("-Xinclude=${it.absolutePath}") }
val friends = friendModule.files
if (friends.isNotEmpty()) {
addArg("-friend-modules", friends.joinToString(File.pathSeparator) { it.absolutePath })
}
}
private fun buildKotlinNativeMainArgs(
@@ -168,6 +168,11 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : Kotl
else objects.fileCollection()
}
@get:Classpath
protected val friendModule: FileCollection by project.provider {
project.files(compilation.friendPaths)
}
@Deprecated("For native tasks use 'libraries' instead", ReplaceWith("libraries"))
override fun getClasspath(): FileCollection = libraries
override fun setClasspath(configuration: FileCollection?) {
@@ -354,10 +359,6 @@ constructor(
private val commonSourcesTree: FileTree
get() = commonSources.asFileTree
private val friendModule: FileCollection by project.provider {
project.files(compilation.friendPaths)
}
// endregion.
// region Language settings imported from a SourceSet.
@@ -634,6 +635,7 @@ constructor(
konanTarget,
outputKind,
libraries.files.filterKlibsPassedToCompiler(),
friendModule,
languageSettings,
enableEndorsedLibs,
localKotlinOptions,