KotlinNativeLink task now uses compiler options

Now KotlinNativeLink task does not extend AbstractKotlinNativeCompile
task as Link task is tool type task that should use
CompilerCommonToolOptions.

^KT-27301 In Progress
This commit is contained in:
Yahor Berdnikau
2022-09-12 14:07:55 +02:00
parent c7064a5edf
commit 564ed0d181
3 changed files with 166 additions and 70 deletions
@@ -30,6 +30,8 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.KOTLIN_NA
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.registerEmbedAndSignAppleFrameworkTask
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmAwareTargetConfigurator
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
import org.jetbrains.kotlin.gradle.targets.native.*
import org.jetbrains.kotlin.gradle.targets.native.internal.commonizeCInteropTask
@@ -52,6 +54,10 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
// region Task creation.
private fun Project.createLinkTask(binary: NativeBinary) {
// workaround for too late compilation compilerOptions creation
// which leads to not able run project.afterEvaluate because of wrong context
// this afterEvaluate comes from NativeCompilerOptions
val compilationCompilerOptions = binary.compilation.compilerOptions
val result = registerTask<KotlinNativeLink>(
binary.linkTaskName, listOf(binary)
) {
@@ -62,6 +68,21 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
val konanPropertiesBuildService = KonanPropertiesBuildService.registerIfAbsent(project.gradle)
it.konanPropertiesService.set(konanPropertiesBuildService)
it.usesService(konanPropertiesBuildService)
it.toolOptions.freeCompilerArgs.convention(
compilationCompilerOptions.options.freeCompilerArgs
)
}
runOnceAfterEvaluated("Sync language settings for NativeLinkTask") {
result.configure {
// We propagate compilation free args to the link task for now (see KT-33717).
val defaultLanguageSettings = binary.compilation.languageSettings as? DefaultLanguageSettingsBuilder
if (defaultLanguageSettings != null) {
it.toolOptions.freeCompilerArgs.addAll(
defaultLanguageSettings.freeCompilerArgs
)
}
}
}
@@ -10,27 +10,32 @@ 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.provider.ProviderFactory
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.compilerRunner.getKonanCacheKind
import org.jetbrains.kotlin.gradle.dsl.CompilerCommonToolOptions
import org.jetbrains.kotlin.gradle.dsl.CompilerCommonToolOptionsDefault
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions
import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
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.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.targets.native.KonanPropertiesBuildService
import org.jetbrains.kotlin.gradle.targets.native.tasks.CompilerPluginData
import org.jetbrains.kotlin.gradle.targets.native.tasks.buildKotlinNativeBinaryLinkerArgs
import org.jetbrains.kotlin.gradle.utils.ResolvedDependencyGraph
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 java.io.File
import javax.inject.Inject
/**
@@ -43,88 +48,131 @@ constructor(
@Internal
val binary: NativeBinary,
private val objectFactory: ObjectFactory,
private val providerFactory: ProviderFactory,
private val execOperations: ExecOperations
) : AbstractKotlinNativeCompile<KotlinCommonToolOptions, KotlinNativeCompilation, StubK2NativeCompilerArguments>(objectFactory) {
) : AbstractKotlinCompileTool<StubK2NativeCompilerArguments>(objectFactory),
KotlinToolTask<CompilerCommonToolOptions> {
@Deprecated("Visibility will be lifted to private in the future releases")
@get:Internal
final override val compilation: KotlinNativeCompilation
val compilation: KotlinNativeCompilation
get() = binary.compilation
private val runnerSettings = KotlinNativeCompilerRunner.Settings.fromProject(project)
final override val toolOptions: CompilerCommonToolOptions = objectFactory
.newInstance<CompilerCommonToolOptionsDefault>()
.apply {
freeCompilerArgs.addAll(PropertiesProvider(project).nativeLinkArgs)
}
init {
dependsOn(project.provider { compilation.compileKotlinTaskProvider })
@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 }
this.setSource(compilation.compileKotlinTask.outputFile)
@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
override val outputKind: CompilerOutputKind
@Input get() = binary.outputKind.compilerOutputKind
override val optimized: Boolean
@Input get() = binary.optimized
override val debuggable: Boolean
@Input get() = binary.debuggable
override val baseName: String
@Input get() = binary.baseName
@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)
objectFactory.fileCollection().from(
compilation.compileDependencyFiles.filterOutPublishableInteropLibs(project)
)
else objectFactory.fileCollection()
}
)
@get:Input
protected val konanCacheKind: NativeCacheKind by lazy {
val outputKind: CompilerOutputKind get() = binary.outputKind.compilerOutputKind
@get:Input
val optimized: Boolean get() = binary.optimized
@get:Input
val debuggable: Boolean get() = binary.debuggable
@get:Input
val baseName: String get() = binary.baseName
@Suppress("DEPRECATION")
private val konanTarget = compilation.konanTarget
@Suppress("DEPRECATION")
@Deprecated("Use toolOptions to configure the task")
@get:Internal
val languageSettings: LanguageSettings = compilation.languageSettings
@Suppress("unused")
@get:Input
protected val konanCacheKind: Provider<NativeCacheKind> = objectFactory.providerWithLazyConvention {
project.getKonanCacheKind(konanTarget)
}
inner class NativeLinkOptions : KotlinCommonToolOptions {
override var allWarningsAsErrors: Boolean = false
override var suppressWarnings: Boolean = false
override var verbose: Boolean = false
override var freeCompilerArgs: List<String> = listOf()
}
private val nativeLinkArgs = PropertiesProvider(project).nativeLinkArgs
// We propagate compilation free args to the link task for now (see KT-33717).
@get:Input
override val additionalCompilerOptions: Provider<Collection<String>> = providerFactory.provider {
kotlinOptions.freeCompilerArgs +
compilation.kotlinOptions.freeCompilerArgs +
((languageSettings as? DefaultLanguageSettingsBuilder)?.freeCompilerArgs ?: emptyList()) +
nativeLinkArgs
internal val useEmbeddableCompilerJar: Boolean
get() = project.nativeUseEmbeddableCompilerJar
@Suppress("unused", "UNCHECKED_CAST")
@Deprecated(
"Use toolOptions.freeCompilerArgs",
replaceWith = ReplaceWith("toolOptions.freeCompilerArgs")
)
@get:Internal
val additionalCompilerOptions: Provider<Collection<String>> = toolOptions.freeCompilerArgs as Provider<Collection<String>>
@Suppress("DEPRECATION")
@Deprecated(
message = "Replaced with toolOptions",
replaceWith = ReplaceWith("toolOptions")
)
@get:Internal
val kotlinOptions: KotlinCommonToolOptions = object : KotlinCommonToolOptions {
override val options: CompilerCommonToolOptions
get() = toolOptions
}
override val kotlinOptions: KotlinCommonToolOptions = NativeLinkOptions()
override fun kotlinOptions(fn: KotlinCommonToolOptions.() -> Unit) {
@Suppress("DEPRECATION")
@Deprecated(
message = "Replaced with toolOptions()",
replaceWith = ReplaceWith("toolOptions(fn)")
)
fun kotlinOptions(fn: KotlinCommonToolOptions.() -> Unit) {
kotlinOptions.fn()
}
override fun kotlinOptions(fn: Closure<*>) {
@Deprecated(
message = "Replaced with toolOptions()",
replaceWith = ReplaceWith("toolOptions(fn)")
)
fun kotlinOptions(fn: Closure<*>) {
@Suppress("DEPRECATION")
fn.delegate = kotlinOptions
fn.call()
}
// Binary-specific options.
val entryPoint: String?
@Input
@Optional
get() = (binary as? Executable)?.entryPoint
@get:Input
@get:Optional
val entryPoint: String? get() = (binary as? Executable)?.entryPoint
val linkerOpts: List<String>
@Input get() = binary.linkerOpts
@get:Input
val linkerOpts: List<String> get() = binary.linkerOpts
@get:Input
val binaryOptions: Map<String, String> by lazy { PropertiesProvider(project).nativeBinaryOptions + binary.binaryOptions }
val processTests: Boolean
@Input get() = binary is TestExecutable
@get:Input
val processTests: Boolean get() = binary is TestExecutable
@get:Classpath
val exportLibraries: FileCollection get() = exportLibrariesResolvedGraph?.files ?: objectFactory.fileCollection()
@@ -146,18 +194,10 @@ constructor(
@get:Internal
val apiFiles = project.files(project.configurations.getByName(compilation.apiConfigurationName)).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.get().toList()
}
private val externalDependenciesArgs by lazy { ExternalDependenciesBuilder(project, compilation).buildCompilerArgs() }
private val cacheBuilderSettings by lazy {
CacheBuilder.Settings.createWithProject(project, binary, konanTarget, localKotlinOptions, externalDependenciesArgs)
CacheBuilder.Settings.createWithProject(project, binary, konanTarget, toolOptions, externalDependenciesArgs)
}
override fun createCompilerArgs(): StubK2NativeCompilerArguments = StubK2NativeCompilerArguments()
@@ -205,10 +245,52 @@ constructor(
@get:Internal
internal abstract val konanPropertiesService: Property<KonanPropertiesBuildService>
@Suppress("DEPRECATION")
@get:Classpath
protected val friendModule: FileCollection = objectFactory.fileCollection().from({ compilation.friendPaths })
@Suppress("DEPRECATION")
private val resolvedDependencyGraph = ResolvedDependencyGraph(
project.configurations.getByName(compilation.compileDependencyConfigurationName)
)
@get:Internal
open val outputFile: Provider<File>
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("DEPRECATION")
@get:Input
val enableEndorsedLibs: Boolean get() = compilation.enableEndorsedLibs
@Internal
val compilerPluginOptions = CompilerPluginOptions()
@Optional
@Classpath
open var compilerPluginClasspath: FileCollection? = null
/**
* Plugin Data provided by [KpmCompilerPlugin]
*/
@get:Optional
@get:Nested
var kotlinPluginData: Provider<KotlinCompilerPluginData>? = null
@TaskAction
fun compile() {
validatedExportedLibraries()
@@ -237,7 +319,7 @@ constructor(
libraries.files.filterKlibsPassedToCompiler(),
friendModule.files.toList(),
enableEndorsedLibs,
localKotlinOptions,
toolOptions,
plugins,
processTests,
entryPoint,
@@ -12,17 +12,14 @@ import org.gradle.api.Project
import org.gradle.api.artifacts.*
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.artifacts.component.ModuleComponentSelector
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.artifacts.result.DependencyResult
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.file.FileTree
import org.gradle.api.file.ProjectLayout
import org.gradle.api.file.RegularFile
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.provider.ProviderFactory
import org.gradle.api.tasks.*
@@ -32,15 +29,11 @@ import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments
import org.jetbrains.kotlin.compilerRunner.*
import org.jetbrains.kotlin.compilerRunner.KotlinNativeCInteropRunner.Companion.run
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions
import org.jetbrains.kotlin.gradle.dsl.*
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
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinNativeCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinNativeFragmentMetadataCompilationData
@@ -108,7 +101,7 @@ private fun File.providedByCompiler(project: Project): Boolean =
// We need to filter out interop duplicates because we create copy of them for IDE.
// TODO: Remove this after interop rework.
private fun FileCollection.filterOutPublishableInteropLibs(project: Project): FileCollection =
internal fun FileCollection.filterOutPublishableInteropLibs(project: Project): FileCollection =
filterOutPublishableInteropLibs(project.buildLibDirectories())
private fun Project.buildLibDirectories(): List<Path> =
@@ -660,7 +653,7 @@ internal class CacheBuilder(
val gradleUserHomeDir: File,
val binary: NativeBinary,
val konanTarget: KonanTarget,
val kotlinOptions: KotlinCommonToolOptions,
val toolOptions: CompilerCommonToolOptions,
val externalDependenciesArgs: List<String>
) {
val rootCacheDirectory get() = getRootCacheDirectory(
@@ -675,7 +668,7 @@ internal class CacheBuilder(
project: Project,
binary: NativeBinary,
konanTarget: KonanTarget,
kotlinOptions: KotlinCommonToolOptions,
toolOptions: CompilerCommonToolOptions,
externalDependenciesArgs: List<String>
): Settings {
val konanCacheKind = project.getKonanCacheKind(konanTarget)
@@ -684,7 +677,7 @@ internal class CacheBuilder(
konanCacheKind = konanCacheKind,
libraries = binary.compilation.compileDependencyFiles.filterOutPublishableInteropLibs(project),
gradleUserHomeDir = project.gradle.gradleUserHomeDir,
binary, konanTarget, kotlinOptions, externalDependenciesArgs
binary, konanTarget, toolOptions, externalDependenciesArgs
)
}
}
@@ -722,7 +715,7 @@ internal class CacheBuilder(
get() = settings.rootCacheDirectory
private val partialLinkage: Boolean
get() = PARTIAL_LINKAGE in settings.kotlinOptions.freeCompilerArgs
get() = PARTIAL_LINKAGE in settings.toolOptions.freeCompilerArgs.get()
private fun getCacheDirectory(
resolvedDependencyGraph: ResolvedDependencyGraph,