[Gradle] Add Configuration Cache support for native tasks
* Replace `project.provider` that captures `project` inside lambda to `lazy`. This is a workaround of this bug gradle/issues/20820 * Lift all the settings-like properties that was used during execution to configuration phase ^KT-43293
This commit is contained in:
+2
-4
@@ -6,10 +6,7 @@
|
||||
package org.jetbrains.kotlin.compilerRunner
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.Classpath
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Nested
|
||||
import org.gradle.api.tasks.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||
import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||
@@ -68,6 +65,7 @@ internal abstract class KotlinNativeToolRunner(
|
||||
@get:Input
|
||||
val konanHome: String,
|
||||
@get:InputFile
|
||||
@get:PathSensitive(PathSensitivity.ABSOLUTE)
|
||||
val konanPropertiesFile: File,
|
||||
@get:Input
|
||||
val jvmArgs: List<String>,
|
||||
|
||||
+3
@@ -62,6 +62,9 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
|
||||
it.group = BasePlugin.BUILD_GROUP
|
||||
it.description = "Links ${binary.outputKind.description} '${binary.name}' for a target '${target.name}'."
|
||||
it.enabled = binary.konanTarget.enabledOnCurrentHost
|
||||
val konanPropertiesBuildService = KonanPropertiesBuildService.registerIfAbsent(project.gradle)
|
||||
it.konanPropertiesService.set(konanPropertiesBuildService)
|
||||
it.usesService(konanPropertiesBuildService)
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.repositories.ArtifactRepository
|
||||
import org.gradle.api.file.FileTree
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinNativeCompilerRunner
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinNativeToolRunner
|
||||
import org.jetbrains.kotlin.compilerRunner.konanHome
|
||||
import org.jetbrains.kotlin.compilerRunner.konanVersion
|
||||
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
||||
@@ -169,7 +169,7 @@ class NativeCompilerDownloader(
|
||||
|
||||
fun downloadIfNeeded() {
|
||||
|
||||
val classpath = KotlinNativeCompilerRunner(project).classpath
|
||||
val classpath = KotlinNativeToolRunner.Settings(project).classpath
|
||||
if (classpath.isEmpty() || classpath.any { !it.exists() }) {
|
||||
downloadAndExtract()
|
||||
}
|
||||
|
||||
+19
-2
@@ -5,12 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.targets.native.internal
|
||||
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.jetbrains.kotlin.commonizer.CommonizerDependency
|
||||
import org.jetbrains.kotlin.commonizer.TargetedCommonizerDependency
|
||||
import org.jetbrains.kotlin.commonizer.allLeaves
|
||||
import org.jetbrains.kotlin.compilerRunner.GradleCliCommonizer
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinNativeCommonizerToolRunner
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinToolRunner
|
||||
import org.jetbrains.kotlin.compilerRunner.konanHome
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
@@ -22,9 +26,14 @@ import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropCommonizerTas
|
||||
import org.jetbrains.kotlin.gradle.tasks.CInteropProcess
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
@CacheableTask
|
||||
internal open class CInteropCommonizerTask : AbstractCInteropCommonizerTask() {
|
||||
internal open class CInteropCommonizerTask
|
||||
@Inject constructor (
|
||||
private val objectFactory: ObjectFactory,
|
||||
private val execOperations: ExecOperations,
|
||||
) : AbstractCInteropCommonizerTask() {
|
||||
|
||||
internal data class CInteropGist(
|
||||
@get:Input val identifier: CInteropIdentifier,
|
||||
@@ -42,6 +51,9 @@ internal open class CInteropCommonizerTask : AbstractCInteropCommonizerTask() {
|
||||
|
||||
override val outputDirectory: File = project.buildDir.resolve("classes/kotlin/commonizer")
|
||||
|
||||
@get:Nested
|
||||
internal val runnerSettings = KotlinNativeCommonizerToolRunner.Settings(project)
|
||||
|
||||
@get:Nested
|
||||
internal var cinterops = setOf<CInteropGist>()
|
||||
private set
|
||||
@@ -81,7 +93,12 @@ internal open class CInteropCommonizerTask : AbstractCInteropCommonizerTask() {
|
||||
outputDirectory(group).deleteRecursively()
|
||||
if (cinteropsForTarget.isEmpty()) return
|
||||
|
||||
GradleCliCommonizer(project).commonizeLibraries(
|
||||
val commonizerRunner = KotlinNativeCommonizerToolRunner(
|
||||
context = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger),
|
||||
settings = runnerSettings
|
||||
)
|
||||
|
||||
GradleCliCommonizer(commonizerRunner).commonizeLibraries(
|
||||
konanHome = project.file(project.konanHome),
|
||||
outputTargets = group.targets,
|
||||
inputLibraries = cinteropsForTarget.map { it.libraryFile.get() }.filter { it.exists() }.toSet(),
|
||||
|
||||
+12
-8
@@ -5,30 +5,34 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.targets.native.tasks
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinNativeCInteropRunner
|
||||
import org.jetbrains.kotlin.gradle.internal.isInIdeaSync
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinNativeToolRunner
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinToolRunner
|
||||
|
||||
internal fun KotlinNativeCInteropRunner.Companion.createExecutionContext(
|
||||
task: Task
|
||||
task: Task,
|
||||
isInIdeaSync: Boolean,
|
||||
runnerSettings: KotlinNativeToolRunner.Settings,
|
||||
gradleExecutionContext: KotlinToolRunner.GradleExecutionContext
|
||||
): KotlinNativeCInteropRunner.ExecutionContext {
|
||||
return if (task.project.isInIdeaSync) IdeaSyncKotlinNativeCInteropRunnerExecutionContext(task)
|
||||
else DefaultKotlinNativeCInteropRunnerExecutionContext(task.project)
|
||||
return if (isInIdeaSync) IdeaSyncKotlinNativeCInteropRunnerExecutionContext(runnerSettings, gradleExecutionContext, task)
|
||||
else DefaultKotlinNativeCInteropRunnerExecutionContext(runnerSettings, gradleExecutionContext)
|
||||
}
|
||||
|
||||
private class DefaultKotlinNativeCInteropRunnerExecutionContext(
|
||||
override val project: Project
|
||||
override val runnerSettings: KotlinNativeToolRunner.Settings,
|
||||
override val gradleExecutionContext: KotlinToolRunner.GradleExecutionContext
|
||||
) : KotlinNativeCInteropRunner.ExecutionContext {
|
||||
override fun runWithContext(action: () -> Unit) = action()
|
||||
}
|
||||
|
||||
private class IdeaSyncKotlinNativeCInteropRunnerExecutionContext(
|
||||
override val runnerSettings: KotlinNativeToolRunner.Settings,
|
||||
override val gradleExecutionContext: KotlinToolRunner.GradleExecutionContext,
|
||||
private val task: Task
|
||||
) : KotlinNativeCInteropRunner.ExecutionContext {
|
||||
|
||||
override val project: Project = task.project
|
||||
|
||||
override fun runWithContext(action: () -> Unit) {
|
||||
try {
|
||||
action()
|
||||
|
||||
+144
-78
@@ -19,8 +19,10 @@ import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.file.FileTree
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments
|
||||
import org.jetbrains.kotlin.compilerRunner.*
|
||||
@@ -30,6 +32,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
|
||||
import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated
|
||||
import org.jetbrains.kotlin.gradle.internal.isInIdeaSync
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.asValidFrameworkName
|
||||
@@ -158,12 +161,8 @@ abstract class AbstractKotlinNativeCompile<
|
||||
compilation.konanTarget
|
||||
}
|
||||
|
||||
init {
|
||||
notCompatibleWithConfigurationCache("Task $name does not support Gradle Configuration Cache. Check KT-43293 for more info")
|
||||
}
|
||||
|
||||
@get:Classpath
|
||||
override val libraries: ConfigurableFileCollection by project.provider {
|
||||
override val libraries: ConfigurableFileCollection by lazy {
|
||||
// Avoid resolving these dependencies during task graph construction when we can't build the target:
|
||||
if (konanTarget.enabledOnCurrentHost)
|
||||
objectFactory.fileCollection().from(
|
||||
@@ -173,9 +172,7 @@ abstract class AbstractKotlinNativeCompile<
|
||||
}
|
||||
|
||||
@get:Classpath
|
||||
protected val friendModule: FileCollection by project.provider {
|
||||
project.files(compilation.friendPaths)
|
||||
}
|
||||
protected val friendModule: FileCollection = project.files({ compilation.friendPaths })
|
||||
|
||||
@get:Input
|
||||
val target: String by project.provider { compilation.konanTarget.name }
|
||||
@@ -187,7 +184,7 @@ abstract class AbstractKotlinNativeCompile<
|
||||
abstract fun kotlinOptions(fn: Closure<*>)
|
||||
|
||||
@get:Input
|
||||
abstract val additionalCompilerOptions: Provider<Collection<String>>
|
||||
abstract val additionalCompilerOptions: Collection<String>
|
||||
|
||||
@get:Internal
|
||||
val languageSettings: LanguageSettings by project.provider {
|
||||
@@ -271,7 +268,7 @@ abstract class AbstractKotlinNativeCompile<
|
||||
override var allWarningsAsErrors = kotlinOptions.allWarningsAsErrors
|
||||
override var suppressWarnings = kotlinOptions.suppressWarnings
|
||||
override var verbose = kotlinOptions.verbose
|
||||
override var freeCompilerArgs = if (defaultsOnly) emptyList() else additionalCompilerOptions.get().toList()
|
||||
override var freeCompilerArgs = if (defaultsOnly) emptyList() else additionalCompilerOptions.toList()
|
||||
}
|
||||
|
||||
return buildKotlinNativeCommonArgs(
|
||||
@@ -293,11 +290,10 @@ abstract class AbstractKotlinNativeCompile<
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
internal val manifestFile: Provider<File>
|
||||
get() = project.provider {
|
||||
val inputManifestFile = project.buildDir.resolve("tmp/$name/inputManifest")
|
||||
inputManifestFile
|
||||
}
|
||||
internal val manifestFile: File by lazy {
|
||||
val inputManifestFile = project.buildDir.resolve("tmp/$name/inputManifest")
|
||||
inputManifestFile
|
||||
}
|
||||
}
|
||||
|
||||
// Remove it once actual K2NativeCompilerArguments will be available without 'kotlin.native.enabled = true' flag
|
||||
@@ -313,7 +309,8 @@ constructor(
|
||||
@Internal
|
||||
@Transient // can't be serialized for Gradle configuration cache
|
||||
final override val compilation: KotlinNativeCompilationData<*>,
|
||||
objectFactory: ObjectFactory
|
||||
private val objectFactory: ObjectFactory,
|
||||
private val execOperations: ExecOperations
|
||||
) : AbstractKotlinNativeCompile<KotlinCommonOptions, KotlinNativeCompilationData<*>, StubK2NativeCompilerArguments>(objectFactory),
|
||||
KotlinCompile<KotlinCommonOptions> {
|
||||
|
||||
@@ -327,7 +324,7 @@ constructor(
|
||||
override val debuggable = true
|
||||
|
||||
@get:Internal
|
||||
override val baseName: String by project.provider {
|
||||
override val baseName: String by lazy {
|
||||
if (compilation.isMainCompilationData())
|
||||
project.name
|
||||
else "${project.name}_${compilation.compilationPurpose}"
|
||||
@@ -337,7 +334,7 @@ constructor(
|
||||
// private val allSourceProvider = compilation.map { project.files(it.allSources).asFileTree }
|
||||
|
||||
@get:Input
|
||||
val moduleName: String by project.provider {
|
||||
val moduleName: String by lazy {
|
||||
project.klibModuleName(baseName)
|
||||
}
|
||||
|
||||
@@ -384,10 +381,14 @@ constructor(
|
||||
}
|
||||
|
||||
@get:Input
|
||||
override val additionalCompilerOptions: Provider<Collection<String>> = project.provider {
|
||||
override val additionalCompilerOptions: Collection<String> by lazy {
|
||||
kotlinOptions.freeCompilerArgs + ((languageSettings as? DefaultLanguageSettingsBuilder)?.freeCompilerArgs ?: emptyList())
|
||||
}
|
||||
|
||||
@get:Nested
|
||||
internal val runnerSettings = KotlinNativeCompilerRunner.Settings(project)
|
||||
private val isAllowCommonizer: Boolean by lazy { project.isAllowCommonizer() }
|
||||
|
||||
override fun kotlinOptions(fn: KotlinCommonOptions.() -> Unit) {
|
||||
kotlinOptions.fn()
|
||||
}
|
||||
@@ -413,7 +414,7 @@ constructor(
|
||||
|
||||
var sharedCompilationData: SharedCompilationData? = null
|
||||
if (compilation is KotlinNativeFragmentMetadataCompilationData) {
|
||||
val manifestFile: File = manifestFile.get()
|
||||
val manifestFile: File = manifestFile
|
||||
manifestFile.ensureParentDirsCreated()
|
||||
val properties = java.util.Properties()
|
||||
properties[KLIB_PROPERTY_NATIVE_TARGETS] = konanTargetsForManifest
|
||||
@@ -421,7 +422,7 @@ constructor(
|
||||
|
||||
sharedCompilationData = SharedCompilationData(
|
||||
manifestFile,
|
||||
project.isAllowCommonizer()
|
||||
isAllowCommonizer
|
||||
)
|
||||
}
|
||||
|
||||
@@ -429,7 +430,7 @@ constructor(
|
||||
override var allWarningsAsErrors = kotlinOptions.allWarningsAsErrors
|
||||
override var suppressWarnings = kotlinOptions.suppressWarnings
|
||||
override var verbose = kotlinOptions.verbose
|
||||
override var freeCompilerArgs = additionalCompilerOptions.get().toList()
|
||||
override var freeCompilerArgs = additionalCompilerOptions.toList()
|
||||
}
|
||||
|
||||
val plugins = listOfNotNull(
|
||||
@@ -455,7 +456,10 @@ constructor(
|
||||
commonSourcesTree
|
||||
)
|
||||
|
||||
KotlinNativeCompilerRunner(project).run(buildArgs)
|
||||
KotlinNativeCompilerRunner(
|
||||
settings = runnerSettings,
|
||||
executionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger)
|
||||
).run(buildArgs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,12 +472,16 @@ abstract class KotlinNativeLink
|
||||
constructor(
|
||||
@Internal
|
||||
val binary: NativeBinary,
|
||||
objectFactory: ObjectFactory
|
||||
private val objectFactory: ObjectFactory,
|
||||
private val execOperations: ExecOperations
|
||||
) : AbstractKotlinNativeCompile<KotlinCommonToolOptions, KotlinNativeCompilation, StubK2NativeCompilerArguments>(objectFactory) {
|
||||
@get:Internal
|
||||
final override val compilation: KotlinNativeCompilation
|
||||
get() = binary.compilation
|
||||
|
||||
@get:Nested
|
||||
internal val runnerSettings = KotlinNativeCompilerRunner.Settings(project)
|
||||
|
||||
init {
|
||||
dependsOn(project.provider { compilation.compileKotlinTaskProvider })
|
||||
// Frameworks actively uses symlinks.
|
||||
@@ -502,7 +510,7 @@ constructor(
|
||||
@Input get() = binary.baseName
|
||||
|
||||
@get:Input
|
||||
protected val konanCacheKind: NativeCacheKind by project.provider {
|
||||
protected val konanCacheKind: NativeCacheKind by lazy {
|
||||
project.getKonanCacheKind(konanTarget)
|
||||
}
|
||||
|
||||
@@ -515,7 +523,7 @@ constructor(
|
||||
|
||||
// We propagate compilation free args to the link task for now (see KT-33717).
|
||||
@get:Input
|
||||
override val additionalCompilerOptions: Provider<Collection<String>> = project.provider {
|
||||
override val additionalCompilerOptions: Collection<String> by lazy {
|
||||
kotlinOptions.freeCompilerArgs +
|
||||
compilation.kotlinOptions.freeCompilerArgs +
|
||||
((languageSettings as? DefaultLanguageSettingsBuilder)?.freeCompilerArgs ?: emptyList()) +
|
||||
@@ -542,17 +550,17 @@ constructor(
|
||||
val linkerOpts: List<String>
|
||||
@Input get() = binary.linkerOpts
|
||||
|
||||
val binaryOptions: Map<String, String>
|
||||
@Input get() = PropertiesProvider(project).nativeBinaryOptions + binary.binaryOptions
|
||||
@get:Input
|
||||
val binaryOptions: Map<String, String> by lazy { PropertiesProvider(project).nativeBinaryOptions + binary.binaryOptions }
|
||||
|
||||
val processTests: Boolean
|
||||
@Input get() = binary is TestExecutable
|
||||
|
||||
@get:Classpath
|
||||
val exportLibraries: FileCollection by project.provider {
|
||||
val exportLibraries: FileCollection by lazy {
|
||||
binary.let {
|
||||
if (it is AbstractNativeLibrary) {
|
||||
project.configurations.getByName(it.exportConfigurationName)
|
||||
project.files(project.configurations.getByName(it.exportConfigurationName))
|
||||
} else {
|
||||
objectFactory.fileCollection()
|
||||
}
|
||||
@@ -570,8 +578,22 @@ constructor(
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
val apiFilesProvider = project.provider {
|
||||
project.configurations.getByName(compilation.apiConfigurationName).files.filterKlibsPassedToCompiler()
|
||||
val apiFiles by lazy {
|
||||
project.files(project.configurations.getByName(compilation.apiConfigurationName)).files.filterKlibsPassedToCompiler()
|
||||
}
|
||||
|
||||
private val localKotlinOptions get() =
|
||||
object : KotlinCommonToolOptions {
|
||||
override var allWarningsAsErrors = kotlinOptions.allWarningsAsErrors
|
||||
override var suppressWarnings = kotlinOptions.suppressWarnings
|
||||
override var verbose = kotlinOptions.verbose
|
||||
override var freeCompilerArgs = additionalCompilerOptions.toList()
|
||||
}
|
||||
|
||||
private val externalDependenciesArgs by lazy { ExternalDependenciesBuilder(project, compilation).buildCompilerArgs() }
|
||||
|
||||
private val cacheBuilderSettings by lazy {
|
||||
CacheBuilder.Settings(project, binary, konanTarget, localKotlinOptions, externalDependenciesArgs)
|
||||
}
|
||||
|
||||
override fun createCompilerArgs(): StubK2NativeCompilerArguments = StubK2NativeCompilerArguments()
|
||||
@@ -584,7 +606,6 @@ constructor(
|
||||
|
||||
private fun validatedExportedLibraries() {
|
||||
val exportConfiguration = exportLibraries as? Configuration ?: return
|
||||
val apiFiles = apiFilesProvider.get()
|
||||
|
||||
val failed = mutableSetOf<Dependency>()
|
||||
exportConfiguration.allDependencies.forEach {
|
||||
@@ -613,6 +634,14 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
internal abstract val konanPropertiesService: Property<KonanPropertiesBuildService>
|
||||
|
||||
private val compileDependencyFiles = FilesWithResolvedDependencyGraph(
|
||||
project,
|
||||
project.configurations.getByName(compilation.compileDependencyConfigurationName)
|
||||
)
|
||||
|
||||
@TaskAction
|
||||
fun compile() {
|
||||
validatedExportedLibraries()
|
||||
@@ -625,15 +654,12 @@ constructor(
|
||||
kotlinPluginData?.orNull?.let { CompilerPluginData(it.classpath, it.options) }
|
||||
)
|
||||
|
||||
val localKotlinOptions = object : KotlinCommonToolOptions {
|
||||
override var allWarningsAsErrors = kotlinOptions.allWarningsAsErrors
|
||||
override var suppressWarnings = kotlinOptions.suppressWarnings
|
||||
override var verbose = kotlinOptions.verbose
|
||||
override var freeCompilerArgs = additionalCompilerOptions.get().toList()
|
||||
}
|
||||
|
||||
val externalDependenciesArgs = ExternalDependenciesBuilder(project, compilation).buildCompilerArgs()
|
||||
val cacheArgs = CacheBuilder(project, binary, konanTarget, localKotlinOptions, externalDependenciesArgs).buildCompilerArgs()
|
||||
val executionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger)
|
||||
val cacheArgs = CacheBuilder(
|
||||
executionContext = executionContext,
|
||||
settings = cacheBuilderSettings,
|
||||
konanPropertiesService = konanPropertiesService.get()
|
||||
).buildCompilerArgs(compileDependencyFiles)
|
||||
|
||||
val buildArgs = buildKotlinNativeBinaryLinkerArgs(
|
||||
output,
|
||||
@@ -657,7 +683,10 @@ constructor(
|
||||
externalDependenciesArgs + cacheArgs
|
||||
)
|
||||
|
||||
KotlinNativeCompilerRunner(project).run(buildArgs)
|
||||
KotlinNativeCompilerRunner(
|
||||
settings = runnerSettings,
|
||||
executionContext = executionContext
|
||||
).run(buildArgs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -838,19 +867,53 @@ private class ExternalDependenciesBuilder(
|
||||
}
|
||||
|
||||
internal class CacheBuilder(
|
||||
val project: Project,
|
||||
val binary: NativeBinary,
|
||||
val konanTarget: KonanTarget,
|
||||
val kotlinOptions: KotlinCommonToolOptions,
|
||||
val externalDependenciesArgs: List<String>
|
||||
private val executionContext: KotlinToolRunner.GradleExecutionContext,
|
||||
private val settings: Settings,
|
||||
private val konanPropertiesService: KonanPropertiesBuildService,
|
||||
) {
|
||||
class Settings(
|
||||
val runnerSettings: KotlinNativeCompilerRunner.Settings,
|
||||
val konanCacheKind: NativeCacheKind,
|
||||
val libraries: FileCollection,
|
||||
val rootCacheDirectory: File,
|
||||
val gradleUserHomeDir: File,
|
||||
val binary: NativeBinary,
|
||||
val konanTarget: KonanTarget,
|
||||
val kotlinOptions: KotlinCommonToolOptions,
|
||||
val externalDependenciesArgs: List<String>
|
||||
) {
|
||||
companion object {
|
||||
operator fun invoke(
|
||||
project: Project,
|
||||
binary: NativeBinary,
|
||||
konanTarget: KonanTarget,
|
||||
kotlinOptions: KotlinCommonToolOptions,
|
||||
externalDependenciesArgs: List<String>
|
||||
): Settings {
|
||||
val konanCacheKind = project.getKonanCacheKind(konanTarget)
|
||||
return Settings(
|
||||
runnerSettings = KotlinNativeCompilerRunner.Settings(project),
|
||||
konanCacheKind = konanCacheKind,
|
||||
libraries = binary.compilation.compileDependencyFiles.filterOutPublishableInteropLibs(project),
|
||||
rootCacheDirectory = getRootCacheDirectory(File(project.konanHome), konanTarget, binary.debuggable, konanCacheKind),
|
||||
gradleUserHomeDir = project.gradle.gradleUserHomeDir,
|
||||
binary, konanTarget, kotlinOptions, externalDependenciesArgs
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val nativeSingleFileResolveStrategy: SingleFileKlibResolveStrategy
|
||||
get() = CompilerSingleFileKlibResolveAllowingIrProvidersStrategy(
|
||||
listOf(KLIB_INTEROP_IR_PROVIDER_IDENTIFIER)
|
||||
)
|
||||
private val compilation: KotlinNativeCompilation
|
||||
get() = binary.compilation
|
||||
|
||||
private val binary: NativeBinary
|
||||
get() = settings.binary
|
||||
|
||||
private val konanTarget: KonanTarget
|
||||
get() = settings.konanTarget
|
||||
|
||||
private val optimized: Boolean
|
||||
get() = binary.optimized
|
||||
@@ -858,25 +921,21 @@ internal class CacheBuilder(
|
||||
private val debuggable: Boolean
|
||||
get() = binary.debuggable
|
||||
|
||||
private val konanPropertiesService: KonanPropertiesBuildService
|
||||
get() = KonanPropertiesBuildService.registerIfAbsent(project.gradle).get()
|
||||
|
||||
private val konanCacheKind: NativeCacheKind
|
||||
get() = project.getKonanCacheKind(konanTarget)
|
||||
get() = settings.konanCacheKind
|
||||
|
||||
// Inputs and outputs
|
||||
private val libraries: FileCollection
|
||||
get() = compilation.compileDependencyFiles.filterOutPublishableInteropLibs(project)
|
||||
get() = settings.libraries
|
||||
|
||||
private val target: String
|
||||
get() = konanTarget.name
|
||||
|
||||
private val rootCacheDirectory by project.provider {
|
||||
getRootCacheDirectory(File(project.konanHome), konanTarget, debuggable, konanCacheKind)
|
||||
}
|
||||
private val rootCacheDirectory: File
|
||||
get() = settings.rootCacheDirectory
|
||||
|
||||
private val partialLinkage: Boolean
|
||||
get() = PARTIAL_LINKAGE in kotlinOptions.freeCompilerArgs
|
||||
get() = PARTIAL_LINKAGE in settings.kotlinOptions.freeCompilerArgs
|
||||
|
||||
private fun getCacheDirectory(dependency: ResolvedDependency): File = getCacheDirectory(
|
||||
rootCacheDirectory = rootCacheDirectory,
|
||||
@@ -886,7 +945,7 @@ internal class CacheBuilder(
|
||||
)
|
||||
|
||||
private fun needCache(libraryPath: String) =
|
||||
libraryPath.startsWith(project.gradle.gradleUserHomeDir.absolutePath) && libraryPath.endsWith(".klib")
|
||||
libraryPath.startsWith(settings.gradleUserHomeDir.absolutePath) && libraryPath.endsWith(".klib")
|
||||
|
||||
private fun ensureDependencyPrecached(dependency: ResolvedDependency, visitedDependencies: MutableSet<ResolvedDependency>) {
|
||||
if (dependency in visitedDependencies)
|
||||
@@ -911,7 +970,7 @@ internal class CacheBuilder(
|
||||
.map {
|
||||
resolveSingleFileKlib(
|
||||
KFile(it.file.absolutePath),
|
||||
logger = GradleLoggerAdapter(project.logger),
|
||||
logger = GradleLoggerAdapter(executionContext.logger),
|
||||
strategy = nativeSingleFileResolveStrategy
|
||||
)
|
||||
}
|
||||
@@ -939,14 +998,14 @@ internal class CacheBuilder(
|
||||
for (library in sortedLibraries) {
|
||||
if (File(cacheDirectory, library.uniqueName.cachedName).listFilesOrEmpty().isNotEmpty())
|
||||
continue
|
||||
project.logger.info("Compiling ${library.uniqueName} to cache")
|
||||
executionContext.logger.info("Compiling ${library.uniqueName} to cache")
|
||||
val args = mutableListOf(
|
||||
"-p", konanCacheKind.produce!!,
|
||||
"-target", target
|
||||
)
|
||||
if (debuggable) args += "-g"
|
||||
args += konanPropertiesService.additionalCacheFlags(konanTarget)
|
||||
args += externalDependenciesArgs
|
||||
args += settings.externalDependenciesArgs
|
||||
if (partialLinkage) args += PARTIAL_LINKAGE
|
||||
args += "-Xadd-cache=${library.libraryFile.absolutePath}"
|
||||
args += "-Xcache-directory=${cacheDirectory.absolutePath}"
|
||||
@@ -969,7 +1028,7 @@ internal class CacheBuilder(
|
||||
args += "-l"
|
||||
args += it.libraryFile.absolutePath
|
||||
}
|
||||
KotlinNativeCompilerRunner(project).run(args)
|
||||
KotlinNativeCompilerRunner(settings.runnerSettings, executionContext).run(args)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -989,12 +1048,12 @@ internal class CacheBuilder(
|
||||
return
|
||||
val unresolvedDependencies = resolveSingleFileKlib(
|
||||
KFile(platformLib.absolutePath),
|
||||
logger = GradleLoggerAdapter(project.logger),
|
||||
logger = GradleLoggerAdapter(executionContext.logger),
|
||||
strategy = nativeSingleFileResolveStrategy
|
||||
).unresolvedDependencies
|
||||
for (dependency in unresolvedDependencies)
|
||||
ensureCompilerProvidedLibPrecached(dependency.path, platformLibs, visitedLibs)
|
||||
project.logger.info("Compiling $platformLibName (${visitedLibs.size}/${platformLibs.size}) to cache")
|
||||
executionContext.logger.info("Compiling $platformLibName (${visitedLibs.size}/${platformLibs.size}) to cache")
|
||||
val args = mutableListOf(
|
||||
"-p", konanCacheKind.produce!!,
|
||||
"-target", target
|
||||
@@ -1010,11 +1069,11 @@ internal class CacheBuilder(
|
||||
}
|
||||
args += "-Xadd-cache=${platformLib.absolutePath}"
|
||||
args += "-Xcache-directory=${rootCacheDirectory.absolutePath}"
|
||||
KotlinNativeCompilerRunner(project).run(args)
|
||||
KotlinNativeCompilerRunner(settings.runnerSettings, executionContext).run(args)
|
||||
}
|
||||
|
||||
private fun ensureCompilerProvidedLibsPrecached() {
|
||||
val distribution = Distribution(project.konanHome)
|
||||
val distribution = Distribution(settings.runnerSettings.parent.konanHome)
|
||||
val platformLibs = mutableListOf<File>().apply {
|
||||
this += File(distribution.stdlib)
|
||||
this += File(distribution.platformLibs(konanTarget)).listFiles().orEmpty()
|
||||
@@ -1024,15 +1083,14 @@ internal class CacheBuilder(
|
||||
ensureCompilerProvidedLibPrecached(platformLibName, platformLibs, visitedLibs)
|
||||
}
|
||||
|
||||
fun buildCompilerArgs(): List<String> = mutableListOf<String>().apply {
|
||||
fun buildCompilerArgs(compileDependencyFiles: FilesWithResolvedDependencyGraph): List<String> = mutableListOf<String>().apply {
|
||||
if (konanCacheKind != NativeCacheKind.NONE && !optimized && konanPropertiesService.cacheWorksFor(konanTarget)) {
|
||||
rootCacheDirectory.mkdirs()
|
||||
ensureCompilerProvidedLibsPrecached()
|
||||
add("-Xcache-directory=${rootCacheDirectory.absolutePath}")
|
||||
val visitedDependencies = mutableSetOf<ResolvedDependency>()
|
||||
val allCacheDirectories = mutableSetOf<String>()
|
||||
val compileDependencyConfiguration = project.configurations.getByName(compilation.compileDependencyConfigurationName)
|
||||
for (root in compileDependencyConfiguration.resolvedConfiguration.firstLevelModuleDependencies) {
|
||||
for (root in compileDependencyFiles.graphRoot.firstLevelModuleDependencies) {
|
||||
ensureDependencyPrecached(root, visitedDependencies)
|
||||
for (dependency in listOf(root) + getAllDependencies(root)) {
|
||||
val cacheDirectory = getCacheDirectory(dependency)
|
||||
@@ -1062,7 +1120,12 @@ internal class CacheBuilder(
|
||||
}
|
||||
|
||||
@CacheableTask
|
||||
open class CInteropProcess @Inject constructor(@get:Internal val settings: DefaultCInteropSettings) : DefaultTask() {
|
||||
open class CInteropProcess
|
||||
@Inject constructor(
|
||||
@get:Internal val settings: DefaultCInteropSettings,
|
||||
private val objectFactory: ObjectFactory,
|
||||
private val execOperations: ExecOperations
|
||||
) : DefaultTask() {
|
||||
|
||||
@Internal // Taken into account in the outputFileProvider property
|
||||
lateinit var destinationDir: Provider<File>
|
||||
@@ -1093,9 +1156,8 @@ open class CInteropProcess @Inject constructor(@get:Internal val settings: Defau
|
||||
val outputFile: File
|
||||
get() = outputFileProvider.get()
|
||||
|
||||
init {
|
||||
notCompatibleWithConfigurationCache("Task $name does not support Gradle Configuration Cache. Check KT-43293 for more info")
|
||||
}
|
||||
@get:Nested
|
||||
internal val runnerSettings = KotlinNativeToolRunner.Settings(project)
|
||||
|
||||
// Inputs and outputs.
|
||||
|
||||
@@ -1137,8 +1199,7 @@ open class CInteropProcess @Inject constructor(@get:Internal val settings: Defau
|
||||
val extraOpts: List<String>
|
||||
@Input get() = settings.extraOpts
|
||||
|
||||
val kotlinNativeVersion: String
|
||||
@Input get() = project.konanVersion.toString()
|
||||
private val isInIdeaSync = project.isInIdeaSync
|
||||
|
||||
// Task action.
|
||||
@TaskAction
|
||||
@@ -1175,6 +1236,11 @@ open class CInteropProcess @Inject constructor(@get:Internal val settings: Defau
|
||||
}
|
||||
|
||||
outputFile.parentFile.mkdirs()
|
||||
KotlinNativeCInteropRunner.createExecutionContext(this).run(args)
|
||||
KotlinNativeCInteropRunner.createExecutionContext(
|
||||
task = this,
|
||||
isInIdeaSync = isInIdeaSync,
|
||||
runnerSettings = runnerSettings,
|
||||
gradleExecutionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger)
|
||||
).run(args)
|
||||
}
|
||||
}
|
||||
|
||||
+16
-7
@@ -5,18 +5,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.targets.native.tasks.artifact
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinNativeCompilerRunner
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinToolRunner
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions
|
||||
import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
|
||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.buildKotlinNativeBinaryLinkerArgs
|
||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.util.visibleName
|
||||
@@ -25,7 +26,9 @@ import javax.inject.Inject
|
||||
|
||||
open class KotlinNativeLinkArtifactTask @Inject constructor(
|
||||
@get:Input val konanTarget: KonanTarget,
|
||||
@get:Input val outputKind: CompilerOutputKind
|
||||
@get:Input val outputKind: CompilerOutputKind,
|
||||
private val objectFactory: ObjectFactory,
|
||||
private val execOperations: ExecOperations
|
||||
) : DefaultTask() {
|
||||
|
||||
@get:Input
|
||||
@@ -74,7 +77,7 @@ open class KotlinNativeLinkArtifactTask @Inject constructor(
|
||||
var librariesConfiguration: String? = null
|
||||
|
||||
@get:Classpath
|
||||
val libraries: FileCollection by project.provider {
|
||||
val libraries: FileCollection by lazy {
|
||||
librariesConfiguration?.let {
|
||||
project.configurations.getByName(it)
|
||||
} ?: project.objects.fileCollection()
|
||||
@@ -84,7 +87,7 @@ open class KotlinNativeLinkArtifactTask @Inject constructor(
|
||||
var exportLibrariesConfiguration: String? = null
|
||||
|
||||
@get:Classpath
|
||||
val exportLibraries: FileCollection by project.provider {
|
||||
val exportLibraries: FileCollection by lazy {
|
||||
exportLibrariesConfiguration?.let {
|
||||
project.configurations.getByName(it)
|
||||
} ?: project.objects.fileCollection()
|
||||
@@ -94,7 +97,7 @@ open class KotlinNativeLinkArtifactTask @Inject constructor(
|
||||
var includeLibrariesConfiguration: String? = null
|
||||
|
||||
@get:Classpath
|
||||
val includeLibraries: FileCollection by project.provider {
|
||||
val includeLibraries: FileCollection by lazy {
|
||||
includeLibrariesConfiguration?.let {
|
||||
project.configurations.getByName(it)
|
||||
} ?: project.objects.fileCollection()
|
||||
@@ -145,6 +148,9 @@ open class KotlinNativeLinkArtifactTask @Inject constructor(
|
||||
return destinationDir.resolve(outFileName)
|
||||
}
|
||||
|
||||
@get:Nested
|
||||
internal val runnerSettings = KotlinNativeCompilerRunner.Settings(project)
|
||||
|
||||
@TaskAction
|
||||
fun link() {
|
||||
val outFile = outputFile
|
||||
@@ -176,6 +182,9 @@ open class KotlinNativeLinkArtifactTask @Inject constructor(
|
||||
additionalOptions = emptyList()//todo support org.jetbrains.kotlin.gradle.tasks.CacheBuilder and org.jetbrains.kotlin.gradle.tasks.ExternalDependenciesBuilder
|
||||
)
|
||||
|
||||
KotlinNativeCompilerRunner(project).run(buildArgs)
|
||||
KotlinNativeCompilerRunner(
|
||||
settings = runnerSettings,
|
||||
executionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger)
|
||||
).run(buildArgs)
|
||||
}
|
||||
}
|
||||
+32
@@ -5,6 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.utils
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ResolvedConfiguration
|
||||
import org.gradle.api.artifacts.ResolvedDependency
|
||||
import org.gradle.api.artifacts.result.ResolvedComponentResult
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.provider.Provider
|
||||
|
||||
const val COMPILE_ONLY = "compileOnly"
|
||||
const val COMPILE = "compile"
|
||||
const val IMPLEMENTATION = "implementation"
|
||||
@@ -12,3 +20,27 @@ const val API = "api"
|
||||
const val RUNTIME_ONLY = "runtimeOnly"
|
||||
const val RUNTIME = "runtime"
|
||||
internal const val INTRANSITIVE = "intransitive"
|
||||
|
||||
/**
|
||||
* Gradle Configuration Cache-friendly holder of resolved Configuration
|
||||
*/
|
||||
class FilesWithResolvedDependencyGraph
|
||||
private constructor (
|
||||
val files: FileCollection,
|
||||
val graphRootProvider: Provider<ResolvedComponentResult>
|
||||
) {
|
||||
val graphRoot get() = graphRootProvider.get()
|
||||
|
||||
companion object {
|
||||
operator fun invoke(project: Project, configuration: Configuration) = FilesWithResolvedDependencyGraph(
|
||||
files = project.files(configuration),
|
||||
graphRootProvider = configuration.incoming.resolutionResult.let { rr -> project.provider { rr.root } }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration Cache-friendly alternative of [ResolvedConfiguration.getFirstLevelModuleDependencies]
|
||||
*/
|
||||
internal val ResolvedComponentResult.firstLevelModuleDependencies: Set<ResolvedDependency> get() =
|
||||
dependencies.filterIsInstance<ResolvedDependency>().toSet()
|
||||
Reference in New Issue
Block a user