diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 1e0ef2038f5..8f33f996915 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -2978,18 +2978,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3330,6 +3348,12 @@
+
+
+
+
+
+
@@ -3372,12 +3396,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3390,6 +3432,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3408,6 +3462,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3420,6 +3486,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3574,6 +3670,12 @@
+
+
+
+
+
+
@@ -3598,6 +3700,12 @@
+
+
+
+
+
+
@@ -3622,6 +3730,12 @@
+
+
+
+
+
+
@@ -3646,6 +3760,12 @@
+
+
+
+
+
+
@@ -3682,6 +3802,12 @@
+
+
+
+
+
+
@@ -3706,6 +3832,12 @@
+
+
+
+
+
+
@@ -3736,6 +3868,12 @@
+
+
+
+
+
+
@@ -3760,24 +3898,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3979,12 +4153,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -6415,12 +6601,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -6433,6 +6631,12 @@
+
+
+
+
+
+
@@ -6451,6 +6655,12 @@
+
+
+
+
+
+
@@ -6463,12 +6673,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -6487,6 +6709,12 @@
+
+
+
+
+
+
@@ -6499,24 +6727,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -7065,6 +7317,12 @@
+
+
+
+
+
+
@@ -7939,6 +8197,12 @@
+
+
+
+
+
+
diff --git a/gradle/versions.properties b/gradle/versions.properties
index 228ad4c3204..4d208409389 100644
--- a/gradle/versions.properties
+++ b/gradle/versions.properties
@@ -48,12 +48,12 @@ versions.kotlinx-coroutines-core=1.5.0
versions.kotlinx-metadata-jvm=0.6.0
versions.kotlinx-metadata-klib=0.0.1-dev-10
versions.kotlinx-serialization-json=1.3.3
-versions.ktor-network=1.4.0
-versions.ktor-utils=1.4.0
-versions.ktor-server-test-host=1.1.5
-versions.ktor-server-core=1.6.7
-versions.ktor-server-netty=1.6.7
-versions.ktor-client-mock=1.6.7
+versions.ktor-network=2.0.2
+versions.ktor-utils=2.0.2
+versions.ktor-server-test-host=2.0.2
+versions.ktor-server-core=2.0.2
+versions.ktor-server-netty=2.0.2
+versions.ktor-client-mock=2.0.2
versions.ktor-client-core=2.0.2
versions.ktor-client-cio=2.0.2
versions.ktor-client-websockets=2.0.2
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts
index cade05db554..2fc45d4f23b 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts
@@ -87,6 +87,7 @@ dependencies {
testImplementation(commonDependency("org.jetbrains.intellij.deps", "trove4j"))
testImplementation(commonDependency("io.ktor", "ktor-server-test-host"))
testImplementation(commonDependency("io.ktor", "ktor-server-core"))
+ testImplementation(commonDependency("io.ktor", "ktor-client-cio"))
testImplementation(commonDependency("io.ktor", "ktor-server-netty"))
testImplementation(commonDependency("io.ktor", "ktor-client-mock"))
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildStatisticsWithKtorIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildStatisticsWithKtorIT.kt
index 9af5ac93385..20c4532b156 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildStatisticsWithKtorIT.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildStatisticsWithKtorIT.kt
@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.gradle
import com.google.gson.Gson
import com.google.gson.JsonObject
import com.google.gson.JsonParser
-import io.ktor.application.*
import io.ktor.http.*
-import io.ktor.request.*
-import io.ktor.response.*
-import io.ktor.routing.*
+import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
+import io.ktor.server.request.*
+import io.ktor.server.response.*
+import io.ktor.server.routing.*
import io.ktor.util.*
import io.ktor.util.collections.*
import org.gradle.util.GradleVersion
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/AppleFrameworkIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/AppleFrameworkIT.kt
index b5125274e96..1b6716035e5 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/AppleFrameworkIT.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/AppleFrameworkIT.kt
@@ -9,6 +9,7 @@ import org.gradle.api.JavaVersion
import org.gradle.testkit.runner.BuildResult
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.testbase.*
+import org.jetbrains.kotlin.gradle.util.replaceText
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.condition.OS
import kotlin.io.path.absolutePathString
@@ -574,6 +575,8 @@ class AppleFrameworkIT : KGPBaseTest() {
)
}
+ subProject("iosApp").buildGradleKts.replaceText("", "\"${TestVersions.AppleGradlePlugin.V222_0_21}\"")
+
build(*dependencyInsight("iosAppIosX64DebugImplementation")) {
assertContainsVariant("mainDynamicDebugFrameworkIos")
}
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsGitIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsGitIT.kt
new file mode 100644
index 00000000000..c98ba998b52
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsGitIT.kt
@@ -0,0 +1,509 @@
+/*
+ * 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.native
+
+
+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
+import org.gradle.testkit.runner.BuildResult
+import org.gradle.util.GradleVersion
+import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_BUILD_TASK_NAME
+import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_GEN_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_INSTALL_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.testbase.*
+import org.jetbrains.kotlin.gradle.util.assertProcessRunResult
+import org.jetbrains.kotlin.gradle.util.capitalize
+import org.jetbrains.kotlin.gradle.util.replaceText
+import org.jetbrains.kotlin.gradle.util.runProcess
+import org.junit.jupiter.api.Assumptions
+import org.junit.jupiter.api.BeforeAll
+import org.junit.jupiter.api.DisplayName
+import org.junit.jupiter.api.condition.OS
+import java.nio.file.Path
+import java.util.*
+import kotlin.io.path.absolutePathString
+import kotlin.io.path.readText
+import kotlin.test.assertTrue
+
+@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC])
+@DisplayName("Git connected K/N tests with cocoapods")
+@NativeGradlePluginTests
+@GradleTestVersions(minVersion = TestVersions.Gradle.G_7_0)
+@OptIn(EnvironmentalVariablesOverride::class)
+class CocoaPodsGitIT : KGPBaseTest() {
+
+ override val defaultBuildOptions = super.defaultBuildOptions.copy(
+ nativeOptions = super.defaultBuildOptions.nativeOptions.copy(
+ cocoapodsGenerateWrapper = true
+ )
+ )
+
+ private val templateProjectName = "native-cocoapods-template"
+ private val groovyTemplateProjectName = "native-cocoapods-template-groovy"
+
+ private val defaultPodRepo = "https://github.com/AFNetworking/AFNetworking"
+ private val defaultPodName = "AFNetworking"
+ private val defaultTarget = "IOS"
+ private val defaultFamily = "ios"
+ private val defaultSDK = "iphonesimulator"
+ private val cinteropTaskName = ":cinterop"
+ private val defaultCinteropTaskName = cinteropTaskName + defaultPodName + defaultTarget
+
+ private val podImportTaskName = ":$POD_IMPORT_TASK_NAME"
+ private val podspecTaskName = ":$POD_SPEC_TASK_NAME"
+ private val podGenTaskName = ":$POD_GEN_TASK_NAME"
+ private val podSetupBuildTaskName = ":$POD_SETUP_BUILD_TASK_NAME"
+ private val podBuildTaskName = ":$POD_BUILD_TASK_NAME"
+ private val podInstallTaskName = ":$POD_INSTALL_TASK_NAME"
+
+ private val defaultPodInstallSyntheticTaskName = ":podInstallSyntheticIos"
+ private val defaultPodGenTaskName = podGenFullTaskName()
+ private val defaultBuildTaskName = podBuildFullTaskName()
+ private val defaultSetupBuildTaskName = podSetupBuildFullTaskName()
+
+ private fun podGenFullTaskName(familyName: String = defaultFamily) =
+ podGenTaskName + familyName.capitalize()
+
+ private fun podSetupBuildFullTaskName(podName: String = defaultPodName, sdkName: String = defaultSDK) =
+ podSetupBuildTaskName + podName.capitalize() + sdkName.capitalize()
+
+ private fun podBuildFullTaskName(podName: String = defaultPodName, sdkName: String = defaultSDK) =
+ podBuildTaskName + podName.capitalize() + sdkName.capitalize()
+
+ private fun cinteropFullTaskName(podName: String = defaultPodName, targetName: String = defaultTarget) =
+ cinteropTaskName + podName.capitalize() + targetName.capitalize()
+
+ @BeforeAll
+ fun setUp() {
+ ensureCocoapodsInstalled()
+ }
+
+ @DisplayName("Downloading pod from git without specifying neither tag not commit")
+ @GradleTest
+ fun testPodDownloadGitNoTagNorCommit(gradleVersion: GradleVersion) {
+ doTestGit(gradleVersion)
+ }
+
+ @DisplayName("Downloading pod from git with specifying tag")
+ @GradleTest
+ fun testPodDownloadGitTag(gradleVersion: GradleVersion) {
+ doTestGit(gradleVersion, tag = "4.0.0")
+ }
+
+ @DisplayName("Downloading pod from git with specifying commit")
+ @GradleTest
+ fun testPodDownloadGitCommit(gradleVersion: GradleVersion) {
+ doTestGit(gradleVersion, commit = "9c07ac0a5645abb58850253eeb109ed0dca515c1")
+ }
+
+ @DisplayName("Downloading pod from git with specifying branch")
+ @GradleTest
+ fun testPodDownloadGitBranch(gradleVersion: GradleVersion) {
+ doTestGit(gradleVersion, branch = "2974")
+ }
+
+ @DisplayName("Downloading pod's subspec from git")
+ @GradleTest
+ fun testPodDownloadGitSubspec(gradleVersion: GradleVersion) {
+ doTestGit(
+ gradleVersion,
+ repo = "https://github.com/SDWebImage/SDWebImage.git",
+ pod = "SDWebImage/MapKit",
+ tag = "5.9.2"
+ )
+ }
+
+ @DisplayName("Downloading pod from git with specifying branch and commit")
+ @GradleTest
+ fun testPodDownloadGitBranchAndCommit(gradleVersion: GradleVersion) {
+ doTestGit(
+ gradleVersion,
+ branch = "2974",
+ commit = "21637dd6164c0641e414bdaf3885af6f1ef15aee"
+ )
+ }
+
+
+ @DisplayName("Downloading pod from git (tag priority is bigger than branch priority)")
+ @GradleTest
+ fun testPodDownloadGitBranchAndTag(gradleVersion: GradleVersion) {
+ doTestGit(
+ gradleVersion,
+ tag = "4.0.0",
+ branch = "2974"
+ )
+ }
+
+ @DisplayName("Downloading pod from git with specifying tag for groovy build file")
+ @GradleTest
+ fun testGroovyDownloadAndImport(gradleVersion: GradleVersion) {
+ doTestGit(
+ gradleVersion,
+ groovyTemplateProjectName,
+ tag = "4.0.0",
+ isGradleBuildScript = true
+ )
+ }
+
+ @DisplayName("Checks that task cinterop is up to date during the second build")
+ @GradleTest
+ fun testCinteropUpToDate(gradleVersion: GradleVersion) {
+ doTestGit(gradleVersion) {
+
+ build(
+ "syncFramework",
+ buildOptions = defaultBuildOptions.copy(
+ nativeOptions = defaultBuildOptions.nativeOptions.copy(
+ cocoapodsGenerateWrapper = true,
+ cocoapodsArchs = "x86_64",
+ cocoapodsConfiguration = "Debug",
+ cocoapodsPlatform = "iphonesimulator",
+ )
+ )
+ ) {
+ assertTasksUpToDate(
+ defaultCinteropTaskName
+ )
+ }
+ }
+
+ }
+
+ @DisplayName("UTD test")
+ @GradleTest
+ fun basicUTDTest(gradleVersion: GradleVersion) {
+ val tasks = listOf(
+ podspecTaskName,
+ defaultPodGenTaskName,
+ defaultPodInstallSyntheticTaskName,
+ defaultSetupBuildTaskName,
+ defaultBuildTaskName,
+ defaultCinteropTaskName,
+ )
+ doTestGit(
+ gradleVersion,
+ testImportAssertions = { assertTasksExecuted(tasks) }
+ ) {
+ testImport {
+ assertTasksUpToDate(tasks)
+ }
+ }
+ }
+
+ @DisplayName("UTD with adding and removing pod")
+ @GradleTest
+ fun testUTDPodAdded(gradleVersion: GradleVersion) {
+ nativeProjectWithCocoapodsAndIosAppPodFile(gradleVersion = gradleVersion) {
+ buildGradleKts.addPod(defaultPodName, produceGitBlock())
+ testImport()
+
+ val anotherPodName = "Alamofire"
+ val anotherPodRepo = "https://github.com/Alamofire/Alamofire"
+ buildGradleKts.addPod(anotherPodName, produceGitBlock(anotherPodRepo))
+ testImport(listOf(defaultPodRepo, anotherPodRepo)) {
+
+ assertTasksExecuted(
+ podspecTaskName,
+ defaultPodGenTaskName,
+ podSetupBuildFullTaskName(anotherPodName),
+ podBuildFullTaskName(anotherPodName),
+ cinteropFullTaskName(anotherPodName)
+ )
+ assertTasksUpToDate(
+ defaultSetupBuildTaskName,
+ defaultBuildTaskName,
+ defaultCinteropTaskName
+ )
+
+ buildGradleKts.removePod(anotherPodName)
+
+ testImport {
+ assertOutputDoesNotContain(podBuildFullTaskName(anotherPodName))
+ assertOutputDoesNotContain(cinteropFullTaskName(anotherPodName))
+ assertTasksUpToDate(
+ defaultBuildTaskName,
+ defaultSetupBuildTaskName,
+ defaultCinteropTaskName
+ )
+ }
+ }
+ }
+ }
+
+ @DisplayName("UTD with adding and removing target")
+ @GradleTest
+ fun testUTDTargetAdded(gradleVersion: GradleVersion) {
+ nativeProjectWithCocoapodsAndIosAppPodFile(gradleVersion = gradleVersion) {
+ buildGradleKts.addPod(defaultPodName, produceGitBlock())
+
+ testImport()
+
+ buildGradleKts.addCocoapodsBlock("osx.deploymentTarget = \"10.15\"")
+ testImport()
+
+ val tasks = listOf(
+ podspecTaskName,
+ defaultPodGenTaskName,
+ defaultSetupBuildTaskName,
+ defaultBuildTaskName,
+ defaultCinteropTaskName
+ )
+ val anotherTarget = "MacosX64"
+ val anotherSdk = "macosx"
+ val anotherFamily = "macos"
+ buildGradleKts.addKotlinBlock(anotherTarget.replaceFirstChar { it.lowercase(Locale.getDefault()) } + "()")
+
+ testImport {
+ assertTasksExecuted(
+ podGenFullTaskName(anotherFamily),
+ podSetupBuildFullTaskName(sdkName = anotherSdk),
+ podBuildFullTaskName(sdkName = anotherSdk),
+ cinteropFullTaskName(targetName = anotherTarget)
+ )
+ assertTasksUpToDate(tasks)
+ }
+
+ buildGradleKts.replaceText(anotherTarget.replaceFirstChar { it.lowercase(Locale.getDefault()) } + "()", "")
+ testImport {
+ assertOutputDoesNotContain(podGenFullTaskName(anotherFamily))
+ assertOutputDoesNotContain(podSetupBuildFullTaskName(sdkName = anotherSdk))
+ assertOutputDoesNotContain(podBuildFullTaskName(sdkName = anotherSdk))
+ assertOutputDoesNotContain(cinteropFullTaskName(targetName = anotherTarget))
+ assertTasksUpToDate(tasks)
+ }
+ }
+ }
+
+ @DisplayName("UTD build")
+ @GradleTest
+ fun testUTDBuild(gradleVersion: GradleVersion) {
+ nativeProjectWithCocoapodsAndIosAppPodFile(gradleVersion = gradleVersion) {
+ buildGradleKts.addPod(defaultPodName, produceGitBlock())
+
+ testImport {
+ assertTasksExecuted(defaultBuildTaskName)
+ }
+
+ val anotherTarget = "MacosX64"
+ val anotherSdk = "macosx"
+ val anotherSdkDefaultPodTaskName = podBuildFullTaskName(sdkName = anotherSdk)
+ buildGradleKts.addCocoapodsBlock("osx.deploymentTarget = \"10.15\"")
+ buildGradleKts.addKotlinBlock(anotherTarget.replaceFirstChar { it.lowercase(Locale.getDefault()) } + "()")
+
+ testImport {
+ assertTasksUpToDate(defaultBuildTaskName)
+ assertTasksExecuted(anotherSdkDefaultPodTaskName)
+ }
+ testImport {
+ assertTasksUpToDate(defaultBuildTaskName, anotherSdkDefaultPodTaskName)
+ }
+ }
+ }
+
+ @DisplayName("Pod Build UTD after clean")
+ @GradleTest
+ fun testPodBuildUTDClean(gradleVersion: GradleVersion) {
+ nativeProjectWithCocoapodsAndIosAppPodFile(gradleVersion = gradleVersion) {
+ buildGradleKts.addPod(defaultPodName, produceGitBlock())
+
+ testImport {
+ assertTasksExecuted(defaultBuildTaskName)
+ }
+ build(":clean")
+ testImport {
+ assertTasksExecuted(defaultBuildTaskName)
+ }
+ }
+ }
+
+ @DisplayName("Link with use of dynamic framework ")
+ @GradleTest
+ fun testUseDynamicFramework(gradleVersion: GradleVersion) {
+ nativeProjectWithCocoapodsAndIosAppPodFile(gradleVersion = gradleVersion) {
+ buildGradleKts.addPod(defaultPodName, produceGitBlock())
+ buildGradleKts.addFrameworkBlock("isStatic = false")
+
+ build("linkPodDebugFrameworkIOS") {
+ val framework = projectPath.resolve("build/bin/iOS/podDebugFramework/cocoapods.framework/cocoapods")
+ val processRunResult = runProcess(
+ listOf("file", framework.absolutePathString()),
+ workingDir = projectPath.toFile(),
+ environmentVariables = environmentVariables.environmentalVariables
+ )
+ assertProcessRunResult(processRunResult) {
+ assertTrue(isSuccessful)
+ assertTrue(output.contains("dynamically linked shared library"))
+ }
+ }
+ }
+ }
+
+ @DisplayName("Link with use of static framework ")
+ @GradleTest
+ fun testUseStaticFramework(gradleVersion: GradleVersion) {
+ nativeProjectWithCocoapodsAndIosAppPodFile(gradleVersion = gradleVersion) {
+ buildGradleKts.addPod(defaultPodName, produceGitBlock())
+ buildGradleKts.addFrameworkBlock("isStatic = true")
+
+ build("linkPodDebugFrameworkIOS") {
+ val framework = projectPath.resolve("build/bin/iOS/podDebugFramework/cocoapods.framework/cocoapods")
+ val processRunResult = runProcess(
+ listOf("file", framework.absolutePathString()),
+ workingDir = projectPath.toFile(),
+ environmentVariables = environmentVariables.environmentalVariables
+ )
+ assertProcessRunResult(processRunResult) {
+ assertTrue(isSuccessful)
+ assertTrue(output.contains("current ar archive"))
+ }
+ }
+ }
+ }
+
+ @DisplayName("UTD with different spec repo")
+ @GradleTest
+ fun testUTDPodGen(gradleVersion: GradleVersion) {
+ nativeProjectWithCocoapodsAndIosAppPodFile(gradleVersion = gradleVersion) {
+
+ buildGradleKts.addPod(defaultPodName)
+ val repos = listOf(
+ "https://github.com/alozhkin/spec_repo_example",
+ "https://github.com/alozhkin/spec_repo_example_2"
+ )
+
+ isRepoAvailable(repos)
+
+ build(defaultPodGenTaskName) {
+ assertTasksExecuted(defaultPodGenTaskName)
+ }
+
+ buildGradleKts.addSpecRepo("https://github.com/alozhkin/spec_repo_example")
+ build(defaultPodGenTaskName) {
+ assertTasksExecuted(defaultPodGenTaskName)
+ }
+
+ buildGradleKts.addSpecRepo("https://github.com/alozhkin/spec_repo_example_2")
+ build(defaultPodGenTaskName) {
+ assertTasksExecuted(defaultPodGenTaskName)
+ }
+
+ build(defaultPodGenTaskName) {
+ assertTasksUpToDate(defaultPodGenTaskName)
+ }
+ }
+
+ }
+
+ private fun doTestGit(
+ gradleVersion: GradleVersion,
+ projectName: String = templateProjectName,
+ repo: String = defaultPodRepo,
+ pod: String = defaultPodName,
+ branch: String? = null,
+ commit: String? = null,
+ tag: String? = null,
+ isGradleBuildScript: Boolean = false,
+ testImportAssertions: BuildResult.() -> Unit = {},
+ block: TestProject.() -> Unit = {},
+ ) {
+
+ nativeProjectWithCocoapodsAndIosAppPodFile(projectName, gradleVersion) {
+ val buildScript = if (isGradleBuildScript) buildGradle else buildGradleKts
+ buildScript.addPod(pod, produceGitBlock(repo, branch, commit, tag))
+
+ testImport(listOf(repo)) {
+ podImportAsserts(buildScript)
+ testImportAssertions()
+ }
+ block()
+ }
+
+ }
+
+ private fun produceGitBlock(
+ repo: String = defaultPodRepo,
+ branchName: String? = null,
+ commitName: String? = null,
+ tagName: String? = null,
+ ): String {
+ val branch = if (branchName != null) "branch = \"$branchName\"" else ""
+ val commit = if (commitName != null) "commit = \"$commitName\"" else ""
+ val tag = if (tagName != null) "tag = \"$tagName\"" else ""
+ return """source = git("$repo") {
+ | $branch
+ | $commit
+ | $tag
+ |}
+ """.trimMargin()
+ }
+
+ private fun BuildResult.podImportAsserts(
+ buildScript: Path,
+ projectName: String? = null,
+ ) {
+
+ val buildScriptText = buildScript.readText()
+ val taskPrefix = projectName?.let { ":$it" } ?: ""
+ val podspec = "podspec"
+
+ if ("noPodspec()" in buildScriptText) {
+ assertTasksSkipped("$taskPrefix:$podspec")
+ }
+
+ if ("podfile" in buildScriptText) {
+ assertTasksExecuted("$taskPrefix$podInstallTaskName")
+ } else {
+ assertTasksSkipped("$taskPrefix$podInstallTaskName")
+ }
+ if (buildScriptText.matches("pod\\(.*\\)".toRegex())) {
+ assertTasksExecuted(listOf("$taskPrefix:$POD_GEN_TASK_NAME"))
+ }
+
+ with(listOf(POD_SETUP_BUILD_TASK_NAME, POD_BUILD_TASK_NAME).map { "$taskPrefix:$it" }) {
+ if (buildScriptText.matches("pod\\(.*\\)".toRegex())) {
+ assertTasksExecuted(this)
+ }
+ }
+ }
+
+ private fun isRepoAvailable(repos: List) = runBlocking {
+ HttpClient(CIO).use { client ->
+ val nonAvailableRepos = repos
+ .map { repo ->
+ async { repo to runCatching { client.get(repo).status }.recover { it }.getOrNull() }
+ }
+ .awaitAll()
+ .filter { (_, status) -> status != HttpStatusCode.OK }
+ Assumptions.assumeTrue(nonAvailableRepos.isEmpty()) {
+ "The following repositories of ${repos.joinToString()} are not available: ${nonAvailableRepos.joinToString()}"
+ }
+ }
+ }
+
+ private fun TestProject.testImport(
+ repos: List = listOf(defaultPodRepo),
+ vararg args: String,
+ assertions: BuildResult.() -> Unit = {},
+ ) {
+
+ isRepoAvailable(repos)
+
+ build(podImportTaskName, *args) {
+ assertions()
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt
index 6e5dcb66ed7..4dfcf1bef54 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt
@@ -13,7 +13,9 @@ import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Compan
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_INSTALL_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.util.createTempDir
+import org.jetbrains.kotlin.gradle.testbase.ImportMode
+import org.jetbrains.kotlin.gradle.testbase.cocoaPodsEnvironmentVariables
+import org.jetbrains.kotlin.gradle.testbase.ensureCocoapodsInstalled
import org.jetbrains.kotlin.gradle.util.modify
import org.jetbrains.kotlin.gradle.util.runProcess
import org.jetbrains.kotlin.konan.target.HostManager
@@ -22,7 +24,6 @@ import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import java.io.File
-import java.io.IOException
import java.util.*
import java.util.concurrent.TimeUnit
import java.util.zip.ZipFile
@@ -40,7 +41,7 @@ class CocoaPodsIT : BaseGradleIT() {
private val gradleVersion = GradleVersionRequired.FOR_MPP_SUPPORT
override fun defaultBuildOptions(): BuildOptions =
- super.defaultBuildOptions().copy(customEnvironmentVariables = getEnvs())
+ super.defaultBuildOptions().copy(customEnvironmentVariables = cocoaPodsEnvironmentVariables())
private val podfileImportDirectivePlaceholder = ""
private val podfileImportPodPlaceholder = "#import_pod_directive"
@@ -48,54 +49,24 @@ class CocoaPodsIT : BaseGradleIT() {
private val cocoapodsSingleKtPod = "native-cocoapods-single"
private val cocoapodsMultipleKtPods = "native-cocoapods-multiple"
private val templateProjectName = "native-cocoapods-template"
- private val groovyTemplateProjectName = "native-cocoapods-template-groovy"
private val cocoapodsTestsProjectName = "native-cocoapods-tests"
private val cocoapodsCommonizationProjectName = "native-cocoapods-commonization"
private val dummyTaskName = ":$DUMMY_FRAMEWORK_TASK_NAME"
private val podspecTaskName = ":$POD_SPEC_TASK_NAME"
private val podGenTaskName = ":$POD_GEN_TASK_NAME"
- private val podBuildTaskName = ":$POD_BUILD_TASK_NAME"
- private val podSetupBuildTaskName = ":$POD_SETUP_BUILD_TASK_NAME"
private val podImportTaskName = ":$POD_IMPORT_TASK_NAME"
private val podInstallTaskName = ":$POD_INSTALL_TASK_NAME"
- private val cinteropTaskName = ":cinterop"
private val defaultPodRepo = "https://github.com/AFNetworking/AFNetworking"
private val defaultPodName = "AFNetworking"
- private val defaultTarget = "IOS"
private val defaultFamily = "ios"
- private val defaultSDK = "iphonesimulator"
private val defaultPodGenTaskName = podGenFullTaskName()
private val defaultPodInstallSyntheticTaskName = ":podInstallSyntheticIos"
- private val defaultBuildTaskName = podBuildFullTaskName()
- private val defaultSetupBuildTaskName = podSetupBuildFullTaskName()
- private val defaultCinteropTaskName = cinteropTaskName + defaultPodName + defaultTarget
private fun podGenFullTaskName(familyName: String = defaultFamily) =
podGenTaskName + familyName.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
- private fun podSetupBuildFullTaskName(podName: String = defaultPodName, sdkName: String = defaultSDK) =
- podSetupBuildTaskName + podName.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } + sdkName.replaceFirstChar {
- if (it.isLowerCase()) it.titlecase(
- Locale.getDefault()
- ) else it.toString()
- }
-
- private fun podBuildFullTaskName(podName: String = defaultPodName, sdkName: String = defaultSDK) =
- podBuildTaskName + podName.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } + sdkName.replaceFirstChar {
- if (it.isLowerCase()) it.titlecase(
- Locale.getDefault()
- ) else it.toString()
- }
-
- private fun cinteropFullTaskName(podName: String = defaultPodName, targetName: String = defaultTarget) =
- cinteropTaskName + podName.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } + targetName.replaceFirstChar {
- if (it.isLowerCase()) it.titlecase(
- Locale.getDefault()
- ) else it.toString()
- }
-
private lateinit var hooks: CustomHooks
private lateinit var project: BaseGradleIT.Project
@@ -154,7 +125,8 @@ class CocoaPodsIT : BaseGradleIT() {
@Test
fun testSyntheticProjectPodfileGeneration() {
val gradleProject = transformProjectWithPluginsDsl(cocoapodsSingleKtPod, gradleVersion)
- gradleProject.gradleBuildScript().appendToCocoapodsBlock("""
+ gradleProject.gradleBuildScript().appendToCocoapodsBlock(
+ """
ios.deploymentTarget = "14.1"
pod("SSZipArchive")
pod("AFNetworking", "~> 4.0.1")
@@ -163,7 +135,8 @@ class CocoaPodsIT : BaseGradleIT() {
tag = "5.6.1"
}
}
- """.trimIndent())
+ """.trimIndent()
+ )
gradleProject.build("podInstallSyntheticIos", "-Pkotlin.native.cocoapods.generate.wrapper=true") {
assertSuccessful()
assertTasksExecuted(":podGenIos")
@@ -184,14 +157,16 @@ class CocoaPodsIT : BaseGradleIT() {
project.gradleBuildScript().apply {
appendToCocoapodsBlock("""pod("ChatSDK", version = "5.2.1")""")
- appendText("""
+ appendText(
+ """
tasks.withType().configureEach {
doLast {
podfile.get().appendText("ENV['SWIFT_VERSION'] = '5'")
}
}
- """.trimIndent())
+ """.trimIndent()
+ )
}
project.build("podInstallSyntheticIos", "-Pkotlin.native.cocoapods.generate.wrapper=true") {
@@ -200,65 +175,6 @@ class CocoaPodsIT : BaseGradleIT() {
}
}
- @Test
- fun testPodDownloadGitNoTagNorCommit() {
- doTestGit()
- }
-
- @Test
- fun testPodDownloadGitTag() {
- doTestGit(tag = "4.0.0")
- }
-
- @Test
- fun testPodDownloadGitCommit() {
- doTestGit(commit = "9c07ac0a5645abb58850253eeb109ed0dca515c1")
- }
-
- @Test
- fun testPodDownloadGitBranch() {
- doTestGit(branch = "2974")
- }
-
- @Test
- fun testPodDownloadGitSubspec() {
- doTestGit(
- repo = "https://github.com/SDWebImage/SDWebImage.git",
- pod = "SDWebImage/MapKit",
- tag = "5.9.2"
- )
- }
-
- @Test
- fun testPodDownloadGitBranchAndCommit() {
- val branch = "2974"
- val commit = "21637dd6164c0641e414bdaf3885af6f1ef15aee"
- with(project.gradleBuildScript()) {
- addPod(defaultPodName, produceGitBlock(defaultPodRepo, branchName = branch, commitName = commit))
- }
- project.testImportWithAsserts(listOf(defaultPodRepo))
- }
-
- // tag priority is bigger than branch priority
- @Test
- fun testPodDownloadGitBranchAndTag() {
- val branch = "2974"
- val tag = "4.0.0"
- with(project.gradleBuildScript()) {
- addPod(defaultPodName, produceGitBlock(defaultPodRepo, branchName = branch, tagName = tag))
- }
- project.testImportWithAsserts(listOf(defaultPodRepo))
- }
-
- @Test
- fun testDownloadAndImport() {
- val tag = "4.0.0"
- with(project.gradleBuildScript()) {
- addPod(defaultPodName, produceGitBlock(defaultPodRepo, tagName = tag))
- }
- project.testImportWithAsserts(listOf(defaultPodRepo))
- }
-
@Test
fun warnIfDeprecatedPodspecPathIsUsed() {
project = getProjectByName(cocoapodsSingleKtPod)
@@ -306,13 +222,15 @@ class CocoaPodsIT : BaseGradleIT() {
@Test
fun testImportUTDAfterLinkingFramework() {
val linkTaskName = ":linkPodDebugFrameworkIOS"
- project.gradleBuildScript().appendToCocoapodsBlock("""
+ project.gradleBuildScript().appendToCocoapodsBlock(
+ """
framework {
baseName = "kotlin-library"
}
name = "kotlin-library"
podfile = project.file("ios-app/Podfile")
- """.trimIndent())
+ """.trimIndent()
+ )
hooks.addHook {
@@ -335,13 +253,15 @@ class CocoaPodsIT : BaseGradleIT() {
@Test
fun testChangeFrameworkTypeUTD() {
- project.gradleBuildScript().appendToCocoapodsBlock("""
+ project.gradleBuildScript().appendToCocoapodsBlock(
+ """
framework {
baseName = "kotlin-library"
}
name = "kotlin-library"
podfile = project.file("ios-app/Podfile")
- """.trimIndent())
+ """.trimIndent()
+ )
hooks.addHook {
assertTasksExecuted(dummyTaskName)
@@ -371,31 +291,6 @@ class CocoaPodsIT : BaseGradleIT() {
}
-
- @Test
- fun basicUTDTest() {
- val tasks = listOf(
- podspecTaskName,
- defaultPodGenTaskName,
- defaultPodInstallSyntheticTaskName,
- defaultSetupBuildTaskName,
- defaultBuildTaskName,
- defaultCinteropTaskName,
- )
- with(project.gradleBuildScript()) {
- addPod(defaultPodName, produceGitBlock(defaultPodRepo))
- }
- hooks.addHook {
- assertTasksExecuted(tasks)
- }
- project.testImportWithAsserts(listOf(defaultPodRepo))
-
- hooks.rewriteHooks {
- assertTasksUpToDate(tasks)
- }
- project.testImport(listOf(defaultPodRepo))
- }
-
@Test
fun testSpecReposUTD() {
with(project.gradleBuildScript()) {
@@ -433,53 +328,6 @@ class CocoaPodsIT : BaseGradleIT() {
project.testSynthetic(defaultPodInstallSyntheticTaskName)
}
- @Test
- fun testUTDPodAdded() {
- with(project.gradleBuildScript()) {
- addPod(defaultPodName, produceGitBlock(defaultPodRepo))
- }
- project.testImport(listOf(defaultPodRepo))
-
- val anotherPodName = "Alamofire"
- val anotherPodRepo = "https://github.com/Alamofire/Alamofire"
- with(project.gradleBuildScript()) {
- addPod(anotherPodName, produceGitBlock(anotherPodRepo))
- }
- hooks.rewriteHooks {
- assertTasksExecuted(
- podspecTaskName,
- defaultPodGenTaskName,
- podSetupBuildFullTaskName(anotherPodName),
- podBuildFullTaskName(anotherPodName),
- cinteropFullTaskName(anotherPodName)
- )
- assertTasksUpToDate(
- defaultSetupBuildTaskName,
- defaultBuildTaskName,
- defaultCinteropTaskName
- )
- }
- project.testImport(listOf(defaultPodRepo, anotherPodRepo))
-
- with(project.gradleBuildScript()) {
- removePod(anotherPodName)
- }
- hooks.rewriteHooks {
- assertTasksNotRegisteredByPrefix(
- listOf(
- podBuildFullTaskName(anotherPodName),
- cinteropFullTaskName(anotherPodName)
- )
- )
- assertTasksUpToDate(
- defaultBuildTaskName,
- defaultSetupBuildTaskName,
- defaultCinteropTaskName
- )
- }
- project.testImport(listOf(defaultPodRepo))
- }
-
@Test
fun testImportSubspecs() {
with(project.gradleBuildScript()) {
@@ -489,62 +337,6 @@ class CocoaPodsIT : BaseGradleIT() {
project.testImport(listOf(defaultPodRepo))
}
- @Test
- fun testUTDTargetAdded() {
- with(project.gradleBuildScript()) {
- addPod(defaultPodName, produceGitBlock(defaultPodRepo))
- appendToCocoapodsBlock("osx.deploymentTarget = \"10.15\"")
- }
- project.testImport(listOf(defaultPodRepo))
-
- val anotherTarget = "MacosX64"
- val anotherSdk = "macosx"
- val anotherFamily = "macos"
- with(project.gradleBuildScript()) {
- appendToKotlinBlock(anotherTarget.replaceFirstChar { it.lowercase(Locale.getDefault()) } + "()")
- }
- hooks.rewriteHooks {
- assertTasksExecuted(
- podGenFullTaskName(anotherFamily),
- podSetupBuildFullTaskName(sdkName = anotherSdk),
- podBuildFullTaskName(sdkName = anotherSdk),
- cinteropFullTaskName(targetName = anotherTarget)
- )
- assertTasksUpToDate(
- podspecTaskName,
- defaultPodGenTaskName,
- defaultSetupBuildTaskName,
- defaultBuildTaskName,
- defaultCinteropTaskName
- )
- }
- project.testImport(listOf(defaultPodRepo))
-
- with(project.gradleBuildScript()) {
- var text = readText()
- text = text.replace(anotherTarget.replaceFirstChar { it.lowercase(Locale.getDefault()) } + "()", "")
- writeText(text)
- }
- hooks.rewriteHooks {
- assertTasksNotRegisteredByPrefix(
- listOf(
- podGenFullTaskName(anotherFamily),
- podSetupBuildFullTaskName(sdkName = anotherSdk),
- podBuildFullTaskName(sdkName = anotherSdk),
- cinteropFullTaskName(targetName = anotherTarget)
- )
- )
- assertTasksUpToDate(
- podspecTaskName,
- defaultPodGenTaskName,
- defaultSetupBuildTaskName,
- defaultBuildTaskName,
- defaultCinteropTaskName
- )
- }
- project.testImport(listOf(defaultPodRepo))
- }
-
@Test
fun testUTDPodspec() {
project.testWithWrapper(podspecTaskName)
@@ -580,83 +372,6 @@ class CocoaPodsIT : BaseGradleIT() {
project.testWithWrapper(podspecTaskName)
}
- @Test
- fun testUTDPodGen() {
- with(project.gradleBuildScript()) {
- addPod(defaultPodName)
- }
- val repos = listOf(
- "https://github.com/alozhkin/spec_repo_example",
- "https://github.com/alozhkin/spec_repo_example_2"
- )
- for (repo in repos) {
- assumeTrue(isRepoAvailable(repo))
- }
- hooks.addHook {
- assertTasksExecuted(defaultPodGenTaskName)
- }
- project.testSynthetic(defaultPodGenTaskName)
- with(project.gradleBuildScript()) {
- addSpecRepo("https://github.com/alozhkin/spec_repo_example")
- }
- project.testSynthetic(defaultPodGenTaskName)
- with(project.gradleBuildScript()) {
- addSpecRepo("https://github.com/alozhkin/spec_repo_example_2")
- }
- project.testSynthetic(defaultPodGenTaskName)
- hooks.rewriteHooks {
- assertTasksUpToDate(defaultPodGenTaskName)
- }
- project.testSynthetic(defaultPodGenTaskName)
- }
-
- @Test
- fun testUTDBuild() {
- with(project.gradleBuildScript()) {
- addPod(defaultPodName, produceGitBlock())
- }
- hooks.addHook {
- assertTasksExecuted(defaultBuildTaskName)
- }
- project.testImport()
-
- val anotherTarget = "MacosX64"
- val anotherSdk = "macosx"
- with(project.gradleBuildScript()) {
- appendToCocoapodsBlock("osx.deploymentTarget = \"10.15\"")
- appendToKotlinBlock(anotherTarget.replaceFirstChar { it.lowercase(Locale.getDefault()) } + "()")
- }
- val anotherSdkDefaultPodTaskName = podBuildFullTaskName(sdkName = anotherSdk)
- hooks.rewriteHooks {
- assertTasksUpToDate(defaultBuildTaskName)
- assertTasksExecuted(anotherSdkDefaultPodTaskName)
- }
- project.testImport()
-
- hooks.rewriteHooks {
- assertTasksUpToDate(defaultBuildTaskName, anotherSdkDefaultPodTaskName)
- }
- project.testImport()
- }
-
- @Test
- fun testPodBuildUTDClean() {
- with(project.gradleBuildScript()) {
- addPod(defaultPodName, produceGitBlock())
- }
- hooks.addHook {
- assertTasksExecuted(defaultBuildTaskName)
- }
- project.testImport()
-
- hooks.rewriteHooks {}
- project.test(":clean")
-
- hooks.addHook {
- assertTasksExecuted(defaultBuildTaskName)
- }
- project.testImport()
- }
@Test
fun testPodInstallWithoutPodFile() {
@@ -664,19 +379,6 @@ class CocoaPodsIT : BaseGradleIT() {
}
- // groovy tests
-
- @Test
- fun testGroovyDownloadAndImport() {
- val project = getProjectByName(groovyTemplateProjectName)
- val tag = "4.0.0"
- with(project.gradleBuildScript()) {
- addPod(defaultPodName, produceGitBlock(defaultPodRepo, tagName = tag))
- }
- project.testImportWithAsserts(listOf(defaultPodRepo))
- }
-
-
// other tests
@Test
@@ -742,47 +444,6 @@ class CocoaPodsIT : BaseGradleIT() {
}
}
- @Test
- fun testUseDynamicFramework() {
- with(project) {
- gradleBuildScript().addPod(defaultPodName, produceGitBlock(defaultPodRepo))
- gradleBuildScript().appendToFrameworkBlock("isStatic = false")
- hooks.addHook {
- // Check that an output framework is a dynamic framework
- val framework = fileInWorkingDir("build/bin/iOS/podDebugFramework/cocoapods.framework/cocoapods")
- with(runProcess(listOf("file", framework.absolutePath), projectDir, environmentVariables = getEnvs())) {
- assertTrue(isSuccessful)
- assertTrue(output.contains("dynamically linked shared library"))
- }
- }
-
- test(
- "linkPodDebugFrameworkIOS",
- "-Pkotlin.native.cocoapods.generate.wrapper=true"
- )
- }
- }
-
- @Test
- fun testUseStaticFramework() {
- with(project) {
- gradleBuildScript().addPod(defaultPodName, produceGitBlock(defaultPodRepo))
- gradleBuildScript().appendToFrameworkBlock("isStatic = true")
- hooks.addHook {
- // Check that an output framework is a static framework
- val framework = fileInWorkingDir("build/bin/iOS/podDebugFramework/cocoapods.framework/cocoapods")
- with(runProcess(listOf("file", framework.absolutePath), projectDir, environmentVariables = getEnvs())) {
- assertTrue(isSuccessful)
- kotlin.test.assertContains(output, "current ar archive")
- }
- }
-
- test(
- "linkPodDebugFrameworkIOS",
- "-Pkotlin.native.cocoapods.generate.wrapper=true"
- )
- }
- }
@Test
fun testCocoapodsWithRegularFrameworkDefinition() {
@@ -970,23 +631,6 @@ class CocoaPodsIT : BaseGradleIT() {
getProjectByName(cocoapodsTestsProjectName).testWithWrapper(":iosX64Test")
}
- @Test
- fun testCinteropUpToDate() {
- project.gradleBuildScript().addPod(defaultPodName, produceGitBlock(defaultPodRepo))
- project.testImport()
- hooks.addHook {
- assertTasksUpToDate(
- defaultCinteropTaskName
- )
- }
- project.test(
- "syncFramework",
- "-Pkotlin.native.cocoapods.platform=iphonesimulator",
- "-Pkotlin.native.cocoapods.archs=x86_64",
- "-Pkotlin.native.cocoapods.configuration=Debug",
- "-Pkotlin.native.cocoapods.generate.wrapper=true"
- )
- }
@Test
fun testCinteropCommonizationOff() {
@@ -1116,11 +760,13 @@ class CocoaPodsIT : BaseGradleIT() {
@Test
fun testLinkOnlyPods() = with(project) {
- gradleBuildScript().appendToCocoapodsBlock("""
+ gradleBuildScript().appendToCocoapodsBlock(
+ """
pod("AFNetworking") { linkOnly = true }
pod("SSZipArchive", linkOnly = true)
pod("SDWebImage/Core")
- """.trimIndent())
+ """.trimIndent()
+ )
build(
":linkPodDebugFrameworkIOS",
@@ -1136,31 +782,37 @@ class CocoaPodsIT : BaseGradleIT() {
assertTasksNotRegistered(":cinteropAFNetworkingIOS")
assertTasksNotRegistered(":cinteropSSZipArchiveIOS")
- assertContains("""
+ assertContains(
+ """
| -linker-option
| -framework
| -linker-option
| AFNetworking
- """.trimMargin())
+ """.trimMargin()
+ )
- assertContains("""
+ assertContains(
+ """
| -linker-option
| -framework
| -linker-option
| SSZipArchive
- """.trimMargin())
+ """.trimMargin()
+ )
}
}
@Test
fun testUsageLinkOnlyWithStaticFrameworkProducesMessage() = with(project) {
- gradleBuildScript().appendToCocoapodsBlock("""
+ gradleBuildScript().appendToCocoapodsBlock(
+ """
framework {
isStatic = true
}
pod("AFNetworking") { linkOnly = true }
- """.trimIndent())
+ """.trimIndent()
+ )
build(
":linkPodDebugFrameworkIOS",
@@ -1184,9 +836,11 @@ class CocoaPodsIT : BaseGradleIT() {
@Test
fun `configuration fails when trying to depend on non-declared pod`() = with(getProjectByName("native-cocoapods-dependant-pods")) {
- gradleBuildScript().appendToCocoapodsBlock("""
+ gradleBuildScript().appendToCocoapodsBlock(
+ """
pod("Foo") { useInteropBindingFrom("JBNonExistent") }
- """.trimIndent())
+ """.trimIndent()
+ )
build(
":help",
@@ -1199,10 +853,12 @@ class CocoaPodsIT : BaseGradleIT() {
@Test
fun `configuration fails when dependant pods are in the wrong order`() = with(getProjectByName("native-cocoapods-dependant-pods")) {
- gradleBuildScript().appendToCocoapodsBlock("""
+ gradleBuildScript().appendToCocoapodsBlock(
+ """
pod("Foo") { useInteropBindingFrom("Bar") }
pod("Bar")
- """.trimIndent())
+ """.trimIndent()
+ )
build(
":help",
@@ -1215,9 +871,11 @@ class CocoaPodsIT : BaseGradleIT() {
@Test
fun `configuration fails when pod depends on itself`() = with(getProjectByName("native-cocoapods-dependant-pods")) {
- gradleBuildScript().appendToCocoapodsBlock("""
+ gradleBuildScript().appendToCocoapodsBlock(
+ """
pod("Foo") { useInteropBindingFrom("Foo") }
- """.trimIndent())
+ """.trimIndent()
+ )
build(
":help",
@@ -1249,22 +907,10 @@ class CocoaPodsIT : BaseGradleIT() {
}
}
- private fun doTestGit(
- repo: String = defaultPodRepo,
- pod: String = defaultPodName,
- branch: String? = null,
- commit: String? = null,
- tag: String? = null
- ) {
- with(project.gradleBuildScript()) {
- addPod(pod, produceGitBlock(repo, branch, commit, tag))
- }
- project.testImportWithAsserts(listOf(repo))
- }
private fun Project.testImportWithAsserts(
repos: List = listOf(),
- vararg args: String
+ vararg args: String,
) {
hooks.addHook {
podImportAsserts()
@@ -1274,7 +920,7 @@ class CocoaPodsIT : BaseGradleIT() {
private fun Project.testImport(
repos: List = listOf(),
- vararg args: String
+ vararg args: String,
) {
for (repo in repos) {
assumeTrue(isRepoAvailable(repo))
@@ -1284,21 +930,21 @@ class CocoaPodsIT : BaseGradleIT() {
private fun Project.testSynthetic(
taskName: String,
- vararg args: String
+ vararg args: String,
) {
testWithWrapper(taskName, *args)
}
private fun Project.testWithWrapper(
taskName: String,
- vararg args: String
+ vararg args: String,
) {
test(taskName, "-Pkotlin.native.cocoapods.generate.wrapper=true", *args)
}
private fun Project.test(
taskName: String,
- vararg args: String
+ vararg args: String,
) {
// check that test executable
@@ -1320,25 +966,6 @@ class CocoaPodsIT : BaseGradleIT() {
appendToCocoapodsBlock(podBlock)
}
- private fun File.removePod(podName: String) {
- val text = readText()
- val begin = text.indexOf("""pod("$podName")""")
- require(begin != -1) { "Pod doesn't exist in file" }
- var index = begin + """pod("$podName")""".length - 1
- if (text.indexOf("""pod("$podName") {""", startIndex = begin) != -1) {
- index += 2
- var bracket = 1
- while (bracket != 0) {
- if (text[++index] == '{') {
- bracket++
- } else if (text[index] == '}') {
- bracket--
- }
- }
- }
- writeText(text.removeRange(begin..index))
- }
-
private fun File.addSpecRepo(specRepo: String) = appendToCocoapodsBlock("url(\"$specRepo\")".wrap("specRepos"))
private fun File.appendToKotlinBlock(str: String) = appendLine(str.wrap("kotlin"))
@@ -1355,23 +982,6 @@ class CocoaPodsIT : BaseGradleIT() {
private fun File.appendLine(s: String) = appendText("\n$s")
- private fun produceGitBlock(
- repo: String = defaultPodRepo,
- branchName: String? = null,
- commitName: String? = null,
- tagName: String? = null
- ): String {
- val branch = if (branchName != null) "branch = \"$branchName\"" else ""
- val commit = if (commitName != null) "commit = \"$commitName\"" else ""
- val tag = if (tagName != null) "tag = \"$tagName\"" else ""
- return """source = git("$repo") {
- | $branch
- | $commit
- | $tag
- |}
- """.trimMargin()
- }
-
// proposition phase
@@ -1426,15 +1036,10 @@ class CocoaPodsIT : BaseGradleIT() {
}
}
- private enum class ImportMode(val directive: String) {
- FRAMEWORKS("use_frameworks!"),
- MODULAR_HEADERS("use_modular_headers!")
- }
-
private data class CommandResult(
val exitCode: Int,
val stdOut: String,
- val stdErr: String
+ val stdErr: String,
)
private fun runCommand(
@@ -1443,11 +1048,11 @@ class CocoaPodsIT : BaseGradleIT() {
vararg args: String,
timeoutSec: Long = 120,
inheritIO: Boolean = false,
- block: CommandResult.() -> Unit
+ block: CommandResult.() -> Unit,
) {
val process = ProcessBuilder(command, *args).apply {
directory(workingDir)
- environment().putAll(getEnvs())
+ environment().putAll(cocoaPodsEnvironmentVariables())
if (inheritIO) {
inheritIO()
}
@@ -1523,79 +1128,12 @@ class CocoaPodsIT : BaseGradleIT() {
@BeforeClass
@JvmStatic
- fun ensureCocoapodsInstalled() {
+ fun checkCocoapodsInstalled() {
if (!HostManager.hostIsMac) {
return
}
- if (shouldInstallLocalCocoapods) {
- val installDir = cocoapodsInstallationRoot.absolutePath
- println("Installing CocoaPods...")
-
- //https://github.com/ffi/ffi/issues/864#issuecomment-875242776
- gem("install", "--install-dir", installDir, "ffi", "-v", "1.15.5", "--", "--enable-libffi-alloc")
-
- gem("install", "--install-dir", installDir, "cocoapods", "-v", localCocoapodsVersion)
- } else if (!isCocoapodsInstalled()) {
- fail(
- """
- Running CocoaPods integration tests requires cocoapods to be installed.
- Please install them manually:
- gem install cocoapods
- Or re-run the tests with the 'installCocoapods=true' Gradle property.
- """.trimIndent()
- )
- }
- }
-
- private const val localCocoapodsVersion = "1.11.0"
-
- private val shouldInstallLocalCocoapods: Boolean = System.getProperty("installCocoapods").toBoolean()
-
- private val cocoapodsInstallationRoot: File by lazy { createTempDir("cocoapods") }
- private val cocoapodsBinPath: File by lazy {
- cocoapodsInstallationRoot.resolve("bin")
- }
-
- private fun getEnvs(): Map {
- if (!shouldInstallLocalCocoapods) {
- return emptyMap()
- }
-
- val path = cocoapodsBinPath.absolutePath + File.pathSeparator + System.getenv("PATH")
- val gemPath = System.getenv("GEM_PATH")?.let {
- cocoapodsInstallationRoot.absolutePath + File.pathSeparator + it
- } ?: cocoapodsInstallationRoot.absolutePath
- return mapOf(
- "PATH" to path,
- "GEM_PATH" to gemPath,
- // CocoaPods 1.11 requires UTF-8 locale being set, more details: https://github.com/CocoaPods/CocoaPods/issues/10939
- "LC_ALL" to "en_US.UTF-8"
- )
- }
-
- private fun isCocoapodsInstalled(): Boolean {
- // Do not use 'gem list' because the gem may be installed but PATH may miss its executables.
- // Try to access the pod executable directly instead
- return try {
- val result = runProcess(
- listOf("pod", "--version"),
- File("."),
- )
- result.isSuccessful
- } catch (e: IOException) {
- false
- }
- }
-
- private fun gem(vararg args: String): String {
- val command = listOf("gem", *args)
- println("Run command: ${command.joinToString(separator = " ")}")
- val result = runProcess(command, File("."), options = BuildOptions(forceOutputToStdout = true))
- check(result.isSuccessful) {
- "Process 'gem ${args.joinToString(separator = " ")}' exited with error code ${result.exitCode}. See log for details."
- }
- return result.output
+ ensureCocoapodsInstalled()
}
}
}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsXcodeIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsXcodeIT.kt
index 92ca0b88dbd..3f237418d7a 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsXcodeIT.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsXcodeIT.kt
@@ -6,10 +6,11 @@
package org.jetbrains.kotlin.gradle.native
import org.gradle.util.GradleVersion
+import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_INSTALL_TASK_NAME
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.util.assertProcessRunResult
-import org.jetbrains.kotlin.gradle.util.replaceText
import org.jetbrains.kotlin.gradle.util.runProcess
+import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.condition.OS
import java.nio.file.Path
@@ -24,18 +25,16 @@ import kotlin.test.assertEquals
@OptIn(EnvironmentalVariablesOverride::class)
class CocoaPodsXcodeIT : KGPBaseTest() {
- private val podfileImportDirectivePlaceholder = ""
-
private val cocoapodsSingleKtPod = "native-cocoapods-single"
private val cocoapodsMultipleKtPods = "native-cocoapods-multiple"
private val templateProjectName = "native-cocoapods-template"
- private val environmentVariables = EnvironmentalVariables(
- mapOf(
- // CocoaPods 1.11 requires UTF-8 locale being set, more details: https://github.com/CocoaPods/CocoaPods/issues/10939
- "LC_ALL" to "en_US.UTF-8"
- )
- )
+ private val environmentVariables = EnvironmentalVariables(cocoaPodsEnvironmentVariables())
+
+ @BeforeAll
+ fun setUp() {
+ ensureCocoapodsInstalled()
+ }
@DisplayName("Checks xcodebuild for ios-app with a single framework")
@GradleTest
@@ -142,20 +141,6 @@ class CocoaPodsXcodeIT : KGPBaseTest() {
mapOf("kotlin-library" to "FirstMultiplatformLibrary", "second-library" to "SecondMultiplatformLibrary")
)
- private enum class ImportMode(val directive: String) {
- FRAMEWORKS("use_frameworks!"),
- MODULAR_HEADERS("use_modular_headers!")
- }
-
- private fun TestProject.preparePodfile(iosAppLocation: String, mode: ImportMode) {
- val iosAppDir = projectPath.resolve(iosAppLocation)
-
- // Set import mode for Podfile.
- iosAppDir.resolve("Podfile")
- .takeIf { it.exists() }
- ?.replaceText(podfileImportDirectivePlaceholder, mode.directive)
- }
-
private fun doTestXcode(
projectName: String,
gradleVersion: GradleVersion,
@@ -208,7 +193,7 @@ class CocoaPodsXcodeIT : KGPBaseTest() {
// Set import mode for Podfile.
preparePodfile(it, mode)
// Install pods.
- build("$taskPrefix:podInstall", buildOptions = buildOptions)
+ build("$taskPrefix:$POD_INSTALL_TASK_NAME", buildOptions = buildOptions)
projectPath.resolve(it).apply {
// Run Xcode build.
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/BuildOptions.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/BuildOptions.kt
index 9c23722e665..0d02d9d9a46 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/BuildOptions.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/BuildOptions.kt
@@ -68,6 +68,9 @@ data class BuildOptions(
data class NativeOptions(
val cacheKind: NativeCacheKind = NativeCacheKind.NONE,
val cocoapodsGenerateWrapper: Boolean? = null,
+ val cocoapodsPlatform: String? = null,
+ val cocoapodsConfiguration: String? = null,
+ val cocoapodsArchs: String? = null,
val distributionType: String? = null,
val distributionDownloadFromMaven: Boolean? = null,
val platformLibrariesMode: String? = null,
@@ -199,6 +202,15 @@ data class BuildOptions(
nativeOptions.cocoapodsGenerateWrapper?.let {
arguments.add("-Pkotlin.native.cocoapods.generate.wrapper=${it}")
}
+ nativeOptions.cocoapodsPlatform?.let {
+ arguments.add("-Pkotlin.native.cocoapods.platform=${it}")
+ }
+ nativeOptions.cocoapodsArchs?.let {
+ arguments.add("-Pkotlin.native.cocoapods.archs=${it}")
+ }
+ nativeOptions.cocoapodsConfiguration?.let {
+ arguments.add("-Pkotlin.native.cocoapods.configuration=${it}")
+ }
nativeOptions.distributionDownloadFromMaven?.let {
arguments.add("-Pkotlin.native.distribution.downloadFromMaven=${it}")
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/TestVersions.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/TestVersions.kt
index 7ea675577cc..ec0ca4eb417 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/TestVersions.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/TestVersions.kt
@@ -70,6 +70,10 @@ interface TestVersions {
;
}
+ object COCOAPODS {
+ const val VERSION = "1.11.0"
+ }
+
object AppleGradlePlugin {
const val V222_0_21 = "222.4550-0.21"
}
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/cocoapodsTestHelpers.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/cocoapodsTestHelpers.kt
index 1f4ddf9b9c0..6d1241e04cc 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/cocoapodsTestHelpers.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/cocoapodsTestHelpers.kt
@@ -5,13 +5,25 @@
package org.jetbrains.kotlin.gradle.testbase
+import org.gradle.util.GradleVersion
+import org.jetbrains.kotlin.gradle.BaseGradleIT
+import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_INSTALL_TASK_NAME
import org.jetbrains.kotlin.gradle.util.replaceText
+import org.jetbrains.kotlin.gradle.util.runProcess
+import java.io.File
+import java.io.IOException
import java.nio.file.Path
-import kotlin.io.path.appendText
+import kotlin.io.path.*
+import kotlin.test.fail
val String.normalizeCocoapadsFrameworkName: String
get() = replace('-', '_')
+enum class ImportMode(val directive: String) {
+ FRAMEWORKS("use_frameworks!"),
+ MODULAR_HEADERS("use_modular_headers!")
+}
+
fun TestProject.useCustomCocoapodsFrameworkName(
subprojectName: String,
frameworkName: String,
@@ -34,10 +46,189 @@ fun TestProject.useCustomCocoapodsFrameworkName(
}
}
+/**
+ * Prepares the Podfile for an iOS app in the [TestProject]
+ *
+ * @param iosAppLocation The relative location of the iOS app directory within the [TestProject]
+ * @param mode The [ImportMode] to be set for the Podfile.
+ *
+ */
+fun TestProject.preparePodfile(iosAppLocation: String, mode: ImportMode) {
+ val iosAppDir = projectPath.resolve(iosAppLocation)
+
+ // Set import mode for Podfile.
+ iosAppDir.resolve("Podfile")
+ .takeIf { it.exists() }
+ ?.replaceText(podfileImportDirectivePlaceholder, mode.directive)
+}
+
+/**
+ * Wraps the given string into a specRepos block and adds this block to the end of the [this] path.
+ *
+ * @param specRepo The code to be wrapped with the Cocoapods block.
+ */
+
+fun Path.addSpecRepo(specRepo: String) = addCocoapodsBlock("url(\"$specRepo\")".wrapIntoBlock("specRepos"))
+
+/**
+ * Wraps the given string into a Cocoapods block and adds this block to the end of the [this] path.
+ *
+ * @param str The code to be wrapped with the Cocoapods block.
+ */
fun Path.addCocoapodsBlock(str: String) = addKotlinBlock(str.wrapIntoBlock("cocoapods"))
-private fun Path.addKotlinBlock(str: String) = appendLine(str.wrapIntoBlock("kotlin"))
+/**
+ * Wraps the given string into a Kotlin block and adds this block to the end of the [this] path.
+ *
+ * @param str The code to be wrapped with the Cocoapods block.
+ */
+fun Path.addKotlinBlock(str: String) = appendLine(str.wrapIntoBlock("kotlin"))
-private fun Path.addFrameworkBlock(str: String) = addCocoapodsBlock(str.wrapIntoBlock("framework"))
+/**
+ * Wraps the given string into a Framework block and adds this block to the end of the [this] path.
+ *
+ * @param str The code to be wrapped with the Cocoapods block.
+ */
+fun Path.addFrameworkBlock(str: String) = addCocoapodsBlock(str.wrapIntoBlock("framework"))
-private fun Path.appendLine(s: String) = appendText("\n$s")
\ No newline at end of file
+
+/**
+ * Adds a Cocoapods dependency to [this] build script.
+ *
+ * @param podName The name of the Cocoapods dependency to be added.
+ * @param configuration The optional configuration string for the Cocoapods dependency.
+ */
+fun Path.addPod(podName: String, configuration: String? = null) {
+ val pod = "pod(\"$podName\")"
+ val podBlock = configuration?.wrapIntoBlock(pod) ?: pod
+ addCocoapodsBlock(podBlock)
+}
+
+/**
+ * Removes a Cocoapods dependency from [this] build script.
+ *
+ * @param podName The name of the Cocoapods dependency to be removes.
+ */
+fun Path.removePod(podName: String) {
+ val text = readText()
+ val begin = text.indexOf("""pod("$podName")""")
+ require(begin != -1) {
+ """
+ Pod doesn't exist in file. File content is:
+ ${text}
+ """.trimIndent()
+ }
+ var index = begin + """pod("$podName")""".length - 1
+ if (text.indexOf("""pod("$podName") {""", startIndex = begin) != -1) {
+ index += 2
+ var bracket = 1
+ while (bracket != 0) {
+ if (text[++index] == '{') {
+ bracket++
+ } else if (text[index] == '}') {
+ bracket--
+ }
+ }
+ }
+ writeText(text.removeRange(begin..index))
+}
+
+/**
+ * Method returns required environment variables for cocoapods tests with execution of [POD_INSTALL_TASK_NAME]
+ */
+fun cocoaPodsEnvironmentVariables(): Map {
+ if (!shouldInstallLocalCocoapods) {
+ return emptyMap()
+ }
+
+ val path = cocoapodsBinPath.absolutePathString() + File.pathSeparator + System.getenv("PATH")
+ val gemPath = System.getenv("GEM_PATH")?.let {
+ cocoapodsInstallationRoot.absolutePathString() + File.pathSeparator + it
+ } ?: cocoapodsInstallationRoot.absolutePathString()
+ return mapOf(
+ "PATH" to path,
+ "GEM_PATH" to gemPath,
+ // CocoaPods 1.11 requires UTF-8 locale being set, more details: https://github.com/CocoaPods/CocoaPods/issues/10939
+ "LC_ALL" to "en_US.UTF-8"
+ )
+}
+
+/**
+ * This method checks if Cocoapods should be installed and verifies its installation status.
+ * If [shouldInstallLocalCocoapods] is true, it tries to install Cocoapods into the specified [cocoapodsInstallationRoot]
+ * if it is not already installed.
+ *
+ * @throws AssertionError if [shouldInstallLocalCocoapods] is false and cocoapods has not been installed
+ */
+fun ensureCocoapodsInstalled() {
+ if (shouldInstallLocalCocoapods) {
+ val installDir = cocoapodsInstallationRoot.absolutePathString()
+ println("Installing CocoaPods...")
+
+ //https://github.com/ffi/ffi/issues/864#issuecomment-875242776
+ gem("install", "--install-dir", installDir, "ffi", "-v", "1.15.5", "--", "--enable-libffi-alloc")
+
+ gem("install", "--install-dir", installDir, "cocoapods", "-v", TestVersions.COCOAPODS.VERSION)
+ } else if (!isCocoapodsInstalled()) {
+ fail(
+ """
+ Running CocoaPods integration tests requires cocoapods to be installed.
+ Please install them manually:
+ gem install cocoapods
+ Or re-run the tests with the 'installCocoapods=true' Gradle property.
+ """.trimIndent()
+ )
+ }
+}
+
+@EnvironmentalVariablesOverride
+fun KGPBaseTest.nativeProjectWithCocoapodsAndIosAppPodFile(
+ projectName: String = templateProjectName,
+ gradleVersion: GradleVersion,
+ buildOptions: BuildOptions = this.defaultBuildOptions,
+ projectBlock: TestProject.() -> Unit = {},
+) {
+ nativeProject(
+ projectName,
+ gradleVersion,
+ buildOptions = buildOptions,
+ environmentVariables = EnvironmentalVariables(cocoaPodsEnvironmentVariables())
+ ) {
+ preparePodfile("ios-app", ImportMode.FRAMEWORKS)
+ projectBlock()
+ }
+}
+
+private val templateProjectName = "native-cocoapods-template"
+
+private val shouldInstallLocalCocoapods: Boolean = System.getProperty("installCocoapods").toBoolean()
+private val cocoapodsInstallationRoot: Path by lazy { createTempDirectory("cocoapods") }
+private val cocoapodsBinPath: Path by lazy { cocoapodsInstallationRoot.resolve("bin") }
+
+private fun isCocoapodsInstalled(): Boolean {
+ // Do not use 'gem list' because the gem may be installed but PATH may miss its executables.
+ // Try to access the pod executable directly instead
+ return try {
+ val result = runProcess(
+ listOf("pod", "--version"),
+ File("."),
+ )
+ result.isSuccessful
+ } catch (e: IOException) {
+ false
+ }
+}
+
+private fun gem(vararg args: String): String {
+ val command = listOf("gem", *args)
+ println("Run command: ${command.joinToString(separator = " ")}")
+ val result = runProcess(command, File("."), options = BaseGradleIT.BuildOptions(forceOutputToStdout = true))
+ check(result.isSuccessful) {
+ "Process 'gem ${args.joinToString(separator = " ")}' exited with error code ${result.exitCode}. See log for details."
+ }
+ return result.output
+}
+
+private fun Path.appendLine(s: String) = appendText("\n$s")
+
+private const val podfileImportDirectivePlaceholder = ""
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/appleGradlePluginConsumesAppleFrameworks/iosApp/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/appleGradlePluginConsumesAppleFrameworks/iosApp/build.gradle.kts
index 9397708343d..af9dbbfaaaf 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/appleGradlePluginConsumesAppleFrameworks/iosApp/build.gradle.kts
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/appleGradlePluginConsumesAppleFrameworks/iosApp/build.gradle.kts
@@ -1,7 +1,7 @@
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
- id("org.jetbrains.gradle.apple.applePlugin") version "222.4550-0.21"
+ id("org.jetbrains.gradle.apple.applePlugin") version
}
apple {
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-cocoapods-template-groovy/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-cocoapods-template-groovy/build.gradle
index 1c0730892fd..30a223b6aaa 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-cocoapods-template-groovy/build.gradle
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-cocoapods-template-groovy/build.gradle
@@ -1,6 +1,6 @@
plugins {
- id("org.jetbrains.kotlin.multiplatform").version("")
- id("org.jetbrains.kotlin.native.cocoapods").version("")
+ id("org.jetbrains.kotlin.multiplatform")
+ id("org.jetbrains.kotlin.native.cocoapods")
}
group = "com.example"