[Gradle] Migrate Xcode/CocoaPods warnings to the new diagnostics infra + elevate deprecation of useLibraries

^KT-59313 Verification Pending
^KT-58519 Verification Pending
This commit is contained in:
Artem Daugel-Dauge
2023-06-20 17:22:20 +02:00
committed by Space Team
parent 67c19b00e0
commit 6861591840
15 changed files with 208 additions and 132 deletions
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.native
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.targets.native.cocoapods.CocoapodsPluginDiagnostics
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.condition.OS
@@ -27,7 +28,7 @@ class AppleFrameworkNonMacIT : KGPBaseTest() {
)
build("podImport", buildOptions = buildOptions) {
assertOutputContains("Kotlin Cocoapods Plugin is fully supported on mac machines only. Gradle tasks that can not run on non-mac hosts will be skipped.")
assertHasDiagnostic(CocoapodsPluginDiagnostics.UnsupportedOs)
}
}
}
@@ -10,7 +10,6 @@ import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.request.*
import io.ktor.http.*
import io.ktor.util.*
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
@@ -21,6 +20,7 @@ import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Compan
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_IMPORT_TASK_NAME
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_SETUP_BUILD_TASK_NAME
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_SPEC_TASK_NAME
import org.jetbrains.kotlin.gradle.targets.native.cocoapods.CocoapodsPluginDiagnostics
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.util.assertProcessRunResult
import org.jetbrains.kotlin.gradle.util.capitalize
@@ -435,21 +435,11 @@ class CocoaPodsGitIT : KGPBaseTest() {
@DisplayName("Checking useLibraries mode")
@GradleTest
fun testUseLibrariesMode(gradleVersion: GradleVersion) {
nativeProjectWithCocoapodsAndIosAppPodFile(gradleVersion = gradleVersion) {
buildGradleKts.addCocoapodsBlock("useLibraries()")
buildGradleKts.addPod("AFNetworking", configuration = "headers = \"AFNetworking/AFNetworking.h\"")
testImport()
}
}
@DisplayName("Checking that useLibraries mode warns when pod is added without headers specified")
@GradleTest
fun testUseLibrariesModeWarnsWhenPodIsAddedWithoutHeadersSpecified(gradleVersion: GradleVersion) {
nativeProjectWithCocoapodsAndIosAppPodFile(gradleVersion = gradleVersion) {
buildGradleKts.addCocoapodsBlock("useLibraries()")
buildGradleKts.addPod("AFNetworking")
nativeProjectWithCocoapodsAndIosAppPodFile(projectName = "native-cocoapods-template-groovy", gradleVersion = gradleVersion) {
buildGradle.addCocoapodsBlock("useLibraries()".trimIndent())
buildGradle.addPod("AFNetworking", configuration = "headers = \"AFNetworking/AFNetworking.h\"")
testImport {
assertOutputContains("w: Pod 'AFNetworking' should have 'headers' property specified when using 'useLibraries()'")
assertHasDiagnostic(CocoapodsPluginDiagnostics.UseLibrariesUsed)
}
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.DUMMY_FRAMEWORK_TASK_NAME
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_IMPORT_TASK_NAME
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_SPEC_TASK_NAME
import org.jetbrains.kotlin.gradle.targets.native.cocoapods.CocoapodsPluginDiagnostics
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.util.assertProcessRunResult
import org.jetbrains.kotlin.gradle.util.replaceText
@@ -85,19 +86,6 @@ class CocoaPodsIT : KGPBaseTest() {
}
}
@DisplayName("Checking the warning about using deprecated podspec path")
@GradleTest
fun warnIfDeprecatedPodspecPathIsUsed(gradleVersion: GradleVersion) {
nativeProjectWithCocoapodsAndIosAppPodFile(cocoapodsSingleKtPod, gradleVersion) {
build(":kotlin-library:tasks") {
assertOutputContains(
listOf("Deprecated DSL found on ${projectPath.toRealPath().absolutePathString()}", "kotlin-library", "build.gradle.kts")
.joinToString(separator = File.separator)
)
}
}
}
@DisplayName("Build with error if project version is not specified for cocoapods")
@GradleTest
fun errorIfVersionIsNotSpecified(gradleVersion: GradleVersion) {
@@ -691,7 +679,7 @@ class CocoaPodsIT : KGPBaseTest() {
""".trimIndent()
)
buildWithCocoapodsWrapper(":linkPodDebugFrameworkIOS") {
assertOutputContains("Dependency on 'AFNetworking' with option 'linkOnly=true' is unused for building static frameworks")
assertHasDiagnostic(CocoapodsPluginDiagnostics.LinkOnlyUsedWithStaticFramework)
}
}
}
@@ -704,9 +692,9 @@ class CocoaPodsIT : KGPBaseTest() {
}
}
@DisplayName("Configuration fails when trying to depend on non-declared pod")
@DisplayName("Error reported when trying to depend on non-declared pod")
@GradleTest
fun testConfigurationFailsWhenTryingToDependOnNonDeclaredPod(gradleVersion: GradleVersion) {
fun testErrorReportedWhenTryingToDependOnNonDeclaredPod(gradleVersion: GradleVersion) {
nativeProjectWithCocoapodsAndIosAppPodFile(cocoapodsDependantPodsProjectName, gradleVersion) {
buildGradleKts.addCocoapodsBlock(
"""
@@ -720,15 +708,15 @@ class CocoaPodsIT : KGPBaseTest() {
)
)
buildAndFail(":help", buildOptions = buildOptions) {
build(":help", buildOptions = buildOptions) {
assertOutputContains("Couldn't find declaration of pod 'JBNonExistent' (interop-binding dependency of pod 'Foo')")
}
}
}
@DisplayName("Configuration fails when dependant pods are in the wrong order")
@DisplayName("Error reported when dependant pods are in the wrong order")
@GradleTest
fun testConfigurationFailsWhenDependantPodsAreInTheWrongOrder(gradleVersion: GradleVersion) {
fun testErrorReportedWhenDependantPodsAreInTheWrongOrder(gradleVersion: GradleVersion) {
nativeProjectWithCocoapodsAndIosAppPodFile(cocoapodsDependantPodsProjectName, gradleVersion) {
buildGradleKts.addCocoapodsBlock(
"""
@@ -743,15 +731,15 @@ class CocoaPodsIT : KGPBaseTest() {
)
)
buildAndFail(":help", buildOptions = buildOptions) {
assertOutputContains("Couldn't find declaration of pod 'Bar' (interop-binding dependency of pod 'Foo')")
build(":help", buildOptions = buildOptions) {
assertHasDiagnostic(CocoapodsPluginDiagnostics.InteropBindingUnknownDependency)
}
}
}
@DisplayName("Configuration fails when pod depends on itself")
@DisplayName("Error reported when pod depends on itself")
@GradleTest
fun testConfigurationFailsWhenPodDependsOnItself(gradleVersion: GradleVersion) {
fun testErrorReportedWhenPodDependsOnItself(gradleVersion: GradleVersion) {
nativeProjectWithCocoapodsAndIosAppPodFile(cocoapodsDependantPodsProjectName, gradleVersion) {
buildGradleKts.addCocoapodsBlock(
"""
@@ -765,8 +753,8 @@ class CocoaPodsIT : KGPBaseTest() {
)
)
buildAndFail(":help", buildOptions = buildOptions) {
assertOutputContains("Pod 'Foo' has an interop-binding dependency on itself")
build(":help", buildOptions = buildOptions) {
assertHasDiagnostic(CocoapodsPluginDiagnostics.InteropBindingSelfDependency)
}
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.gradle.native
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.util.replaceFirst
import org.jetbrains.kotlin.gradle.util.replaceText
@@ -69,7 +70,7 @@ class XCFrameworkIT : KGPBaseTest() {
assertTasksExecuted(":shared:assembleOtherDebugXCFramework")
assertDirectoryInProjectExists("shared/build/XCFrameworks/debug/other.xcframework")
assertDirectoryInProjectExists("shared/build/XCFrameworks/debug/other.xcframework/ios-arm64/dSYMs/shared.framework.dSYM")
assertOutputContains("Name of XCFramework 'other' differs from inner frameworks name 'shared'! Framework renaming is not supported yet")
assertHasDiagnostic(KotlinToolingDiagnostics.XCFrameworkDifferentInnerFrameworksName)
}
}
}
@@ -20,8 +20,7 @@ kotlin {
cocoapods {
summary = "CocoaPods test library"
homepage = "https://github.com/JetBrains/kotlin"
// test warnIfDeprecatedPodspecPathIsUsed depends on deprecated api usage
pod("pod_dependency", "1.0", project.file("../pod_dependency/pod_dependency.podspec"))
pod("pod_dependency", "1.0", project.file("../pod_dependency"))
pod("subspec_dependency/Core", "1.0", project.file("../subspec_dependency"))
podfile = project.file("../ios-app/Podfile")
@@ -506,6 +506,20 @@ object KotlinToolingDiagnostics {
)
}
object XCFrameworkDifferentInnerFrameworksName : ToolingDiagnosticFactory(WARNING) {
operator fun invoke(xcFramework: String, innerFrameworks: String) = build(
"Name of XCFramework '$xcFramework' differs from inner frameworks name '$innerFrameworks'! Framework renaming is not supported yet"
)
}
object UnknownAppleFrameworkBuildType : ToolingDiagnosticFactory(WARNING) {
operator fun invoke(envConfiguration: String) = build(
"""
Unable to detect Kotlin framework build type for CONFIGURATION=$envConfiguration automatically.
Specify 'KOTLIN_FRAMEWORK_BUILD_TYPE' to 'debug' or 'release'
""".trimIndent()
)
}
}
private fun String.indentLines(nSpaces: Int = 4, skipFirstLine: Boolean = true): String {
@@ -14,6 +14,8 @@ import org.gradle.api.provider.Provider
import org.gradle.api.tasks.*
import org.gradle.process.ExecOperations
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeBinaryContainer
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic
import org.jetbrains.kotlin.gradle.plugin.mpp.Framework
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.gradle.plugin.mpp.enabledOnCurrentHost
@@ -106,10 +108,7 @@ private fun Project.registerAssembleAppleFrameworkTask(framework: Framework): Ta
if (envBuildType == null || envTargets.isEmpty() || envFrameworkSearchDir == null) {
val envConfiguration = System.getenv("CONFIGURATION")
if (envTargets.isNotEmpty() && envConfiguration != null) {
logger.warn(
"Unable to detect Kotlin framework build type for CONFIGURATION=$envConfiguration automatically. " +
"Specify 'KOTLIN_FRAMEWORK_BUILD_TYPE' to 'debug' or 'release'"
)
project.reportDiagnostic(KotlinToolingDiagnostics.UnknownAppleFrameworkBuildType(envConfiguration))
} else {
logger.debug("Not registering $frameworkTaskName, since not called from Xcode")
}
@@ -8,12 +8,13 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.apple
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.file.ProjectLayout
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.*
import org.gradle.process.ExecOperations
import org.jetbrains.kotlin.gradle.plugin.cocoapods.asValidFrameworkName
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.plugin.diagnostics.UsesKotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.plugin.mpp.Framework
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.gradle.tasks.*
@@ -23,6 +24,7 @@ import org.jetbrains.kotlin.konan.target.KonanTarget
import java.io.File
import javax.inject.Inject
@Suppress("unused") // used through .values() call
internal enum class AppleTarget(
val targetName: String,
val targets: List<KonanTarget>
@@ -147,7 +149,7 @@ abstract class XCFrameworkTask
internal constructor(
private val execOperations: ExecOperations,
private val projectLayout: ProjectLayout,
) : DefaultTask() {
) : DefaultTask(), UsesKotlinToolingDiagnostics {
init {
onlyIf { HostManager.hostIsMac }
}
@@ -238,9 +240,10 @@ internal constructor(
frameworks.joinToString("\n") { it.file.path })
}
if (name != xcfName) {
logger.warn(
"Name of XCFramework '$rawXcfName' differs from inner frameworks name '$name'! Framework renaming is not supported yet"
)
toolingDiagnosticsCollector.get().report(this, KotlinToolingDiagnostics.XCFrameworkDifferentInnerFrameworksName(
xcFramework = rawXcfName,
innerFrameworks = name,
))
}
}
@@ -14,8 +14,10 @@ import org.gradle.api.tasks.*
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension.CocoapodsDependency.PodLocation.*
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_FRAMEWORK_PREFIX
import org.jetbrains.kotlin.gradle.plugin.diagnostics.kotlinToolingDiagnosticsCollector
import org.jetbrains.kotlin.gradle.plugin.mpp.Framework
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.gradle.targets.native.cocoapods.CocoapodsPluginDiagnostics
import org.jetbrains.kotlin.gradle.utils.getFile
import java.io.File
import java.net.URI
@@ -49,18 +51,12 @@ abstract class CocoapodsExtension @Inject constructor(private val project: Proje
/**
* Setup plugin to generate synthetic xcodeproj compatible with static libraries
*
* This option is not supported and scheduled to be removed. If you are using this please
* file an issue with your case to [https://kotl.in/issue](https://kotl.in/issue)
*/
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("This option is not supported and scheduled to be removed")
@Deprecated("'useLibraries' mode is removed", level = DeprecationLevel.ERROR)
fun useLibraries() {
useLibraries = true
project.kotlinToolingDiagnosticsCollector.report(project, CocoapodsPluginDiagnostics.UseLibrariesUsed())
}
internal var useLibraries: Boolean = false
/**
* Configure name of the pod built from this project.
*/
@@ -169,31 +165,6 @@ abstract class CocoapodsExtension @Inject constructor(private val project: Proje
// 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" }
var podSource = path
if (path != null && !path.isDirectory) {
val pattern = "\\W*pod(.*\"${name}\".*)".toRegex()
val buildScript = project.buildFile
val lines = buildScript.readLines()
val lineNumber = lines.indexOfFirst { pattern.matches(it) }
val warnMessage = if (lineNumber != -1) run {
val lineContent = lines[lineNumber].trimIndent()
val newContent = lineContent.replace(path.name, "")
"""
|Deprecated DSL found on ${buildScript.absolutePath}${File.pathSeparator}${lineNumber + 1}:
|Found: "$lineContent"
|Expected: "$newContent"
|Please, change the path to avoid this warning.
|
""".trimMargin()
} else
"""
|Deprecated DSL is used for pod "$name".
|Please, change its path from ${path.path} to ${path.parentFile.path}
|
""".trimMargin()
project.logger.warn(warnMessage)
podSource = path.parentFile
}
addToPods(
project.objects.newInstance(
CocoapodsDependency::class.java,
@@ -202,7 +173,7 @@ abstract class CocoapodsExtension @Inject constructor(private val project: Proje
).apply {
this.headers = headers
this.version = version
source = podSource?.let { Path(it) }
source = path?.let(::Path)
this.linkOnly = linkOnly
}
)
@@ -0,0 +1,55 @@
/*
* 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.
*/
package org.jetbrains.kotlin.gradle.targets.native.cocoapods
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic.Severity.ERROR
import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic.Severity.WARNING
import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnosticFactory
@InternalKotlinGradlePluginApi // used in integration tests
object CocoapodsPluginDiagnostics {
object DeprecatedPropertiesUsed : ToolingDiagnosticFactory(WARNING) {
operator fun invoke(usedDeprecatedProperties: List<String>) = build(
"""
|Properties
| ${usedDeprecatedProperties.joinToString(separator = "\n| ")}
|are not supported and will be ignored since CocoaPods plugin generates all required properties automatically.
""".trimMargin()
)
}
object LinkOnlyUsedWithStaticFramework : ToolingDiagnosticFactory(WARNING) {
operator fun invoke(podName: String) = build(
"""
Dependency on '$podName' 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()
)
}
object UnsupportedOs : ToolingDiagnosticFactory(WARNING) {
operator fun invoke() = build(
"""
Kotlin CocoaPods Plugin is fully supported on MacOS machines only. Gradle tasks that can not run on non-mac hosts will be skipped.
""".trimIndent()
)
}
object UseLibrariesUsed : ToolingDiagnosticFactory(ERROR) {
operator fun invoke() = build("'useLibraries' mode is removed")
}
object InteropBindingSelfDependency : ToolingDiagnosticFactory(ERROR) {
operator fun invoke(podName: String) = build("Pod '$podName' has an interop-binding dependency on itself")
}
object InteropBindingUnknownDependency : ToolingDiagnosticFactory(ERROR) {
operator fun invoke(podName: String, dependencyName: String) = build("Couldn't find declaration of pod '$dependencyName' (interop-binding dependency of pod '${podName}')")
}
}
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.addExtension
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension.CocoapodsDependency
import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic
import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnosticOncePerProject
import org.jetbrains.kotlin.gradle.plugin.ide.Idea222Api
import org.jetbrains.kotlin.gradle.plugin.ide.ideaImportDependsOn
import org.jetbrains.kotlin.gradle.plugin.mpp.*
@@ -30,6 +32,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.apple.*
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.AppleSdk
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.AppleTarget
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
import org.jetbrains.kotlin.gradle.targets.native.cocoapods.CocoapodsPluginDiagnostics
import org.jetbrains.kotlin.gradle.targets.native.cocoapods.KotlinArtifactsPodspecExtension
import org.jetbrains.kotlin.gradle.targets.native.cocoapods.kotlinArtifactsPodspecExtension
import org.jetbrains.kotlin.gradle.targets.native.tasks.*
@@ -243,22 +246,6 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
val platforms = project.findProperty(PLATFORM_PROPERTY)?.toString()?.split(",", " ")?.filter { it.isNotBlank() }
val archs = project.findProperty(ARCHS_PROPERTY)?.toString()?.split(",", " ")?.filter { it.isNotBlank() }
if (
project.findProperty(CFLAGS_PROPERTY) != null ||
project.findProperty(FRAMEWORK_PATHS_PROPERTY) != null ||
project.findProperty(HEADER_PATHS_PROPERTY) != null
) {
logger.warn(
"""
Properties
kotlin.native.cocoapods.cflags
kotlin.native.cocoapods.paths.frameworks
kotlin.native.cocoapods.paths.headers
are not supported and will be ignored since Cocoapods plugin generates all required properties automatically.
""".trimIndent()
)
}
if (platforms == null || archs == null) {
check(project.findProperty(TARGET_PROPERTY) == null) {
"""
@@ -298,6 +285,15 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
}
}
private fun reportDeprecatedPropertiesUsage(project: Project) {
listOf(CFLAGS_PROPERTY, FRAMEWORK_PATHS_PROPERTY, HEADER_PATHS_PROPERTY)
.filter { project.findProperty(it) != null }
.takeIf { it.isNotEmpty() }
?.let {
project.reportDiagnostic(CocoapodsPluginDiagnostics.DeprecatedPropertiesUsed(it))
}
}
private fun createInterops(
project: Project,
kotlinExtension: KotlinMultiplatformExtension,
@@ -315,7 +311,6 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
lowerCamelCaseName("generateDef", pod.moduleName).asValidTaskName()
) {
it.pod.set(pod)
it.useLibraries.set(cocoapodsExtension.useLibraries)
it.description = "Generates a def file for CocoaPods dependencies with module ${pod.moduleName}"
// This task is an implementation detail so we don't add it in any group
// to avoid showing it in the `tasks` output.
@@ -374,11 +369,15 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
dependencyName: String,
) {
if (pod.name == dependencyName) {
error("Pod '${pod.name}' has an interop-binding dependency on itself")
project.reportDiagnosticOncePerProject(CocoapodsPluginDiagnostics.InteropBindingSelfDependency(pod.name))
return
}
val dependencyPod = cocoapodsExtension.pods.findByName(dependencyName)
?: error("Couldn't find declaration of pod '$dependencyName' (interop-binding dependency of pod '${pod.name}')")
?: run {
project.reportDiagnosticOncePerProject(CocoapodsPluginDiagnostics.InteropBindingUnknownDependency(pod.name, dependencyName))
return
}
val dependencyTaskName = cinterops.getByName(dependencyPod.moduleName).interopProcessingTaskName
val dependencyTask = project.tasks.named<CInteropProcess>(dependencyTaskName)
@@ -520,7 +519,6 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
task.description = "Сreates a synthetic Xcode project to retrieve CocoaPods dependencies"
task.podspec.set(podspecTaskProvider.map { it.outputFile })
task.podName.set(project.provider { cocoapodsExtension.name })
task.useLibraries.set(project.provider { cocoapodsExtension.useLibraries })
task.specRepos.set(project.provider { cocoapodsExtension.specRepos })
task.family.set(family)
task.platformSettings.set(platformSettings)
@@ -799,10 +797,7 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
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())
project.reportDiagnostic(CocoapodsPluginDiagnostics.LinkOnlyUsedWithStaticFramework(pod.name))
}
}
}
@@ -854,12 +849,10 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
registerPodPublishTasks(project, cocoapodsExtension)
if (!HostManager.hostIsMac) {
logger.warn(
"""
Kotlin Cocoapods Plugin is fully supported on mac machines only. Gradle tasks that can not run on non-mac hosts will be skipped.
""".trimIndent()
)
reportDiagnostic(CocoapodsPluginDiagnostics.UnsupportedOs())
}
reportDeprecatedPropertiesUsage(project)
createInterops(project, kotlinExtension, cocoapodsExtension)
configureLinkingOptions(project, cocoapodsExtension)
checkLinkOnlyNotUsedWithStaticFramework(project, cocoapodsExtension)
@@ -11,7 +11,6 @@ import org.gradle.api.file.ProjectLayout
import org.gradle.api.file.RegularFile
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Nested
import org.gradle.api.tasks.OutputFile
@@ -31,9 +30,6 @@ abstract class DefFileTask @Inject constructor(projectLayout: ProjectLayout) : D
@get:Nested
abstract val pod: Property<CocoapodsDependency>
@get:Input
abstract val useLibraries: Property<Boolean>
@get:OutputFile
val defFile: Provider<RegularFile> = projectLayout.cocoapodsBuildDirs.defs.map { it.file("${pod.get().moduleName}.def") }
@@ -51,12 +47,6 @@ abstract class DefFileTask @Inject constructor(projectLayout: ProjectLayout) : D
with(pod.get()) {
when {
headers != null -> appendLine("headers = $headers")
useLibraries.get() -> logger.warn(
"""
w: Pod '$moduleName' should have 'headers' property specified when using 'useLibraries()'.
Otherwise code from this pod won't be accessible from Kotlin.
""".trimIndent()
)
else -> {
appendLine("modules = $moduleName")
@@ -39,9 +39,6 @@ abstract class PodGenTask @Inject constructor(projectLayout: ProjectLayout) : Co
@get:Input
internal abstract val podName: Property<String>
@get:Input
internal abstract val useLibraries: Property<Boolean>
@get:Input
internal abstract val family: Property<Family>
@@ -80,9 +77,8 @@ abstract class PodGenTask @Inject constructor(projectLayout: ProjectLayout) : Co
}
appendLine("target '${family.platformLiteral}' do")
if (useLibraries.get().not()) {
appendLine("\tuse_frameworks!")
}
appendLine("\tuse_frameworks!")
val settings = platformSettings.get()
val deploymentTarget = settings.deploymentTarget
if (deploymentTarget != null) {
@@ -0,0 +1,61 @@
/*
* 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
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.CFLAGS_PROPERTY
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.FRAMEWORK_PATHS_PROPERTY
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.HEADER_PATHS_PROPERTY
import org.jetbrains.kotlin.gradle.targets.native.cocoapods.CocoapodsPluginDiagnostics
import org.jetbrains.kotlin.gradle.util.*
import org.jetbrains.kotlin.gradle.util.assertContainsDiagnostic
import org.jetbrains.kotlin.konan.target.HostManager
import org.junit.Assume
import org.junit.Test
class CocoapodsUnitTests {
@Test
fun `warning is reported on non-mac machines`() {
Assume.assumeTrue(!HostManager.hostIsMac)
buildProjectWithCocoapods {
assertContainsDiagnostic(CocoapodsPluginDiagnostics.UnsupportedOs)
}
}
@Test
fun `warning is reported when using deprecated properties`() {
buildProjectWithMPP {
propertiesExtension.set(CFLAGS_PROPERTY, "cflags value")
applyCocoapodsPlugin()
assertContainsDiagnostic(CocoapodsPluginDiagnostics.DeprecatedPropertiesUsed)
}
buildProjectWithMPP {
propertiesExtension.set(HEADER_PATHS_PROPERTY, "header paths value")
applyCocoapodsPlugin()
assertContainsDiagnostic(CocoapodsPluginDiagnostics.DeprecatedPropertiesUsed)
}
buildProjectWithMPP {
propertiesExtension.set(FRAMEWORK_PATHS_PROPERTY, "framework paths value")
applyCocoapodsPlugin()
assertContainsDiagnostic(CocoapodsPluginDiagnostics.DeprecatedPropertiesUsed)
}
buildProjectWithMPP {
propertiesExtension.set(FRAMEWORK_PATHS_PROPERTY, "framework paths value")
propertiesExtension.set(HEADER_PATHS_PROPERTY, "header paths value")
applyCocoapodsPlugin()
assertContainsDiagnostic(CocoapodsPluginDiagnostics.DeprecatedPropertiesUsed(listOf(FRAMEWORK_PATHS_PROPERTY, HEADER_PATHS_PROPERTY)))
}
}
}
@@ -19,6 +19,8 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_COMPATIBILITY_METADATA_VARIANT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_INTRANSITIVE_METADATA_CONFIGURATION
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension
import org.jetbrains.kotlin.gradle.plugin.getExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
import org.jetbrains.kotlin.gradle.unitTests.kpm.applyKpmPlugin
@@ -50,6 +52,11 @@ fun buildProjectWithJvm(projectBuilder: ProjectBuilder.() -> Unit = {}, code: Pr
code()
}
fun buildProjectWithCocoapods(projectBuilder: ProjectBuilder.() -> Unit = {}, code: Project.() -> Unit = {}) = buildProject(projectBuilder) {
project.applyCocoapodsPlugin()
code()
}
fun Project.applyKotlinJvmPlugin() {
project.plugins.apply(KotlinPluginWrapper::class.java)
}
@@ -87,6 +94,14 @@ fun Project.applyMultiplatformPlugin(): KotlinMultiplatformExtension {
return extensions.getByName("kotlin") as KotlinMultiplatformExtension
}
fun Project.applyCocoapodsPlugin(): CocoapodsExtension {
val kotlinExtension = applyMultiplatformPlugin()
plugins.apply("org.jetbrains.kotlin.native.cocoapods")
return kotlinExtension.getExtension<CocoapodsExtension>("cocoapods")!!.also {
it.version = "1.0"
}
}
val Project.propertiesExtension: ExtraPropertiesExtension
get() = extensions.getByType(ExtraPropertiesExtension::class.java)