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 db77e731fa1..89e156ac1c3 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 @@ -763,43 +763,6 @@ class CocoaPodsIT : BaseGradleIT() { } } - @Test - fun testCommaSeparatedTargets() { - with(project) { - gradleBuildScript().modify { - // Replace a single target with a pair (iosX64 + iosArm64) to test building a fat framework. - it.replace("iosX64(\"iOS\")", "ios()") - } - hooks.addHook { - // Check that a built universal framework includes both device and simulator architectures. - val framework = fileInWorkingDir("build/cocoapods/framework/cocoapods.framework/cocoapods") - with(runProcess(listOf("file", framework.absolutePath), projectDir, environmentVariables = getPathEnvs())) { - assertTrue(isSuccessful) - assertTrue(output.contains("\\(for architecture x86_64\\):\\s+current ar archive".toRegex())) - assertTrue(output.contains("\\(for architecture arm64\\):\\s+current ar archive".toRegex())) - } - } - // Run the build. - test( - "syncFramework", - "-Pkotlin.native.cocoapods.target=ios_x64,ios_arm64", - "-Pkotlin.native.cocoapods.configuration=Debug" - ) - } - } - - @Test - fun testCustomXcodeConfiguration() { - with(project) { - gradleBuildScript().appendToCocoapodsBlock("xcodeConfigurationToNativeBuildType[\"CUSTOM\"] = org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType.DEBUG\n") - test( - "syncFramework", - "-Pkotlin.native.cocoapods.target=ios_x64", - "-Pkotlin.native.cocoapods.configuration=CUSTOM" - ) - } - } - @Test fun testUseDynamicFramework() { with(project) { @@ -808,7 +771,7 @@ class CocoaPodsIT : BaseGradleIT() { hooks.addHook { // Check that an output framework is a dynamic framework val framework = fileInWorkingDir("build/cocoapods/framework/cocoapods.framework/cocoapods") - with(runProcess(listOf("file", framework.absolutePath), projectDir)) { + with(runProcess(listOf("file", framework.absolutePath), projectDir, environmentVariables = getPathEnvs())) { assertTrue(isSuccessful) assertTrue(output.contains("dynamically linked shared library")) } @@ -829,6 +792,95 @@ class CocoaPodsIT : BaseGradleIT() { } } + @Test + fun testSyncFramework() { + with(project) { + hooks.addHook { + assertTasksExecuted(":linkPodDebugFrameworkIOS") + assertTrue(fileInWorkingDir("build/cocoapods/framework/cocoapods.framework/cocoapods").exists()) + } + test( + "syncFramework", + "-Pkotlin.native.cocoapods.platform=iphonesimulator", + "-Pkotlin.native.cocoapods.archs=x86_64", + "-Pkotlin.native.cocoapods.configuration=Debug" + ) + } + } + + @Test + fun testSyncFrameworkCustomXcodeConfiguration() { + with(project) { + gradleBuildScript().appendToCocoapodsBlock("xcodeConfigurationToNativeBuildType[\"CUSTOM\"] = org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType.DEBUG\n") + hooks.addHook { + assertTasksExecuted(":linkPodDebugFrameworkIOS") + assertTrue(fileInWorkingDir("build/cocoapods/framework/cocoapods.framework/cocoapods").exists()) + } + test( + "syncFramework", + "-Pkotlin.native.cocoapods.platform=iphonesimulator", + "-Pkotlin.native.cocoapods.archs=x86_64", + "-Pkotlin.native.cocoapods.configuration=CUSTOM" + ) + } + } + + @Test + fun testSyncFrameworkInvalidArch() { + with(project) { + build( + "syncFramework", + "-Pkotlin.native.cocoapods.platform=iphoneos", + "-Pkotlin.native.cocoapods.archs=x86_64", + "-Pkotlin.native.cocoapods.configuration=Debug" + ) { + assertFailed() + assertContains("Architecture x86_64 is not supported for platform iphoneos") + } + } + } + + @Test + fun testSyncFrameworkMultiplePlatforms() { + with(project) { + build( + "syncFramework", + "-Pkotlin.native.cocoapods.platform=iphoneos iphonesimulator", + "-Pkotlin.native.cocoapods.archs=arm64", + "-Pkotlin.native.cocoapods.configuration=Debug" + ) { + assertFailed() + assertContains("kotlin.native.cocoapods.platform has to contain a single value only.") + } + } + } + + @Test + fun testSyncFrameworkMultipleArchitectures() { + with(project) { + gradleBuildScript().appendToKotlinBlock("iosArm64()") + gradleBuildScript().appendToKotlinBlock("iosArm32()") + hooks.addHook { + // Check that an output framework is a dynamic framework + val framework = fileInWorkingDir("build/cocoapods/framework/cocoapods.framework/cocoapods") + with(runProcess(listOf("file", framework.absolutePath), projectDir)) { + assertTrue(isSuccessful) + assertTrue(output.contains("\\(for architecture armv7\\):\\s+current ar archive random librar".toRegex())) + assertTrue(output.contains("\\(for architecture arm64\\):\\s+current ar archive random library".toRegex())) + } + } + + test( + "syncFramework", + "-Pkotlin.native.cocoapods.platform=iphoneos", + "-Pkotlin.native.cocoapods.archs=arm64 armv7", + "-Pkotlin.native.cocoapods.configuration=Debug", + "-Pkotlin.native.cocoapods.generate.wrapper=true" + ) + } + } + + // paths private fun CompiledProject.url() = externalSources().resolve("url") @@ -1324,15 +1376,6 @@ class CocoaPodsIT : BaseGradleIT() { spec.module_name = "#{spec.name}_umbrella" spec.dependency 'pod_dependency', '1.0' spec.dependency 'subspec_dependency/Core', '1.0' - spec.pod_target_xcconfig = { - 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', - 'KOTLIN_TARGET[sdk=iphoneos*]' => 'ios_arm', - 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x64', - 'KOTLIN_TARGET[sdk=watchos*]' => 'watchos_arm', - 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64', - 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64', - 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64' - } spec.script_phases = [ { :name => 'Build kotlin_library', @@ -1342,7 +1385,8 @@ class CocoaPodsIT : BaseGradleIT() { set -ev REPO_ROOT="${'$'}PODS_TARGET_SRCROOT" "${'$'}REPO_ROOT/../gradlew" -p "${'$'}REPO_ROOT" :kotlin-library:syncFramework \ - -Pkotlin.native.cocoapods.target=${'$'}KOTLIN_TARGET \ + -Pkotlin.native.cocoapods.platform=${'$'}PLATFORM_NAME \ + -Pkotlin.native.cocoapods.archs="${'$'}ARCHS" \ -Pkotlin.native.cocoapods.configuration=${'$'}CONFIGURATION \ -Pkotlin.native.cocoapods.cflags="${'$'}OTHER_CFLAGS" \ -Pkotlin.native.cocoapods.paths.headers="${'$'}HEADER_SEARCH_PATHS" \ @@ -1365,15 +1409,6 @@ class CocoaPodsIT : BaseGradleIT() { spec.vendored_frameworks = "build/cocoapods/framework/${frameworkName ?: "second_library"}.framework" spec.libraries = "c++" spec.module_name = "#{spec.name}_umbrella" - spec.pod_target_xcconfig = { - 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', - 'KOTLIN_TARGET[sdk=iphoneos*]' => 'ios_arm', - 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x64', - 'KOTLIN_TARGET[sdk=watchos*]' => 'watchos_arm', - 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64', - 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64', - 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64' - } spec.script_phases = [ { :name => 'Build second_library', @@ -1383,7 +1418,8 @@ class CocoaPodsIT : BaseGradleIT() { set -ev REPO_ROOT="${'$'}PODS_TARGET_SRCROOT" "${'$'}REPO_ROOT/../gradlew" -p "${'$'}REPO_ROOT" :second-library:syncFramework \ - -Pkotlin.native.cocoapods.target=${'$'}KOTLIN_TARGET \ + -Pkotlin.native.cocoapods.platform=${'$'}PLATFORM_NAME \ + -Pkotlin.native.cocoapods.archs="${'$'}ARCHS" \ -Pkotlin.native.cocoapods.configuration=${'$'}CONFIGURATION \ -Pkotlin.native.cocoapods.cflags="${'$'}OTHER_CFLAGS" \ -Pkotlin.native.cocoapods.paths.headers="${'$'}HEADER_SEARCH_PATHS" \ diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-cocoapods-template/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-cocoapods-template/build.gradle.kts index 858eb241436..c8809358b34 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-cocoapods-template/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-cocoapods-template/build.gradle.kts @@ -15,6 +15,9 @@ group = "org.jetbrains.kotlin.sample.native" version = "1.0" kotlin { + sourceSets["commonMain"].dependencies { + implementation(kotlin("stdlib-common")) + } iosX64("iOS") cocoapods { homepage = "https://github.com/JetBrains/kotlin" diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-cocoapods-template/src/commonMain/kotlin/A.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-cocoapods-template/src/commonMain/kotlin/A.kt new file mode 100644 index 00000000000..0e9dc60b2e9 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-cocoapods-template/src/commonMain/kotlin/A.kt @@ -0,0 +1,5 @@ +package testProject.`new-mpp-cocoapods-template`.src.commonMain.kotlin + +fun foo() { + println("hi!") +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt index 8525230c3a0..90a1b8f72de 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt @@ -18,6 +18,9 @@ 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.cocoapods.CocoapodsExtension.CocoapodsDependency.PodLocation.* +import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.ARCHS_PROPERTY +import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.CONFIGURATION_PROPERTY +import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.PLATFORM_PROPERTY import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType import org.jetbrains.kotlin.gradle.plugin.whenEvaluated @@ -88,8 +91,9 @@ private val CocoapodsDependency.toPodDownloadTaskName: String ) internal val Project.shouldUseSyntheticProjectSettings: Boolean - get() = (findProperty(KotlinCocoapodsPlugin.TARGET_PROPERTY) == null && - findProperty(KotlinCocoapodsPlugin.CONFIGURATION_PROPERTY) == null) + get() = (project.findProperty(PLATFORM_PROPERTY) == null && + project.findProperty(ARCHS_PROPERTY) == null && + project.findProperty(CONFIGURATION_PROPERTY) == null) private val KotlinNativeTarget.toValidSDK: String get() = when (konanTarget) { @@ -174,7 +178,7 @@ open class KotlinCocoapodsPlugin : Plugin { requestedBuildType: NativeBuildType, requestedPlatforms: List ) { - val fatTargets = requestedPlatforms.associate { it to kotlinExtension.targetsForPlatform(it) } + val fatTargets = requestedPlatforms.associateWith { kotlinExtension.targetsForPlatform(it) } check(fatTargets.values.any { it.isNotEmpty() }) { "The project must have a target for at least one of the following platforms: " + @@ -188,10 +192,10 @@ open class KotlinCocoapodsPlugin : Plugin { val fatFrameworkTask = project.registerTask("fatFramework") { task -> task.group = TASK_GROUP - task.description = "Creates a fat framework for ARM32 and ARM64 architectures" + task.description = "Creates a fat framework for requested architectures" task.destinationDir = project.cocoapodsBuildDirs.fatFramework(requestedBuildType) - fatTargets.forEach { _, targets -> + fatTargets.forEach { (_, targets) -> targets.singleOrNull()?.let { task.from(it.binaries.getFramework(POD_FRAMEWORK_PREFIX, requestedBuildType)) } @@ -221,8 +225,29 @@ open class KotlinCocoapodsPlugin : Plugin { kotlinExtension: KotlinMultiplatformExtension, cocoapodsExtension: CocoapodsExtension ) = project.whenEvaluated { - val requestedTargetName = project.findProperty(TARGET_PROPERTY)?.toString() ?: return@whenEvaluated val xcodeConfiguration = project.findProperty(CONFIGURATION_PROPERTY)?.toString() ?: return@whenEvaluated + val platforms = project.findProperty(PLATFORM_PROPERTY)?.toString()?.split(",", " ")?.filter { it.isNotBlank() } + val archs = project.findProperty(ARCHS_PROPERTY)?.toString()?.split(",", " ")?.filter { it.isNotBlank() } + + if (platforms == null || archs == null) { + check(project.findProperty(TARGET_PROPERTY) == null) { + """ + $TARGET_PROPERTY property was dropped in favor of $PLATFORM_PROPERTY and $ARCHS_PROPERTY. + Podspec file might be outdated. Sync project with Gradle files or run the 'podspec' task manually to regenerate it. + """.trimIndent() + } + return@whenEvaluated + } + + check(platforms.size == 1) { + "$PLATFORM_PROPERTY has to contain a single value only. If building for multiple platforms is required, consider using XCFrameworks" + } + + val platform = platforms.first() + + val nativeTargets = getNativeTargets(platform, archs) + + check(nativeTargets.isNotEmpty()) { "Could not identify native targets for platform: '$platform' and architectures: '$archs'" } val requestedBuildType = cocoapodsExtension.xcodeConfigurationToNativeBuildType[xcodeConfiguration] @@ -233,25 +258,95 @@ open class KotlinCocoapodsPlugin : Plugin { """.trimIndent() } - // We create a fat framework only for device platforms which have several - // device architectures: iosArm64, iosArm32, watchosArm32 and watchosArm64. - val frameworkPlatforms: List = when (requestedTargetName) { - KOTLIN_TARGET_FOR_IOS_DEVICE -> listOf(IOS_ARM64, IOS_ARM32) - KOTLIN_TARGET_FOR_WATCHOS_DEVICE -> listOf(WATCHOS_ARM32, WATCHOS_ARM64) - // A request parameter can be comma separated list of targets. - else -> requestedTargetName.split(",").map { HostManager().targetByName(it) }.toList() - } - - val frameworkTargets = frameworkPlatforms.flatMap { kotlinExtension.targetsForPlatform(it) } + val frameworkTargets = nativeTargets.flatMap { kotlinExtension.targetsForPlatform(it) } if (frameworkTargets.size == 1) { // Fast path: there is only one device target. There is no need to build a fat framework. createSyncForRegularFramework(project, kotlinExtension, requestedBuildType, frameworkTargets.single().konanTarget) } else { // There are several device targets so we need to build a fat framework. - createSyncForFatFramework(project, kotlinExtension, requestedBuildType, frameworkPlatforms) + createSyncForFatFramework(project, kotlinExtension, requestedBuildType, nativeTargets) } } + private fun getNativeTargets(platform: String, archs: List): List { + class UnknownArchitectureException(platform: String, arch: String) : + IllegalArgumentException("Architecture $arch is not supported for platform $platform") + + val targets: MutableSet = mutableSetOf() + + when (platform) { + + "iphoneos" -> { + targets.addAll(archs.map { arch -> + when (arch) { + "arm64", "arm64e" -> IOS_ARM64 + "armv7", "armv7s" -> IOS_ARM32 + else -> throw UnknownArchitectureException(platform, arch) + } + }) + } + "iphonesimulator" -> { + targets.addAll(archs.map { arch -> + when (arch) { + "arm64", "arm64e" -> IOS_SIMULATOR_ARM64 + "x86_64" -> IOS_X64 + else -> throw UnknownArchitectureException(platform, arch) + } + }) + } + "watchos" -> { + targets.addAll(archs.map { arch -> + when (arch) { + "armv7k" -> WATCHOS_ARM32 + "arm64_32" -> WATCHOS_ARM64 + else -> throw UnknownArchitectureException(platform, arch) + } + }) + } + "watchsimulator" -> { + targets.addAll(archs.map { arch -> + when (arch) { + "arm64", "arm64e" -> WATCHOS_SIMULATOR_ARM64 + "i386" -> WATCHOS_X86 + "x86_64" -> WATCHOS_X64 + else -> throw UnknownArchitectureException(platform, arch) + } + }) + } + "appletvos" -> { + targets.addAll(archs.map { arch -> + when (arch) { + "arm64", "arm64e" -> TVOS_ARM64 + else -> throw UnknownArchitectureException(platform, arch) + } + }) + } + "appletvsimulator" -> { + targets.addAll(archs.map { arch -> + when (arch) { + "arm64", "arm64e" -> TVOS_SIMULATOR_ARM64 + "x86_64" -> TVOS_X64 + else -> throw UnknownArchitectureException(platform, arch) + } + }) + } + "macosx" -> { + targets.addAll(archs.map { arch -> + when (arch) { + "arm64" -> MACOS_ARM64 + "x86_64" -> MACOS_X64 + else -> throw UnknownArchitectureException(platform, arch) + } + }) + } + + else -> throw IllegalArgumentException("Platform $platform is not supported") + } + + return targets.toList() + } + + private fun createInterops( project: Project, kotlinExtension: KotlinMultiplatformExtension, @@ -590,7 +685,9 @@ open class KotlinCocoapodsPlugin : Plugin { // We don't move these properties in PropertiesProvider because // they are not intended to be overridden in local.properties. + const val PLATFORM_PROPERTY = "kotlin.native.cocoapods.platform" const val TARGET_PROPERTY = "kotlin.native.cocoapods.target" + const val ARCHS_PROPERTY = "kotlin.native.cocoapods.archs" const val CONFIGURATION_PROPERTY = "kotlin.native.cocoapods.configuration" const val CFLAGS_PROPERTY = "kotlin.native.cocoapods.cflags" @@ -599,11 +696,6 @@ open class KotlinCocoapodsPlugin : Plugin { const val GENERATE_WRAPPER_PROPERTY = "kotlin.native.cocoapods.generate.wrapper" - // Used in Xcode script phase to indicate that the framework is being built for a device - // so we should generate a fat framework with arm32 and arm64 binaries. - const val KOTLIN_TARGET_FOR_IOS_DEVICE = "ios_arm" - const val KOTLIN_TARGET_FOR_WATCHOS_DEVICE = "watchos_arm" - val isAvailableToProduceSynthetic: Boolean by lazy { if (!HostManager.hostIsMac) { return@lazy false diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CocoapodsTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CocoapodsTasks.kt index 3dfd892d9ed..ccf0b91a487 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CocoapodsTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CocoapodsTasks.kt @@ -19,8 +19,6 @@ import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension.* import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.COCOAPODS_EXTENSION_NAME import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.GENERATE_WRAPPER_PROPERTY -import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.KOTLIN_TARGET_FOR_IOS_DEVICE -import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.KOTLIN_TARGET_FOR_WATCHOS_DEVICE import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.SYNC_TASK_NAME import org.jetbrains.kotlin.gradle.plugin.cocoapods.asValidFrameworkName import org.jetbrains.kotlin.gradle.plugin.cocoapods.cocoapodsBuildDirs @@ -132,16 +130,6 @@ open class PodspecTask : DefaultTask() { | $dependencies | - | spec.pod_target_xcconfig = { - | 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', - | 'KOTLIN_TARGET[sdk=iphoneos*]' => '$KOTLIN_TARGET_FOR_IOS_DEVICE', - | 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x64', - | 'KOTLIN_TARGET[sdk=watchos*]' => '$KOTLIN_TARGET_FOR_WATCHOS_DEVICE', - | 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64', - | 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64', - | 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64' - | } - | | spec.script_phases = [ | { | :name => 'Build $specName', @@ -151,7 +139,8 @@ open class PodspecTask : DefaultTask() { | set -ev | REPO_ROOT="${'$'}PODS_TARGET_SRCROOT" | "$gradleCommand" -p "${'$'}REPO_ROOT" $syncTask \ - | -P${KotlinCocoapodsPlugin.TARGET_PROPERTY}=${'$'}KOTLIN_TARGET \ + | -P${KotlinCocoapodsPlugin.PLATFORM_PROPERTY}=${'$'}PLATFORM_NAME \ + | -P${KotlinCocoapodsPlugin.ARCHS_PROPERTY}="${'$'}ARCHS" \ | -P${KotlinCocoapodsPlugin.CONFIGURATION_PROPERTY}=${'$'}CONFIGURATION \ | -P${KotlinCocoapodsPlugin.CFLAGS_PROPERTY}="${'$'}OTHER_CFLAGS" \ | -P${KotlinCocoapodsPlugin.HEADER_PATHS_PROPERTY}="${'$'}HEADER_SEARCH_PATHS" \