[Gradle] Add workarounds in CocoaPods plugin for compatibility with Xcode 14.3

Raise deployment target for 3rd-party pods if it's less then minimal supported by the new Xcode

^KT-57539 Verification Pending
This commit is contained in:
Artem Daugel-Dauge
2023-05-16 14:57:48 +02:00
committed by Space Team
parent f7acbb5252
commit ca0b0e61e8
12 changed files with 125 additions and 31 deletions
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.gradle.native
import org.gradle.api.logging.configuration.WarningMode
import org.jetbrains.kotlin.gradle.*
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.DUMMY_FRAMEWORK_TASK_NAME
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_BUILD_TASK_NAME
@@ -1742,6 +1741,7 @@ class CocoaPodsIT : BaseGradleIT() {
spec.summary = 'CocoaPods test library'
spec.vendored_frameworks = 'build/cocoapods/framework/${frameworkName ?: "kotlin_library"}.framework'
spec.libraries = 'c++'
spec.ios.deployment_target = '11.0'
spec.dependency 'pod_dependency', '1.0'
spec.dependency 'subspec_dependency/Core', '1.0'
spec.pod_target_xcconfig = {
@@ -364,7 +364,7 @@ class GeneralNativeIT : BaseGradleIT() {
frameworkPaths.forEach { assertFileExists(it) }
assertTrue(fileInWorkingDir(headerPaths[0]).readText().contains("+ (int32_t)exported"))
val xcodeMajorVersion = Xcode!!.currentVersion.split(".")[0].toInt()
val xcodeMajorVersion = Xcode!!.currentVersion.major
// Check that by default release frameworks have bitcode embedded.
withNativeCommandLineArguments(":linkMainReleaseFrameworkIos") { arguments ->
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.gradle.transformProjectWithPluginsDsl
import org.jetbrains.kotlin.gradle.util.modify
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
import org.jetbrains.kotlin.gradle.utils.Xcode
import org.jetbrains.kotlin.gradle.utils.XcodeVersion
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.target.presetName
@@ -252,15 +253,8 @@ class NativeDownloadAndPlatformLibsIT : BaseGradleIT() {
Assume.assumeTrue(maven != MAVEN_CENTRAL)
if (HostManager.hostIsMac) {
val xcodeVersion = Xcode!!.currentVersion
val versionSplit = xcodeVersion.split("(\\s+|\\.|-)".toRegex())
check(versionSplit.size >= 2) {
"Unrecognised version of Xcode $xcodeVersion was split to $versionSplit"
}
val major = versionSplit[0].toInt()
val minor = versionSplit[1].toInt()
// Building platform libs require Xcode 14.1
Assume.assumeTrue(major >= 14 && minor >= 1)
Assume.assumeTrue(Xcode!!.currentVersion >= XcodeVersion(14, 1))
}
with(transformNativeTestProjectWithPluginDsl("native-download-maven")) {
@@ -22,5 +22,7 @@ kotlin {
homepage = "https://github.com/JetBrains/kotlin"
pod("pod_dependency", "1.0", project.file("../pod_dependency"))
pod("subspec_dependency/Core", "1.0", project.file("../subspec_dependency"))
ios.deploymentTarget = "11.0"
}
}
@@ -7,4 +7,4 @@ target 'ios-app' do
pod 'subspec_dependency', :path => '../subspec_dependency'
pod 'kotlin_library', :path => '../kotlin-library'
#import_pod_directive
end
end
@@ -24,5 +24,7 @@ kotlin {
pod("pod_dependency", "1.0", project.file("../pod_dependency/pod_dependency.podspec"))
pod("subspec_dependency/Core", "1.0", project.file("../subspec_dependency"))
podfile = project.file("../ios-app/Podfile")
ios.deploymentTarget = "11.0"
}
}
@@ -8,4 +8,6 @@ Pod::Spec.new do |spec|
spec.summary = 'foo'
spec.source_files = 'src/*'
spec.public_header_files = 'src/*.h'
spec.ios.deployment_target = '11.0'
end
@@ -12,4 +12,6 @@ Pod::Spec.new do |spec|
core.source_files = "src/*"
core.public_header_files = "src/*.h"
end
spec.ios.deployment_target = '11.0'
end
@@ -537,6 +537,7 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
task.family.set(family)
task.platformSettings.set(platformSettings)
task.pods.set(cocoapodsExtension.pods)
task.xcodeVersion.set(Xcode?.currentVersion)
}
project.registerTask<PodInstallSyntheticTask>(family.toPodInstallSyntheticTaskName) { task ->
@@ -14,6 +14,7 @@ import org.gradle.api.tasks.*
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension.*
import org.jetbrains.kotlin.gradle.plugin.cocoapods.cocoapodsBuildDirs
import org.jetbrains.kotlin.gradle.plugin.cocoapods.platformLiteral
import org.jetbrains.kotlin.gradle.utils.XcodeVersion
import org.jetbrains.kotlin.konan.target.Family
import java.io.File
@@ -49,6 +50,9 @@ abstract class PodGenTask : CocoapodsTask() {
@get:Nested
internal abstract val pods: ListProperty<CocoapodsDependency>
@get:Input
internal abstract val xcodeVersion: Property<XcodeVersion>
@get:OutputFile
val podfile: Provider<File> = family.map { project.cocoapodsBuildDirs.synthetic(it).resolve("Podfile") }
@@ -59,18 +63,18 @@ abstract class PodGenTask : CocoapodsTask() {
val podfile = this.podfile.get()
podfile.createNewFile()
val podfileContent = getPodfileContent(specRepos, family.get().platformLiteral)
val podfileContent = getPodfileContent(specRepos, family.get())
podfile.writeText(podfileContent)
}
private fun getPodfileContent(specRepos: Collection<String>, xcodeTarget: String) =
private fun getPodfileContent(specRepos: Collection<String>, family: Family) =
buildString {
specRepos.forEach {
appendLine("source '$it'")
}
appendLine("target '$xcodeTarget' do")
appendLine("target '${family.platformLiteral}' do")
if (useLibraries.get().not()) {
appendLine("\tuse_frameworks!")
}
@@ -97,20 +101,55 @@ abstract class PodGenTask : CocoapodsTask() {
}
}.forEach { appendLine("\t$it") }
appendLine("end\n")
//disable signing for all synthetic pods KT-54314
append(
appendLine(
"""
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = ""
config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"
config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"
end
end
end
""".trimIndent()
|post_install do |installer|
| installer.pods_project.targets.each do |target|
| target.build_configurations.each do |config|
|
| # Disable signing for all synthetic pods KT-54314
| config.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = ""
| config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"
| config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"
| ${insertXcode143DeploymentTargetWorkarounds(family)}
| end
| end
|end
""".trimMargin()
)
appendLine()
}
}
private fun insertXcode143DeploymentTargetWorkarounds(family: Family): String {
if (xcodeVersion.get() < XcodeVersion(14, 3)) {
return ""
}
class Spec(val property: String, val major: Int, val minor: Int)
val minDeploymentTargetSpec = when (family) {
Family.IOS -> Spec("IPHONEOS_DEPLOYMENT_TARGET", 11, 0)
Family.OSX -> Spec("MACOSX_DEPLOYMENT_TARGET", 10, 13)
Family.TVOS -> Spec("TVOS_DEPLOYMENT_TARGET", 11, 0)
Family.WATCHOS -> Spec("WATCHOS_DEPLOYMENT_TARGET", 4, 0)
else -> error("Family $family is not an Apple platform")
}
return minDeploymentTargetSpec.run {
"""
|
| deployment_target_split = config.build_settings['$property']&.split('.')
| deployment_target_major = deployment_target_split&.first&.to_i
| deployment_target_minor = deployment_target_split&.second&.to_i
|
| if deployment_target_major && deployment_target_minor then
| if deployment_target_major < $major || (deployment_target_major == $major && deployment_target_minor < $minor) then
| version = "#{$major}.#{$minor}"
| puts "Deployment target for #{target} #{config} has been raised to #{version}. See KT-57741 for more details"
| config.build_settings['$property'] = version
| end
| end
""".trimMargin()
}
}
}
@@ -15,21 +15,42 @@ import org.jetbrains.kotlin.konan.target.Family.*
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toUpperCaseAsciiOnly
import java.io.Serializable
@InternalKotlinGradlePluginApi
val Xcode = XcodeUtils.INSTANCE
@InternalKotlinGradlePluginApi
data class XcodeVersion(val major: Int, val minor: Int) : Serializable, Comparable<XcodeVersion> {
override fun compareTo(other: XcodeVersion): Int {
return when (val majorComparison = major.compareTo(other.major)) {
0 -> minor.compareTo(other.minor)
else -> majorComparison
}
}
}
@InternalKotlinGradlePluginApi
class XcodeUtils private constructor() {
companion object {
internal val INSTANCE: XcodeUtils? =
if (HostManager.hostIsMac) XcodeUtils() else null
internal fun parseFromXcodebuild(output: String): XcodeVersion? {
val version = output.lines()[0].removePrefix("Xcode ")
val split = version.split("(\\s+|\\.|-)".toRegex())
return XcodeVersion(
major = split[0].toIntOrNull() ?: return null,
minor = split.getOrNull(1)?.toIntOrNull() ?: return null,
)
}
}
val currentVersion: String by lazy {
val currentVersion: XcodeVersion by lazy {
val out = runCommand(listOf("/usr/bin/xcrun", "xcodebuild", "-version"))
out.lines()[0].removePrefix("Xcode ")
parseFromXcodebuild(out) ?: XcodeVersion(1, 0)
}
private val defaultTestDevices: Map<Family, String> by lazy {
@@ -66,7 +87,7 @@ class XcodeUtils private constructor() {
fun getDefaultTestDeviceId(target: KonanTarget): String? = defaultTestDevices[target.family]
fun defaultBitcodeEmbeddingMode(target: KonanTarget, buildType: NativeBuildType): BitcodeEmbeddingMode {
if (currentVersion.split(".")[0].toInt() < 14) {
if (currentVersion.major < 14) {
if (target.family in listOf(IOS, WATCHOS, TVOS) && target.architecture in listOf(ARM32, ARM64)) {
when (buildType) {
NativeBuildType.RELEASE -> return BitcodeEmbeddingMode.BITCODE
@@ -0,0 +1,31 @@
/*
* 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.utils
import org.junit.Test
import kotlin.test.assertEquals
class XcodeVersionTest {
@Test
fun testParsing() {
assertEquals(XcodeVersion(14, 1), XcodeUtils.parseFromXcodebuild("Xcode 14.1\nBuild version 14B47b\n"))
assertEquals(XcodeVersion(14, 3), XcodeUtils.parseFromXcodebuild("Xcode 14.3\nBuild version 14E222b\n"))
assertEquals(XcodeVersion(1, 0), XcodeUtils.parseFromXcodebuild("Xcode 1.0 RC\nBuild version 7B85\n"))
assertEquals(XcodeVersion(1, 15), XcodeUtils.parseFromXcodebuild("Xcode 1.15-RC\nBuild version 7B85\n"))
assertEquals(XcodeVersion(14, 1), XcodeUtils.parseFromXcodebuild("Xcode 14.1.1.3.2.1.123\nBuild version 14B47b\n"))
assertEquals(null, XcodeUtils.parseFromXcodebuild("Xcode 14\nBuild version 14B47b\n"))
assertEquals(null, XcodeUtils.parseFromXcodebuild("XC 14.1\nBuild version 14B47b\n"))
}
@Test
fun testComparison() {
assert(XcodeVersion(3, 2) == XcodeVersion(3, 2))
assert(XcodeVersion(3, 2) > XcodeVersion(2, 14))
assert(XcodeVersion(3, 2) > XcodeVersion(3, 1))
assert(XcodeVersion(3, 2) < XcodeVersion(3, 3))
assert(XcodeVersion(4, 0) > XcodeVersion(3, 3))
}
}