All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeLink.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("PackageDirectoryMismatch") // Old package for compatibility
package org.jetbrains.kotlin.gradle.tasks
import groovy.lang.Closure
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.artifacts.result.ResolvedDependencyResult
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileCollection
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.build.report.metrics.BuildMetricsReporter
import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric
import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime
import org.jetbrains.kotlin.cli.common.arguments.K2NativeCompilerArguments
import org.jetbrains.kotlin.compilerRunner.*
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.CreateCompilerArgumentsContext
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.CreateCompilerArgumentsContext.Companion.create
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.cocoapods.asValidFrameworkName
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter
import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService
import org.jetbrains.kotlin.gradle.targets.native.UsesKonanPropertiesBuildService
import org.jetbrains.kotlin.gradle.targets.native.tasks.CompilerPluginData
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.project.model.LanguageSettings
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
import java.io.File
import javax.inject.Inject
/**
* A task producing a final binary from a compilation.
*/
@CacheableTask
abstract class KotlinNativeLink
@Inject
constructor(
@Internal
@Transient // This property can't be accessed in the execution phase
val binary: NativeBinary,
private val objectFactory: ObjectFactory,
private val execOperations: ExecOperations,
) : AbstractKotlinCompileTool(objectFactory),
UsesKonanPropertiesBuildService,
UsesBuildMetricsService,
KotlinToolTask {
@Deprecated("Visibility will be lifted to private in the future releases")
@get:Internal
val compilation: KotlinNativeCompilation
get() = binary.compilation
@get:Internal
val konanDataDir: Provider = project.provider { project.konanDataDir }
@get:Internal
val konanHome: Provider = project.provider { project.konanHome }
private val runnerSettings = KotlinNativeCompilerRunner.Settings.of(konanHome.get(), konanDataDir.getOrNull(), project)
final override val toolOptions: KotlinCommonCompilerToolOptions = objectFactory
.newInstance()
init {
@Suppress("DEPRECATION")
this.dependsOn(compilation.compileTaskProvider)
// Frameworks actively uses symlinks.
// Gradle build cache transforms symlinks into regular files https://guides.gradle.org/using-build-cache/#symbolic_links
outputs.cacheIf { outputKind != CompilerOutputKind.FRAMEWORK }
@Suppress("DEPRECATION")
this.setSource(compilation.compileTaskProvider.map { it.outputFile })
includes.clear() // we need to include non '.kt' or '.kts' files
disallowSourceChanges()
}
override val destinationDirectory: DirectoryProperty = binary.outputDirectoryProperty
@get:Classpath
override val libraries: ConfigurableFileCollection = objectFactory.fileCollection().from(
{
// Avoid resolving these dependencies during task graph construction when we can't build the target:
@Suppress("DEPRECATION")
if (konanTarget.enabledOnCurrentHost) compilation.compileDependencyFiles
else objectFactory.fileCollection()
}
)
@get:Input
val outputKind: CompilerOutputKind by lazyConvention { binary.outputKind.compilerOutputKind }
@get:Input
val optimized: Boolean by lazyConvention { binary.optimized }
@get:Input
val debuggable: Boolean by lazyConvention { binary.debuggable }
@get:Input
val baseName: String by lazyConvention { binary.baseName }
@get:Input
internal val binaryName: String by lazyConvention { binary.name }
@Suppress("DEPRECATION")
private val konanTarget = compilation.konanTarget
@Suppress("DEPRECATION")
@Deprecated("Use toolOptions to configure the task")
@get:Internal
val languageSettings: LanguageSettings = compilation.defaultSourceSet.languageSettings
@Suppress("unused")
@get:Input
protected val konanCacheKind: Provider = objectFactory.providerWithLazyConvention {
project.getKonanCacheKind(konanTarget)
}
@get:Input
internal val useEmbeddableCompilerJar: Boolean = project.nativeUseEmbeddableCompilerJar
@Suppress("unused", "UNCHECKED_CAST")
@Deprecated(
"Use toolOptions.freeCompilerArgs",
replaceWith = ReplaceWith("toolOptions.freeCompilerArgs.get()")
)
@get:Internal
val additionalCompilerOptions: Provider> = toolOptions.freeCompilerArgs as Provider>
@get:Internal
val kotlinOptions: KotlinCommonToolOptions = object : KotlinCommonToolOptions {
override val options: KotlinCommonCompilerToolOptions
get() = toolOptions
}
fun kotlinOptions(fn: KotlinCommonToolOptions.() -> Unit) {
kotlinOptions.fn()
}
fun kotlinOptions(fn: Closure<*>) {
fn.delegate = kotlinOptions
fn.call()
}
// Binary-specific options.
private val _entryPoint: String by lazyConvention { (binary as? Executable)?.entryPoint.orEmpty() }
@get:Input
@get:Optional
val entryPoint: String?
get() = _entryPoint.ifEmpty { null }
@get:Input
val linkerOpts: List by lazyConvention { binary.linkerOpts }
@get:Input
internal val additionalLinkerOpts: MutableList = mutableListOf()
@get:Input
val binaryOptions: Map by lazy { PropertiesProvider(project).nativeBinaryOptions + binary.binaryOptions }
@get:Input
val processTests: Boolean by lazyConvention { binary is TestExecutable }
@get:Classpath
val exportLibraries: FileCollection get() = exportLibrariesResolvedConfiguration?.files ?: objectFactory.fileCollection()
private val exportLibrariesResolvedConfiguration = if (binary is AbstractNativeLibrary) {
LazyResolvedConfiguration(project.configurations.getByName(binary.exportConfigurationName))
} else {
null
}
@get:Input
val isStaticFramework: Boolean by lazyConvention { binary.let { it is Framework && it.isStatic } }
@Suppress("DEPRECATION")
@get:Input
val target: String = compilation.konanTarget.name
@Deprecated("Use 'embedBitcodeMode' provider instead.", ReplaceWith("embedBitcodeMode.get()"))
@get:Internal
val embedBitcode: BitcodeEmbeddingMode
get() = embedBitcodeMode.get()
@get:Input
@get:Optional
val embedBitcodeMode: Provider =
(binary as? Framework)?.embedBitcodeMode ?: objectFactory.property()
@get:Internal
val apiFiles = project.files(project.configurations.getByName(compilation.apiConfigurationName)).filterKlibsPassedToCompiler()
@get:Optional
@get:InputFile
@get:PathSensitive(PathSensitivity.RELATIVE)
internal val xcodeVersion = objectFactory.fileProperty()
private val externalDependenciesArgs by lazy { ExternalDependenciesBuilder(project, compilation).buildCompilerArgs() }
private val cacheBuilderSettings by lazy {
CacheBuilder.Settings.createWithProject(konanHome.get(), konanDataDir.getOrNull(), project, binary, konanTarget, toolOptions, externalDependenciesArgs)
}
private class CacheSettings(val orchestration: NativeCacheOrchestration, val kind: NativeCacheKind,
val icEnabled: Boolean, val threads: Int,
val gradleUserHomeDir: File, val gradleBuildDir: File)
private val cacheSettings by lazy {
CacheSettings(project.getKonanCacheOrchestration(), project.getKonanCacheKind(konanTarget),
project.isKonanIncrementalCompilationEnabled(), project.getKonanParallelThreads(),
project.gradle.gradleUserHomeDir, project.buildDir)
}
override fun createCompilerArguments(context: CreateCompilerArgumentsContext) = context.create {
val compilerPlugins = listOfNotNull(
compilerPluginClasspath?.let { CompilerPluginData(it, compilerPluginOptions) },
kotlinPluginData?.orNull?.let { CompilerPluginData(it.classpath, it.options) }
)
primitive { args ->
args.outputName = outputFile.get().absolutePath
args.optimization = optimized
args.debug = debuggable
args.enableAssertions = debuggable
args.target = konanTarget.name
args.produce = outputKind.name.toLowerCaseAsciiOnly()
args.multiPlatform = true
args.noendorsedlibs = true
args.pluginOptions = compilerPlugins.flatMap { it.options.arguments }.toTypedArray()
args.generateTestRunner = processTests
args.mainPackage = entryPoint
when (bitcodeEmbeddingMode()) {
BitcodeEmbeddingMode.BITCODE -> args.embedBitcode = true
BitcodeEmbeddingMode.MARKER -> args.embedBitcodeMarker = true
BitcodeEmbeddingMode.DISABLE -> Unit
}
args.singleLinkerArguments = (linkerOpts + additionalLinkerOpts).toTypedArray()
args.binaryOptions = binaryOptions.map { (key, value) -> "$key=$value" }.toTypedArray()
args.staticFramework = isStaticFramework
KotlinCommonCompilerToolOptionsHelper.fillCompilerArguments(toolOptions, args)
}
pluginClasspath { args ->
args.pluginClasspaths = compilerPlugins.flatMap { classpath -> runSafe { classpath.files } ?: emptySet() }.toPathsArray()
}
dependencyClasspath { args ->
args.libraries = runSafe { libraries.files.filterKlibsPassedToCompiler() }?.toPathsArray()
args.exportedLibraries = runSafe { exportLibraries.files.filterKlibsPassedToCompiler() }?.toPathsArray()
args.friendModules = runSafe { friendModule.files.toList().takeIf { it.isNotEmpty() } }
?.joinToString(File.pathSeparator) { it.absolutePath }
}
sources { args ->
args.includes = sources.asFileTree.files.toPathsArray()
}
}
private fun validatedExportedLibraries() {
if (exportLibrariesResolvedConfiguration == null) return
val failed = mutableSetOf()
exportLibrariesResolvedConfiguration
.allDependencies
.filterIsInstance()
.forEach {
val dependencyFiles = exportLibrariesResolvedConfiguration.getArtifacts(it).map { it.file }.filterKlibsPassedToCompiler()
if (!apiFiles.files.containsAll(dependencyFiles)) {
failed.add(it)
}
}
check(failed.isEmpty()) {
val failedDependenciesList = failed.joinToString(separator = "\n") {
val componentId = it.selected.id
when (componentId) {
is ModuleComponentIdentifier -> "|Files: ${exportLibrariesResolvedConfiguration.getArtifacts(it).map { it.file }}"
is ProjectComponentIdentifier -> "|Project ${componentId.projectPath}"
else -> "|${componentId.displayName}"
}
}
"""
|Following dependencies exported in the $binaryName binary are not specified as API-dependencies of a corresponding source set:
|
$failedDependenciesList
|
|Please add them in the API-dependencies and rerun the build.
""".trimMargin()
}
}
@Suppress("DEPRECATION")
@get:Classpath
protected val friendModule: FileCollection = objectFactory.fileCollection().from({ compilation.friendPaths })
@Suppress("DEPRECATION")
private val resolvedConfiguration = LazyResolvedConfiguration(
project.configurations.getByName(compilation.compileDependencyConfigurationName)
)
@get:Internal
open val outputFile: Provider
get() = destinationDirectory.flatMap {
val prefix = outputKind.prefix(konanTarget)
val suffix = outputKind.suffix(konanTarget)
val filename = "$prefix${baseName}$suffix".let {
when {
outputKind == CompilerOutputKind.FRAMEWORK ->
it.asValidFrameworkName()
outputKind in listOf(CompilerOutputKind.STATIC, CompilerOutputKind.DYNAMIC) ||
outputKind == CompilerOutputKind.PROGRAM && konanTarget == KonanTarget.WASM32 ->
it.replace('-', '_')
else -> it
}
}
objectFactory.property(it.file(filename).asFile)
}
@Suppress("unused", "DeprecatedCallableAddReplaceWith")
@Deprecated(
"Please declare explicit dependency on kotlinx-cli. This option has no longer effect since 1.9.0",
level = DeprecationLevel.ERROR
)
@get:Input
val enableEndorsedLibs: Boolean
get() = false
@Internal
val compilerPluginOptions = CompilerPluginOptions()
@Optional
@Classpath
open var compilerPluginClasspath: FileCollection? = null
/**
* Plugin Data provided by [KpmCompilerPlugin]
*/
@get:Optional
@get:Nested
var kotlinPluginData: Provider? = null
@TaskAction
fun compile() {
val metricsReporter = metrics.get()
addBuildMetricsForTaskAction(metricsReporter = metricsReporter, languageVersion = null) {
validatedExportedLibraries()
val output = outputFile.get()
output.parentFile.mkdirs()
val executionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger)
val additionalOptions = mutableListOf().apply {
addAll(externalDependenciesArgs)
when (cacheSettings.orchestration) {
NativeCacheOrchestration.Compiler -> {
if (cacheSettings.kind != NativeCacheKind.NONE
&& !optimized
&& konanPropertiesService.get().cacheWorksFor(konanTarget)
) {
add("-Xauto-cache-from=${cacheSettings.gradleUserHomeDir}")
add("-Xbackend-threads=${cacheSettings.threads}")
if (cacheSettings.icEnabled) {
val icCacheDir = cacheSettings.gradleBuildDir.resolve("kotlin-native-ic-cache")
icCacheDir.mkdirs()
add("-Xenable-incremental-compilation")
add("-Xic-cache-dir=$icCacheDir")
}
}
}
NativeCacheOrchestration.Gradle -> {
if (cacheSettings.icEnabled) {
executionContext.logger.warn(
"K/N incremental compilation only works in conjunction with kotlin.native.cacheOrchestration=compiler"
)
}
val cacheBuilder = CacheBuilder(
executionContext = executionContext,
settings = cacheBuilderSettings,
konanPropertiesService = konanPropertiesService.get(),
metricsReporter = metricsReporter
)
addAll(cacheBuilder.buildCompilerArgs(resolvedConfiguration))
}
}
}
val arguments = createCompilerArguments()
val buildArguments = ArgumentUtils.convertArgumentsToStringList(arguments) + additionalOptions
KotlinNativeCompilerRunner(
settings = runnerSettings,
executionContext = executionContext,
metricsReporter = metricsReporter
).run(buildArguments)
}
}
private inline fun lazyConvention(noinline lazyConventionValue: () -> T): Provider {
return objectFactory.providerWithLazyConvention(lazyConventionValue)
}
private fun bitcodeEmbeddingMode(): BitcodeEmbeddingMode {
return XcodeUtils.bitcodeEmbeddingMode(outputKind, embedBitcodeMode.orNull, xcodeVersion, konanTarget, debuggable)
}
}