diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt index 745b117595b..d20415d25d2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt @@ -104,13 +104,9 @@ internal open class GradleCompilerRunner( * @see [GradleKotlinCompilerWork] */ fun runMetadataCompilerAsync( - kotlinSources: List, - kotlinCommonSources: List, args: K2MetadataCompilerArguments, environment: GradleCompilerEnvironment ): WorkQueue? { - args.freeArgs += kotlinSources.map { it.absolutePath } - args.commonSources = kotlinCommonSources.map { it.absolutePath }.toTypedArray() return runCompilerAsync(KotlinCompilerClass.METADATA, args, environment) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/Kotlin2JsCompile.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/Kotlin2JsCompile.kt index 3f11cca6324..414b069cd3e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/Kotlin2JsCompile.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/Kotlin2JsCompile.kt @@ -222,14 +222,13 @@ abstract class Kotlin2JsCompile @Inject constructor( contribute(KotlinCompilerArgumentsProducer.ArgumentType.DependencyClasspath) { args -> args.friendModules = friendDependencies.files.joinToString(File.pathSeparator) { it.absolutePath } - val dependencies = libraries - .filter { it.exists() && libraryFilter(it) } - .map { it.normalize().absolutePath } - - args.libraries = dependencies.distinct().let { - if (it.isNotEmpty()) - it.joinToString(File.pathSeparator) else - null + args.libraries = tryLenient { + libraries + .filter { it.exists() && libraryFilter(it) } + .map { it.normalize().absolutePath } + .toSet() + .takeIf { it.isNotEmpty() } + ?.joinToString(File.pathSeparator) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt index d7c6129c5e8..b5cf46ec496 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt @@ -17,11 +17,13 @@ package org.jetbrains.kotlin.gradle.tasks import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.FileCollection import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.* import org.gradle.work.InputChanges import org.gradle.work.NormalizeLineEndings import org.gradle.workers.WorkerExecutor +import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl @@ -29,7 +31,12 @@ import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles import org.jetbrains.kotlin.gradle.logging.GradleErrorMessageCollector import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.CreateCompilerArgumentsContext +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.CreateCompilerArgumentsContext.Companion.create +import org.jetbrains.kotlin.gradle.report.BuildReportMode import org.jetbrains.kotlin.gradle.tasks.internal.KotlinMultiplatformCommonOptionsCompat +import org.jetbrains.kotlin.gradle.utils.toPathsArray import java.io.File import javax.inject.Inject @@ -40,6 +47,7 @@ abstract class KotlinCompileCommon @Inject constructor( objectFactory: ObjectFactory ) : AbstractKotlinCompile(objectFactory, workerExecutor), KotlinCompilationTask, + KotlinCompilerArgumentsProducer, KotlinCommonCompile { init { @@ -76,10 +84,14 @@ abstract class KotlinCompileCommon @Inject constructor( if (defaultsOnly) return - val classpathList = libraries.files.filter { it.exists() }.toMutableList() + val classpathList = try { + libraries.files.filter { it.exists() }.toMutableList() + } catch (t: Throwable) { + if (ignoreClasspathResolutionErrors) null else throw t + } with(args) { - classpath = classpathList.joinToString(File.pathSeparator) + classpath = classpathList?.joinToString(File.pathSeparator) destination = destinationDirectory.get().asFile.normalize().absolutePath friendPaths = this@KotlinCompileCommon.friendPaths.files.map { it.absolutePath }.toTypedArray() @@ -94,6 +106,51 @@ abstract class KotlinCompileCommon @Inject constructor( } } + override fun createCompilerArguments(context: CreateCompilerArgumentsContext) = context.create { + contribute(KotlinCompilerArgumentsProducer.ArgumentType.Primitive) { args -> + args.multiPlatform = multiPlatformEnabled.get() + + args.moduleName = this@KotlinCompileCommon.moduleName.get() + + args.pluginOptions = (pluginOptions.toSingleCompilerPluginOptions() + kotlinPluginData?.orNull?.options) + .arguments.toTypedArray() + + if (reportingSettings().buildReportMode == BuildReportMode.VERBOSE) { + args.reportPerf = true + } + + args.expectActualLinker = expectActualLinker.get() + + args.destination = destinationDirectory.get().asFile.normalize().absolutePath + + KotlinCommonCompilerOptionsHelper.fillCompilerArguments(compilerOptions, args) + + val localExecutionTimeFreeCompilerArgs = executionTimeFreeCompilerArgs + if (localExecutionTimeFreeCompilerArgs != null) { + args.freeArgs = localExecutionTimeFreeCompilerArgs + } + } + + contribute(KotlinCompilerArgumentsProducer.ArgumentType.PluginClasspath) { args -> + args.pluginClasspaths = tryLenient { + listOfNotNull( + pluginClasspath, kotlinPluginData?.orNull?.classpath + ).reduce(FileCollection::plus).toPathsArray() + } + } + + contribute(KotlinCompilerArgumentsProducer.ArgumentType.DependencyClasspath) { args -> + args.classpath = tryLenient { libraries.files.filter { it.exists() }.joinToString(File.pathSeparator) } + args.friendPaths = tryLenient { this@KotlinCompileCommon.friendPaths.files.toPathsArray() } + args.refinesPaths = refinesMetadataPaths.toPathsArray() + } + + contribute(KotlinCompilerArgumentsProducer.ArgumentType.Sources) { args -> + args.freeArgs += sources.asFileTree.map { it.absolutePath } + args.commonSources = commonSourceSet.asFileTree.toPathsArray() + } + } + @get:PathSensitive(PathSensitivity.RELATIVE) @get:IgnoreEmptyDirectories @get:InputFiles @@ -118,12 +175,7 @@ abstract class KotlinCompileCommon @Inject constructor( reportingSettings = reportingSettings(), outputFiles = allOutputFiles() ) - compilerRunner.runMetadataCompilerAsync( - kotlinSources.toList(), - commonSourceSet.files.toList(), - args, - environment - ) + compilerRunner.runMetadataCompilerAsync(args, environment) compilerRunner.errorsFile?.also { gradleMessageCollector.flush(it) } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/JsCompilerArgumentTests.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/Kotlin2JsCompileArgumentsTest.kt similarity index 65% rename from libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/JsCompilerArgumentTests.kt rename to libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/Kotlin2JsCompileArgumentsTest.kt index 8a43982d110..632840ea434 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/JsCompilerArgumentTests.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/Kotlin2JsCompileArgumentsTest.kt @@ -13,17 +13,22 @@ import org.jetbrains.kotlin.gradle.dependencyResolutionTests.mavenCentralCacheRe import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.internal.prepareCompilerArguments import org.jetbrains.kotlin.gradle.plugin.CreateCompilerArgumentsContext +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.ArgumentType +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.CreateCompilerArgumentsContext.Companion.default +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.CreateCompilerArgumentsContext.Companion.lenient import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP import org.jetbrains.kotlin.gradle.util.main import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFails +import kotlin.test.assertNull -class JsCompilerArgumentTests { +class Kotlin2JsCompileArgumentsTest { @Suppress("DEPRECATION") @Test - fun `test - simple project`() { + fun `test - simple project - old CompilerArgumentsAware and new CompilerArgumentsProducer - return same arguments`() { val project = buildProjectWithMPP { repositories { mavenLocal() @@ -50,4 +55,18 @@ class JsCompilerArgumentTests { ArgumentUtils.convertArgumentsToStringList(argumentsFromCompilerArgumentsProducer), ) } + + @Test + fun `test - simple project - failing dependency - lenient`() { + val project = buildProjectWithMPP() + val kotlin = project.multiplatformExtension + val jsTarget = kotlin.js() + kotlin.sourceSets.getByName("commonMain").dependencies { implementation("not-a:dependency:1.0.0") } + project.evaluate() + + val jsMainCompileTask = jsTarget.compilations.main.compileTaskProvider.get() + assertNull(jsMainCompileTask.createCompilerArguments(lenient).libraries) + + assertFails { jsMainCompileTask.createCompilerArguments(default) } + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/JvmCompilerArgumentsTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinCompileArgumentsTest.kt similarity index 99% rename from libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/JvmCompilerArgumentsTest.kt rename to libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinCompileArgumentsTest.kt index 2a1424a167a..747e2b71b1c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/JvmCompilerArgumentsTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinCompileArgumentsTest.kt @@ -28,7 +28,7 @@ import kotlin.reflect.full.findAnnotation import kotlin.test.* -class JvmCompilerArgumentsTest { +class KotlinCompileArgumentsTest { @Suppress("DEPRECATION") @Test diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinCompileCommonArgumentsTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinCompileCommonArgumentsTest.kt new file mode 100644 index 00000000000..663a2efa413 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinCompileCommonArgumentsTest.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2023 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("FunctionName") + +package org.jetbrains.kotlin.gradle.unitTests.compilerArgumetns + +import org.jetbrains.kotlin.compilerRunner.ArgumentUtils +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.internal.prepareCompilerArguments +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.CreateCompilerArgumentsContext +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.CreateCompilerArgumentsContext.Companion.lenient +import org.jetbrains.kotlin.gradle.tasks.KotlinCompileCommon +import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFails +import kotlin.test.assertNull + +class KotlinCompileCommonArgumentsTest { + @Test + @Suppress("DEPRECATION") + fun `test - simple project - old CompilerArgumentsAware and new CompilerArgumentsProducer - return same arguments`() { + val project = buildProjectWithMPP() + project.repositories.mavenLocal() + val kotlin = project.multiplatformExtension + kotlin.jvm() + kotlin.linuxX64() + project.evaluate() + + val commonMainCompilation = kotlin.metadata().compilations.getByName("commonMain") + val commonMainCompileTask = commonMainCompilation.compileTaskProvider.get() as KotlinCompileCommon + + val argumentsFromCompilerArgumentsProducer = commonMainCompileTask.createCompilerArguments(lenient) + val argumentsFromCompilerArgumentsAware = commonMainCompileTask.prepareCompilerArguments(true) + + assertEquals( + ArgumentUtils.convertArgumentsToStringList(argumentsFromCompilerArgumentsAware), + ArgumentUtils.convertArgumentsToStringList(argumentsFromCompilerArgumentsProducer) + ) + } + + @Test + fun `test - simple project - failing dependency - lenient`() { + val project = buildProjectWithMPP() + val kotlin = project.multiplatformExtension + kotlin.jvm() + kotlin.linuxX64() + kotlin.sourceSets.getByName("commonMain").dependencies { implementation("not-a:dependency:1.0.0") } + project.evaluate() + + val commonMainCompileTask = kotlin.metadata().compilations.getByName("commonMain").compileTaskProvider.get() as KotlinCompileCommon + assertNull(commonMainCompileTask.createCompilerArguments(lenient).classpath) + assertFails { commonMainCompileTask.createCompilerArguments(CreateCompilerArgumentsContext.default) } + } +} \ No newline at end of file