François
02/21/2025, 7:53 AMafterEvaluate
.
I’m planning a new feature for my plugin spmForKmp. I want to short-circuit the cinterop by keeping the .klibs.
So instead of building everything each time the same klib, I’m going to use the cached ones.
The gradle cache is working fine, but I want to go further.François
02/21/2025, 8:35 AMfreeCompilerArgs -library
which solve half of the issue, It’s ok for the binary linking task but useless for code completion, it’s not indexed.Anton Lakotka [JB]
02/21/2025, 8:50 AMFrançois
02/21/2025, 8:57 AMAnton Lakotka [JB]
02/21/2025, 8:59 AMshort-circuit the cinterop Tasks.
If enabled and not present, the cinterop final output files are stored beside the project source.
On next build, we directly use the stored files.
That sounds like task execution avoidance ( up-to-date checks) & build cache built-in Gradle features. Dont they work for you?
François
02/21/2025, 9:08 AMFrançois
02/21/2025, 9:28 AMAnton Lakotka [JB]
02/21/2025, 9:44 AMFor generating a klib, my plugin needs to build a swift package, then call cinterop for generating klib. Until the plugin config change, it will be the same klibs.so that is how Task Up-to-date check works. roughly it should look like this:
abstract class KlibProvider : DefaultTask() {
@get:Input
abstract val pluginConfigurationKey: Provider<String /* or some other type */>
@get:OutputFile
abstract val outputKlib: RegularFileProvider
@TaskAction
fun action() {
// do anything you need to generate outputKlib file.
}
}
And then you can declare dependency to such KlibProvider like following for example:
kotlin.targets.withType(KotlinNativeTarget::class.java).configureEach { target ->
val apiConfigurationName = target.compilations["main"].defaultSourceSet.apiConfigurationName
project.dependencies.add(apiConfigurationName, klibProvider.map { it.outputKlib })
}
^ the code is written from top of my head, it may not be compilable but can illustrate things you may need.
so then if Klib is already "built" and the Input of this task doesn't change, then it will stay up-to-date.
OR, perhaps I got what you're doing. You have your own gradle plugin that can be shared across multiple & different gradle projects. They depend on your plugin and you want to avoid duplicate compilations of the same thing, I get it.
Question: Can't you pre-built this "same thing" and include it as part of your Gradle Plugin?
If not, then you can check how we're doing it with NativeDistributionCommonization
TL;DR: we store it in global directory and have task that is doing simillar thing as I described above.
But for UP-TO-DATE checks we have to create our own and solve concurrency problem with "file lock".
But that is considered as not so good approach. and it is better to prebuilt & publish.François
02/21/2025, 9:56 AMFrançois
02/21/2025, 10:01 AMFrançois
02/21/2025, 1:20 PMCannot change dependencies of dependency configuration ':example:iosSimulatorArm64MainApi' after it has been included in dependency resolution.
The cinterop tasks can do it, I would like to know how...Anton Lakotka [JB]
02/21/2025, 1:29 PMFrançois
02/21/2025, 1:45 PMfreeCompilerArgs.addAll("-library", klib.absolutePath)
But, the klib is not indexed by the IDE, there are missing in the project.Vampire
02/21/2025, 2:59 PMJust add it as file dependencyThat's generally almost always a bad idea. File dependencies have quite some drawbacks, including not being listed in things like build scans or the
dependencies
output.
The prebuilt klib is the cinterop tasks output file, where I don’t want to call if the klib is already present outside of the gradle tasks.I don't understand all you said as I don't know what cinterop and cocoapods and so on are. But where is that task you are trying to provide prebuilt result? And what is happening with that task? Can you maybe just replace that tasks action with an own action that copies the pre-built file to the output file location?
François
02/21/2025, 4:14 PMVampire
02/21/2025, 6:24 PMFrançois
02/22/2025, 8:58 AMVampire
02/22/2025, 11:32 AM