Add linkOnly mode for pods

^KT-41830 Verification Pending

Merge-request: KT-MR-8302
Merged-by: Artem Daugel-Dauge <Artem.Daugel-Dauge@jetbrains.com>
This commit is contained in:
Artem Daugel-Dauge
2023-01-17 18:32:54 +00:00
committed by Space Team
parent 71486a321c
commit a24119858f
3 changed files with 90 additions and 2 deletions
@@ -1088,6 +1088,58 @@ class CocoaPodsIT : BaseGradleIT() {
assertContains(manifestLines, "linkerOpts=-framework AFNetworking")
}
@Test
fun testLinkOnlyPods() = with(project) {
gradleBuildScript().appendToCocoapodsBlock("""
pod("AFNetworking") { linkOnly = true }
pod("SSZipArchive", linkOnly = true)
pod("SDWebImage/Core")
""".trimIndent())
build(":linkPodDebugFrameworkIOS", "-Pkotlin.native.cocoapods.generate.wrapper=true") {
assertSuccessful()
assertTasksExecuted(":podBuildAFNetworkingIphonesimulator")
assertTasksExecuted(":podBuildSDWebImageIphonesimulator")
assertTasksExecuted(":podBuildSSZipArchiveIphonesimulator")
assertTasksExecuted(":cinteropSDWebImageIOS")
assertTasksNotRegistered(":cinteropAFNetworkingIOS")
assertTasksNotRegistered(":cinteropSSZipArchiveIOS")
assertContains("""
| -linker-option
| -framework
| -linker-option
| AFNetworking
""".trimMargin())
assertContains("""
| -linker-option
| -framework
| -linker-option
| SSZipArchive
""".trimMargin())
}
}
@Test
fun testUsageLinkOnlyWithStaticFrameworkProducesMessage() = with(project) {
gradleBuildScript().appendToCocoapodsBlock("""
framework {
isStatic = true
}
pod("AFNetworking") { linkOnly = true }
""".trimIndent())
build(":linkPodDebugFrameworkIOS", "-Pkotlin.native.cocoapods.generate.wrapper=true") {
assertSuccessful()
assertContains("Dependency on 'AFNetworking' with option 'linkOnly=true' is unused for building static frameworks")
}
}
// test configuration phase
private class CustomHooks {
@@ -157,9 +157,19 @@ abstract class CocoapodsExtension @Inject constructor(private val project: Proje
/**
* Add a CocoaPods dependency to the pod built from this project.
*
* @param linkOnly designates that the pod will be used only for dynamic framework linking and not for the cinterops. Code from it won't
* be accessible for referencing from Kotlin but its native symbols will be visible while linking the framework.
*/
@JvmOverloads
fun pod(name: String, version: String? = null, path: File? = null, moduleName: String = name.asModuleName(), headers: String? = null) {
fun pod(
name: String,
version: String? = null,
path: File? = null,
moduleName: String = name.asModuleName(),
headers: String? = null,
linkOnly: Boolean = false,
) {
// Empty string will lead to an attempt to create two podDownload tasks.
// One is original podDownload and second is podDownload + pod.name
require(name.isNotEmpty()) { "Please provide not empty pod name to avoid ambiguity" }
@@ -197,6 +207,7 @@ abstract class CocoapodsExtension @Inject constructor(private val project: Proje
this.headers = headers
this.version = version
source = podSource?.let { Path(it) }
this.linkOnly = linkOnly
}
)
}
@@ -276,6 +287,16 @@ abstract class CocoapodsExtension @Inject constructor(private val project: Proje
@get:Internal
var packageName: String = "cocoapods.$moduleName"
/**
* Designates that the pod will be used only for dynamic framework linking and not for the cinterops. Code from it won't be
* accessible for referencing from Kotlin but its native symbols will be visible while linking the framework.
*
* For static frameworks adding this flag is equivalent to removing the pod dependency entirely (because pods are not used for
* static framework linking).
*/
@get:Input
var linkOnly: Boolean = false
@Input
override fun getName(): String = name
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.gradle.targets.native.cocoapods.kotlinArtifactsPodsp
import org.jetbrains.kotlin.gradle.targets.native.tasks.*
import org.jetbrains.kotlin.gradle.targets.native.tasks.artifact.kotlinArtifactsExtension
import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.asValidTaskName
import org.jetbrains.kotlin.gradle.utils.filesProvider
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
@@ -297,7 +298,7 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
val moduleNames = mutableSetOf<String>()
cocoapodsExtension.pods.all { pod ->
if (moduleNames.contains(pod.moduleName)) {
if (pod.linkOnly || moduleNames.contains(pod.moduleName)) {
return@all
}
moduleNames.add(pod.moduleName)
@@ -743,6 +744,19 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
}
}
private fun checkLinkOnlyNotUsedWithStaticFramework(project: Project, cocoapodsExtension: CocoapodsExtension) {
project.runProjectConfigurationHealthCheckWhenEvaluated {
cocoapodsExtension.pods.all { pod ->
if (pod.linkOnly && cocoapodsExtension.podFrameworkIsStatic.get()) {
logger.warn("""
Dependency on '${pod.name}' with option 'linkOnly=true' is unused for building static frameworks.
When using static linkage you will need to provide all dependencies for linking the framework into a final application.
""".trimIndent())
}
}
}
}
override fun apply(project: Project): Unit = with(project) {
pluginManager.withPlugin("kotlin-multiplatform") {
@@ -774,6 +788,7 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
}
createInterops(project, kotlinExtension, cocoapodsExtension)
configureLinkingOptions(project, cocoapodsExtension)
checkLinkOnlyNotUsedWithStaticFramework(project, cocoapodsExtension)
}
}