diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt index 2e6185436b5..141bcb96865 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt @@ -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 : 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( binary.linkTaskName, listOf(binary) ) { @@ -62,6 +68,21 @@ open class KotlinNativeTargetConfigurator : 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 + ) + } + } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt index c3c5b4ddf3f..68c779ec03d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt @@ -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(objectFactory) { +) : AbstractKotlinCompileTool(objectFactory), + KotlinToolTask { + @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() + .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 = 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 = 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> = 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> = toolOptions.freeCompilerArgs as Provider> + + @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 - @Input get() = binary.linkerOpts + @get:Input + val linkerOpts: List get() = binary.linkerOpts @get:Input val binaryOptions: Map 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 + @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 + 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? = null + @TaskAction fun compile() { validatedExportedLibraries() @@ -237,7 +319,7 @@ constructor( libraries.files.filterKlibsPassedToCompiler(), friendModule.files.toList(), enableEndorsedLibs, - localKotlinOptions, + toolOptions, plugins, processTests, entryPoint, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt index c859a1c400e..0fb74b94055 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt @@ -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 = @@ -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 ) { val rootCacheDirectory get() = getRootCacheDirectory( @@ -675,7 +668,7 @@ internal class CacheBuilder( project: Project, binary: NativeBinary, konanTarget: KonanTarget, - kotlinOptions: KotlinCommonToolOptions, + toolOptions: CompilerCommonToolOptions, externalDependenciesArgs: List ): 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,