[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:cinteropMyCinteropLinuxX64",
":lib:commonizeCInterop", ":lib:commonizeCInterop",
":lib:compileKotlinLinuxX64", ":lib:compileKotlinLinuxX64",
":lib:copyCinteropMyCinteropLinuxX64",
":lib:linkExecutableDebugExecutableLinuxX64", ":lib:linkExecutableDebugExecutableLinuxX64",
":lib:linkSharedDebugSharedLinuxX64", ":lib:linkSharedDebugSharedLinuxX64",
":lib:linkStaticDebugStaticLinuxX64", ":lib:linkStaticDebugStaticLinuxX64",
@@ -95,7 +94,6 @@ class ConfigurationCacheIT : AbstractConfigurationCacheIT() {
expectedTasks += listOf( expectedTasks += listOf(
":lib:cinteropMyCinteropIosX64", ":lib:cinteropMyCinteropIosX64",
":lib:compileKotlinIosX64", ":lib:compileKotlinIosX64",
":lib:copyCinteropMyCinteropIosX64",
":lib:assembleMyframeDebugFrameworkIosArm64", ":lib:assembleMyframeDebugFrameworkIosArm64",
":lib:assembleMyfatframeDebugFatFramework", ":lib:assembleMyfatframeDebugFatFramework",
":lib:assembleLibDebugXCFramework", ":lib:assembleLibDebugXCFramework",
@@ -21,7 +21,6 @@ import org.gradle.api.internal.artifacts.ArtifactAttributes
import org.gradle.api.internal.plugins.DefaultArtifactPublicationSet import org.gradle.api.internal.plugins.DefaultArtifactPublicationSet
import org.gradle.api.plugins.BasePlugin import org.gradle.api.plugins.BasePlugin
import org.gradle.api.provider.Provider import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.Exec import org.gradle.api.tasks.Exec
import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.TaskProvider
import org.gradle.language.base.plugins.LifecycleBasePlugin 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.PropertiesProvider.Companion.KOTLIN_NATIVE_IGNORE_INCORRECT_DEPENDENCIES
import org.jetbrains.kotlin.gradle.plugin.mpp.* import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.registerEmbedAndSignAppleFrameworkTask 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.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
import org.jetbrains.kotlin.gradle.targets.native.* 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.createCInteropApiElementsKlibArtifact
import org.jetbrains.kotlin.gradle.targets.native.internal.locateOrCreateCInteropApiElementsConfiguration 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.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.tasks.*
import org.jetbrains.kotlin.gradle.testing.internal.configureConventions import org.jetbrains.kotlin.gradle.testing.internal.configureConventions
import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry
import org.jetbrains.kotlin.gradle.testing.testTaskName 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.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly 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. // Register the interop library as a dependency of the compilation to make IDE happy.
project.dependencies.add(compileDependencyConfigurationName, interopOutput) project.dependencies.add(compileDependencyConfigurationName, interopOutput)
if (isMain()) { 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 // Add interop library to special CInteropApiElements configuration
createCInteropApiElementsKlibArtifact(compilation.target, interop, interopTask) createCInteropApiElementsKlibArtifact(compilation.target, interop, interopTask)
@@ -260,10 +260,8 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
artifactFile = interopTask.map { it.outputFile }, artifactFile = interopTask.map { it.outputFile },
classifier = "cinterop-${interop.name}", classifier = "cinterop-${interop.name}",
producingTask = interopTask, producingTask = interopTask,
copy = true
) )
// We cannot add the interop library in an compilation output because in this case // 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 // 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. // main interop libraries in dependencies of the default test compilation.
@@ -555,7 +553,6 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
artifactFile: Provider<File>, artifactFile: Provider<File>,
classifier: String?, classifier: String?,
producingTask: TaskProvider<*>, producingTask: TaskProvider<*>,
copy: Boolean = false
) { ) {
val project = compilationInfo.project val project = compilationInfo.project
if (!konanTarget.enabledOnCurrentHost) { if (!konanTarget.enabledOnCurrentHost) {
@@ -567,30 +564,13 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
is KotlinCompilationInfo.TCS -> compilationInfo.compilation.target.apiElementsConfigurationName is KotlinCompilationInfo.TCS -> compilationInfo.compilation.target.apiElementsConfigurationName
} }
val apiElements = project.configurations.getByName(apiElementsName) with(project.configurations.getByName(apiElementsName)) {
val klibArtifact = project.project.artifacts.add(name, artifactFile) { artifact ->
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 ->
artifact.name = compilationInfo.compilationName artifact.name = compilationInfo.compilationName
artifact.extension = "klib" artifact.extension = "klib"
artifact.type = "klib" artifact.type = "klib"
artifact.classifier = classifier artifact.classifier = classifier
artifact.builtBy(realProducingTask) artifact.builtBy(producingTask)
} }
project.project.extensions.getByType(DefaultArtifactPublicationSet::class.java).addCandidate(klibArtifact) project.project.extensions.getByType(DefaultArtifactPublicationSet::class.java).addCandidate(klibArtifact)
artifacts.add(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.DirectoryProperty
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.model.ObjectFactory import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider import org.gradle.api.provider.Provider
import org.gradle.api.tasks.* import org.gradle.api.tasks.*
import org.gradle.process.ExecOperations 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: // Avoid resolving these dependencies during task graph construction when we can't build the target:
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
if (konanTarget.enabledOnCurrentHost) if (konanTarget.enabledOnCurrentHost) compilation.compileDependencyFiles
objectFactory.fileCollection().from(
compilation.compileDependencyFiles.filterOutPublishableInteropLibs(project)
)
else objectFactory.fileCollection() else objectFactory.fileCollection()
} }
) )
@@ -52,7 +52,6 @@ import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.project.model.LanguageSettings import org.jetbrains.kotlin.project.model.LanguageSettings
import java.io.File import java.io.File
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path
import javax.inject.Inject import javax.inject.Inject
import kotlin.collections.associateBy import kotlin.collections.associateBy
import kotlin.collections.component1 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: * We pass to the compiler:
* *
@@ -464,7 +449,6 @@ internal constructor(
return SharedCompilationData(manifestFile, isAllowCommonizer, refinesModule) return SharedCompilationData(manifestFile, isAllowCommonizer, refinesModule)
} }
private val libDirectories = project.buildLibDirectories()
@TaskAction @TaskAction
fun compile() { fun compile() {
@@ -481,7 +465,7 @@ internal constructor(
optimized, optimized,
debuggable, debuggable,
konanTarget, konanTarget,
libraries.filterOutPublishableInteropLibs(libDirectories).files.filterKlibsPassedToCompiler(), libraries.files.filterKlibsPassedToCompiler(),
languageSettings, languageSettings,
enableEndorsedLibs, enableEndorsedLibs,
compilerOptions, compilerOptions,
@@ -707,7 +691,7 @@ internal class CacheBuilder(
return Settings( return Settings(
runnerSettings = KotlinNativeCompilerRunner.Settings.fromProject(project), runnerSettings = KotlinNativeCompilerRunner.Settings.fromProject(project),
konanCacheKind = konanCacheKind, konanCacheKind = konanCacheKind,
libraries = binary.compilation.compileDependencyFiles.filterOutPublishableInteropLibs(project), libraries = binary.compilation.compileDependencyFiles,
gradleUserHomeDir = project.gradle.gradleUserHomeDir, gradleUserHomeDir = project.gradle.gradleUserHomeDir,
binary, konanTarget, toolOptions, externalDependenciesArgs binary, konanTarget, toolOptions, externalDependenciesArgs
) )
@@ -1046,13 +1030,11 @@ open class CInteropProcess @Inject internal constructor(params: Params) : Defaul
@get:PathSensitive(PathSensitivity.RELATIVE) @get:PathSensitive(PathSensitivity.RELATIVE)
val headerFilterDirs: Set<File> get() = settings.includeDirs.headerFilterDirs.files val headerFilterDirs: Set<File> get() = settings.includeDirs.headerFilterDirs.files
private val libDirectories = project.buildLibDirectories()
@get:IgnoreEmptyDirectories @get:IgnoreEmptyDirectories
@get:InputFiles @get:InputFiles
@get:NormalizeLineEndings @get:NormalizeLineEndings
@get:PathSensitive(PathSensitivity.RELATIVE) @get:PathSensitive(PathSensitivity.RELATIVE)
val libraries: FileCollection get() = settings.dependencyFiles.filterOutPublishableInteropLibs(libDirectories) val libraries: FileCollection get() = settings.dependencyFiles
@get:Input @get:Input
val extraOpts: List<String> get() = settings.extraOpts val extraOpts: List<String> get() = settings.extraOpts