[Gradle] Support configuration cache in Xcode/CocoaPods tasks with Gradle 8.1

This commit moves invocation of `xcodebuild` from configuration to execution time. This also fixes the problem with Xcode version being cached inside the daemon.

^KT-59252 Verification Pending
This commit is contained in:
Artem Daugel-Dauge
2023-06-11 21:00:20 +02:00
committed by Space Team
parent 78f4d399d4
commit b6847d0835
22 changed files with 316 additions and 211 deletions
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.konan.target
import org.jetbrains.kotlin.konan.properties.KonanPropertiesLoader
import org.jetbrains.kotlin.konan.properties.Properties
import org.jetbrains.kotlin.konan.util.InternalServer
import kotlin.math.max
class AppleConfigurablesImpl(
target: KonanTarget,
@@ -58,7 +57,7 @@ class AppleConfigurablesImpl(
val xcode = Xcode.findCurrent()
if (properties.getProperty("ignoreXcodeVersionCheck") != "true") {
properties.getProperty("minimalXcodeVersion")?.let { minimalXcodeVersion ->
properties.getProperty("minimalXcodeVersion")?.let(XcodeVersion::parse)?.let { minimalXcodeVersion ->
val currentXcodeVersion = xcode.version
checkXcodeVersion(minimalXcodeVersion, currentXcodeVersion)
}
@@ -68,22 +67,9 @@ class AppleConfigurablesImpl(
}
}
private fun checkXcodeVersion(minimalVersion: String, currentVersion: String) {
// Xcode versions contain only numbers (even betas).
// But we still split by '-' and whitespaces to take into account versions like 11.2-beta.
val minimalVersionParts = minimalVersion.split("(\\s+|\\.|-)".toRegex()).map { it.toIntOrNull() ?: 0 }
val currentVersionParts = currentVersion.split("(\\s+|\\.|-)".toRegex()).map { it.toIntOrNull() ?: 0 }
val size = max(minimalVersionParts.size, currentVersionParts.size)
for (i in 0 until size) {
val currentPart = currentVersionParts.getOrElse(i) { 0 }
val minimalPart = minimalVersionParts.getOrElse(i) { 0 }
when {
currentPart > minimalPart -> return
currentPart < minimalPart ->
error("Unsupported Xcode version $currentVersion, minimal supported version is $minimalVersion.")
}
private fun checkXcodeVersion(minimalVersion: XcodeVersion, currentVersion: XcodeVersion) {
if (currentVersion < minimalVersion) {
error("Unsupported Xcode version $currentVersion, minimal supported version is $minimalVersion.")
}
}
@@ -21,12 +21,35 @@ import org.jetbrains.kotlin.konan.MissingXcodeException
import org.jetbrains.kotlin.konan.exec.Command
import org.jetbrains.kotlin.konan.file.File
data class XcodeVersion(val major: Int, val minor: Int) : Comparable<XcodeVersion> {
override fun compareTo(other: XcodeVersion): Int {
return when (val majorComparison = major.compareTo(other.major)) {
0 -> minor.compareTo(other.minor)
else -> majorComparison
}
}
override fun toString(): String {
return "$major.$minor"
}
companion object {
fun parse(version: String): XcodeVersion? {
val split = version.split("(\\s+|\\.|-)".toRegex())
return XcodeVersion(
major = split[0].toIntOrNull() ?: return null,
minor = split.getOrNull(1)?.toIntOrNull() ?: return null,
)
}
}
}
interface Xcode {
val toolchain: String
val macosxSdk: String
val iphoneosSdk: String
val iphonesimulatorSdk: String
val version: String
val version: XcodeVersion
val appletvosSdk: String
val appletvsimulatorSdk: String
val watchosSdk: String
@@ -87,12 +110,14 @@ internal class CurrentXcode : Xcode {
override val watchosSdk: String by lazy { getSdkPath("watchos") }
override val watchsimulatorSdk: String by lazy { getSdkPath("watchsimulator") }
internal val xcodebuildVersion: String
internal val xcodebuildVersion: XcodeVersion
get() = xcrun("xcodebuild", "-version")
.removePrefix("Xcode ")
.removePrefix("Xcode ")
.parseXcodeVersion()
internal val bundleVersion: String
internal val bundleVersion: XcodeVersion
get() = bash("""/usr/libexec/PlistBuddy "$(xcode-select -print-path)/../Info.plist" -c "Print :CFBundleShortVersionString"""")
.parseXcodeVersion()
override val version by lazy {
try {
@@ -119,4 +144,8 @@ internal class CurrentXcode : Xcode {
private fun bash(command: String): String = Command("/bin/bash", "-c", command).getOutputLines().joinToString("\n")
private fun getSdkPath(sdk: String) = xcrun("--sdk", sdk, "--show-sdk-path")
private fun String.parseXcodeVersion(): XcodeVersion {
return XcodeVersion.parse(this) ?: throw MissingXcodeException("Couldn't parse Xcode version from '$this'")
}
}
@@ -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.konan.target
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.*
class XcodeVersionTest {
@Test
fun `xcode version parsed correctly`() {
assertEquals(XcodeVersion(14, 1), XcodeVersion.parse("14.1\nBuild version 14B47b\n"))
assertEquals(XcodeVersion(14, 3), XcodeVersion.parse("14.3\nBuild version 14E222b\n"))
assertEquals(XcodeVersion(1, 0), XcodeVersion.parse("1.0 RC\nBuild version 7B85\n"))
assertEquals(XcodeVersion(1, 15), XcodeVersion.parse("1.15-RC\nBuild version 7B85\n"))
assertEquals(XcodeVersion(14, 1), XcodeVersion.parse("14.1.1.3.2.1.123"))
assertEquals(null, XcodeVersion.parse("14\nBuild version 14B47b\n"))
assertEquals(null, XcodeVersion.parse("13"))
}
@Test
fun `test xcode version comparison`() {
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))
}
}