[Gradle] Streamline how cinterop artifacts are exposed within a Gradle project

Before:
- The cinterop task's output files were added as file dependency
to the declaring target's apiElementsConfiguration
- A 'copy' task was created for the cinterop artifact that was added
to the apiElements configuration as artifact (and therefore also
to the apiElements-published). This copy task placed the
same klib into the 'libs' folder
- Before passing libraries to the compiler the, all files
that are likely to be the result of the 'copy' task (in any libs dir) were
filtered

After:
- The cinterop task's output files are *not* added as file dependency
- The cinterop task's output is added as artifact directly to
the 'apiElements' configuration
- There is no more need for a copy task
- There is no more need for manually filtering the 'libs' artifacts

Tested:
project to project dependencies,
project to project dependencies (with KGP based dependency resolution)
project to repository
project to repository (with KGP based dependency resolution)

^KT-37051 Verification Pending
This commit is contained in:
Sebastian Sellmair
2023-02-01 15:58:08 +01:00
committed by Space Team
parent e401c29c26
commit 8a62523ffc
4 changed files with 14 additions and 58 deletions
@@ -84,7 +84,6 @@ class ConfigurationCacheIT : AbstractConfigurationCacheIT() {
":lib:cinteropMyCinteropLinuxX64",
":lib:commonizeCInterop",
":lib:compileKotlinLinuxX64",
":lib:copyCinteropMyCinteropLinuxX64",
":lib:linkExecutableDebugExecutableLinuxX64",
":lib:linkSharedDebugSharedLinuxX64",
":lib:linkStaticDebugStaticLinuxX64",
@@ -95,7 +94,6 @@ class ConfigurationCacheIT : AbstractConfigurationCacheIT() {
expectedTasks += listOf(
":lib:cinteropMyCinteropIosX64",
":lib:compileKotlinIosX64",
":lib:copyCinteropMyCinteropIosX64",
":lib:assembleMyframeDebugFrameworkIosArm64",
":lib:assembleMyfatframeDebugFatFramework",
":lib:assembleLibDebugXCFramework",
@@ -21,7 +21,6 @@ import org.gradle.api.internal.artifacts.ArtifactAttributes
import org.gradle.api.internal.plugins.DefaultArtifactPublicationSet
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.Exec
import org.gradle.api.tasks.TaskProvider
import org.gradle.language.base.plugins.LifecycleBasePlugin
@@ -30,7 +29,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationInfo.KPM
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.KOTLIN_NATIVE_IGNORE_INCORRECT_DEPENDENCIES
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.GradleKpmVariant
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
import org.jetbrains.kotlin.gradle.targets.native.*
@@ -38,12 +37,16 @@ import org.jetbrains.kotlin.gradle.targets.native.internal.commonizeCInteropTask
import org.jetbrains.kotlin.gradle.targets.native.internal.createCInteropApiElementsKlibArtifact
import org.jetbrains.kotlin.gradle.targets.native.internal.locateOrCreateCInteropApiElementsConfiguration
import org.jetbrains.kotlin.gradle.targets.native.internal.locateOrCreateCInteropDependencyConfiguration
import org.jetbrains.kotlin.gradle.targets.native.tasks.*
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeHostTest
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeSimulatorTest
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest
import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.gradle.testing.internal.configureConventions
import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry
import org.jetbrains.kotlin.gradle.testing.testTaskName
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.Xcode
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.gradle.utils.newInstance
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
@@ -247,9 +250,6 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
// Register the interop library as a dependency of the compilation to make IDE happy.
project.dependencies.add(compileDependencyConfigurationName, interopOutput)
if (isMain()) {
// Register the interop library as an outgoing klib to allow depending on projects with cinterops.
project.dependencies.add(target.apiElementsConfigurationName, interopOutput)
// Add interop library to special CInteropApiElements configuration
createCInteropApiElementsKlibArtifact(compilation.target, interop, interopTask)
@@ -260,10 +260,8 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
artifactFile = interopTask.map { it.outputFile },
classifier = "cinterop-${interop.name}",
producingTask = interopTask,
copy = true
)
// We cannot add the interop library in an compilation output because in this case
// IDE doesn't see this library in module dependencies. So we have to manually add
// main interop libraries in dependencies of the default test compilation.
@@ -555,7 +553,6 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
artifactFile: Provider<File>,
classifier: String?,
producingTask: TaskProvider<*>,
copy: Boolean = false
) {
val project = compilationInfo.project
if (!konanTarget.enabledOnCurrentHost) {
@@ -567,30 +564,13 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
is KotlinCompilationInfo.TCS -> compilationInfo.compilation.target.apiElementsConfigurationName
}
val apiElements = project.configurations.getByName(apiElementsName)
val realProducingTask: TaskProvider<*>
// TODO: Someone remove this HACK PLEASE!
val realArtifactFile = if (copy) {
realProducingTask = project.project.registerTask<Copy>("copy${producingTask.name.capitalizeAsciiOnly()}") {
val targetSubDirectory = compilationInfo.targetDisambiguationClassifier?.let { "$it/" }.orEmpty()
it.destinationDir = project.project.buildDir.resolve("libs/$targetSubDirectory${compilationInfo.compilationName}")
it.from(artifactFile)
it.dependsOn(producingTask)
}
realProducingTask.map { (it as Copy).destinationDir.resolve(artifactFile.get().name) }
} else {
realProducingTask = producingTask
artifactFile
}
with(apiElements) {
val klibArtifact = project.project.artifacts.add(apiElements.name, realArtifactFile) { artifact ->
with(project.configurations.getByName(apiElementsName)) {
val klibArtifact = project.project.artifacts.add(name, artifactFile) { artifact ->
artifact.name = compilationInfo.compilationName
artifact.extension = "klib"
artifact.type = "klib"
artifact.classifier = classifier
artifact.builtBy(realProducingTask)
artifact.builtBy(producingTask)
}
project.project.extensions.getByType(DefaultArtifactPublicationSet::class.java).addCandidate(klibArtifact)
artifacts.add(klibArtifact)
@@ -14,7 +14,6 @@ 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
@@ -80,10 +79,7 @@ constructor(
{
// 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)
)
if (konanTarget.enabledOnCurrentHost) compilation.compileDependencyFiles
else objectFactory.fileCollection()
}
)
@@ -52,7 +52,6 @@ import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.project.model.LanguageSettings
import java.io.File
import java.nio.file.Files
import java.nio.file.Path
import javax.inject.Inject
import kotlin.collections.associateBy
import kotlin.collections.component1
@@ -95,20 +94,6 @@ internal fun MutableList<String>.addFileArgs(parameter: String, values: FileColl
}
}
// We need to filter out interop duplicates because we create copy of them for IDE.
// TODO: Remove this after interop rework.
internal fun FileCollection.filterOutPublishableInteropLibs(project: Project): FileCollection =
filterOutPublishableInteropLibs(project.buildLibDirectories())
private fun Project.buildLibDirectories(): List<Path> =
rootProject.allprojects.map { it.buildDir.resolve("libs").absoluteFile.toPath() }
private fun FileCollection.filterOutPublishableInteropLibs(libDirectories: List<Path>): FileCollection {
return filter { file ->
!(file.name.contains("-cinterop-") && libDirectories.any { file.toPath().startsWith(it) })
}
}
/**
* We pass to the compiler:
*
@@ -464,7 +449,6 @@ internal constructor(
return SharedCompilationData(manifestFile, isAllowCommonizer, refinesModule)
}
private val libDirectories = project.buildLibDirectories()
@TaskAction
fun compile() {
@@ -481,7 +465,7 @@ internal constructor(
optimized,
debuggable,
konanTarget,
libraries.filterOutPublishableInteropLibs(libDirectories).files.filterKlibsPassedToCompiler(),
libraries.files.filterKlibsPassedToCompiler(),
languageSettings,
enableEndorsedLibs,
compilerOptions,
@@ -707,7 +691,7 @@ internal class CacheBuilder(
return Settings(
runnerSettings = KotlinNativeCompilerRunner.Settings.fromProject(project),
konanCacheKind = konanCacheKind,
libraries = binary.compilation.compileDependencyFiles.filterOutPublishableInteropLibs(project),
libraries = binary.compilation.compileDependencyFiles,
gradleUserHomeDir = project.gradle.gradleUserHomeDir,
binary, konanTarget, toolOptions, externalDependenciesArgs
)
@@ -1046,13 +1030,11 @@ open class CInteropProcess @Inject internal constructor(params: Params) : Defaul
@get:PathSensitive(PathSensitivity.RELATIVE)
val headerFilterDirs: Set<File> get() = settings.includeDirs.headerFilterDirs.files
private val libDirectories = project.buildLibDirectories()
@get:IgnoreEmptyDirectories
@get:InputFiles
@get:NormalizeLineEndings
@get:PathSensitive(PathSensitivity.RELATIVE)
val libraries: FileCollection get() = settings.dependencyFiles.filterOutPublishableInteropLibs(libDirectories)
val libraries: FileCollection get() = settings.dependencyFiles
@get:Input
val extraOpts: List<String> get() = settings.extraOpts