[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:
committed by
Space Team
parent
78f4d399d4
commit
b6847d0835
@@ -80,7 +80,7 @@ object PlatformInfo {
|
|||||||
&& properties.checkXcodeVersion
|
&& properties.checkXcodeVersion
|
||||||
&& requiredMajorVersion != null
|
&& requiredMajorVersion != null
|
||||||
) {
|
) {
|
||||||
val currentXcodeVersion = Xcode.findCurrent().version
|
val currentXcodeVersion = Xcode.findCurrent().version.toString()
|
||||||
val currentMajorVersion = currentXcodeVersion.splitToSequence('.').first()
|
val currentMajorVersion = currentXcodeVersion.splitToSequence('.').first()
|
||||||
if (currentMajorVersion != requiredMajorVersion) {
|
if (currentMajorVersion != requiredMajorVersion) {
|
||||||
throw IllegalStateException(
|
throw IllegalStateException(
|
||||||
|
|||||||
+2
-10
@@ -25,7 +25,7 @@ import kotlin.io.path.*
|
|||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC])
|
@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC])
|
||||||
@DisplayName("K/N cocoapods tests")
|
@DisplayName("CocoaPods plugin tests")
|
||||||
@NativeGradlePluginTests
|
@NativeGradlePluginTests
|
||||||
@GradleTestVersions(minVersion = TestVersions.Gradle.G_7_0)
|
@GradleTestVersions(minVersion = TestVersions.Gradle.G_7_0)
|
||||||
@OptIn(EnvironmentalVariablesOverride::class)
|
@OptIn(EnvironmentalVariablesOverride::class)
|
||||||
@@ -771,16 +771,8 @@ class CocoaPodsIT : KGPBaseTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("Configuration cache works in a complex scenario with Gradle 8_1")
|
|
||||||
@GradleTest
|
|
||||||
@GradleTestVersions(minVersion = TestVersions.Gradle.G_8_1)
|
|
||||||
@Disabled // will be fixed in the next step
|
|
||||||
fun testConfigurationCacheWorksInAComplexScenarioWithGradle8_1(gradleVersion: GradleVersion) {
|
|
||||||
testConfigurationCacheWorksInAComplexScenario(gradleVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
@DisplayName("Configuration cache works in a complex scenario")
|
@DisplayName("Configuration cache works in a complex scenario")
|
||||||
@GradleTestVersions(minVersion = TestVersions.Gradle.MAX_SUPPORTED)
|
@GradleTestVersions(minVersion = TestVersions.Gradle.G_7_6, maxVersion = TestVersions.Gradle.G_8_1)
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun testConfigurationCacheWorksInAComplexScenario(gradleVersion: GradleVersion) {
|
fun testConfigurationCacheWorksInAComplexScenario(gradleVersion: GradleVersion) {
|
||||||
val buildOptions = defaultBuildOptions.copy(
|
val buildOptions = defaultBuildOptions.copy(
|
||||||
|
|||||||
+2
-7
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.gradle.native
|
|||||||
|
|
||||||
import com.intellij.testFramework.TestDataFile
|
import com.intellij.testFramework.TestDataFile
|
||||||
import org.gradle.api.logging.LogLevel
|
import org.gradle.api.logging.LogLevel
|
||||||
import org.gradle.api.logging.configuration.WarningMode
|
|
||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
import org.jdom.input.SAXBuilder
|
import org.jdom.input.SAXBuilder
|
||||||
import org.jetbrains.kotlin.gradle.*
|
import org.jetbrains.kotlin.gradle.*
|
||||||
@@ -18,11 +17,7 @@ import org.jetbrains.kotlin.gradle.testbase.*
|
|||||||
import org.jetbrains.kotlin.gradle.testbase.TestVersions.Kotlin.NATIVE_STABLE_RELEASE
|
import org.jetbrains.kotlin.gradle.testbase.TestVersions.Kotlin.NATIVE_STABLE_RELEASE
|
||||||
import org.jetbrains.kotlin.gradle.util.modify
|
import org.jetbrains.kotlin.gradle.util.modify
|
||||||
import org.jetbrains.kotlin.gradle.util.runProcess
|
import org.jetbrains.kotlin.gradle.util.runProcess
|
||||||
import org.jetbrains.kotlin.gradle.utils.Xcode
|
import org.jetbrains.kotlin.konan.target.*
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
|
||||||
import org.jetbrains.kotlin.konan.target.HostManager
|
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
|
||||||
import org.jetbrains.kotlin.konan.target.presetName
|
|
||||||
import org.junit.Assume
|
import org.junit.Assume
|
||||||
import org.junit.Ignore
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@@ -364,7 +359,7 @@ class GeneralNativeIT : BaseGradleIT() {
|
|||||||
frameworkPaths.forEach { assertFileExists(it) }
|
frameworkPaths.forEach { assertFileExists(it) }
|
||||||
|
|
||||||
assertTrue(fileInWorkingDir(headerPaths[0]).readText().contains("+ (int32_t)exported"))
|
assertTrue(fileInWorkingDir(headerPaths[0]).readText().contains("+ (int32_t)exported"))
|
||||||
val xcodeMajorVersion = Xcode!!.currentVersion.major
|
val xcodeMajorVersion = Xcode.findCurrent().version.major
|
||||||
|
|
||||||
// Check that by default release frameworks have bitcode embedded.
|
// Check that by default release frameworks have bitcode embedded.
|
||||||
withNativeCommandLineArguments(":linkMainReleaseFrameworkIos") { arguments ->
|
withNativeCommandLineArguments(":linkMainReleaseFrameworkIos") { arguments ->
|
||||||
|
|||||||
+3
-3
@@ -14,10 +14,10 @@ import org.jetbrains.kotlin.gradle.testbase.extractNativeCompilerCommandLineArgu
|
|||||||
import org.jetbrains.kotlin.gradle.transformProjectWithPluginsDsl
|
import org.jetbrains.kotlin.gradle.transformProjectWithPluginsDsl
|
||||||
import org.jetbrains.kotlin.gradle.util.modify
|
import org.jetbrains.kotlin.gradle.util.modify
|
||||||
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
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.HostManager
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import org.jetbrains.kotlin.konan.target.Xcode
|
||||||
|
import org.jetbrains.kotlin.konan.target.XcodeVersion
|
||||||
import org.jetbrains.kotlin.konan.target.presetName
|
import org.jetbrains.kotlin.konan.target.presetName
|
||||||
import org.jetbrains.kotlin.konan.util.DependencyDirectories
|
import org.jetbrains.kotlin.konan.util.DependencyDirectories
|
||||||
import org.junit.Assume
|
import org.junit.Assume
|
||||||
@@ -244,7 +244,7 @@ class NativeDownloadAndPlatformLibsIT : BaseGradleIT() {
|
|||||||
|
|
||||||
if (HostManager.hostIsMac) {
|
if (HostManager.hostIsMac) {
|
||||||
// Building platform libs require Xcode 14.1
|
// Building platform libs require Xcode 14.1
|
||||||
Assume.assumeTrue(Xcode!!.currentVersion >= XcodeVersion(14, 1))
|
Assume.assumeTrue(Xcode.findCurrent().version >= XcodeVersion(14, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
with(transformNativeTestProjectWithPluginDsl("native-download-maven")) {
|
with(transformNativeTestProjectWithPluginDsl("native-download-maven")) {
|
||||||
|
|||||||
+2
-3
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.gradle.native
|
|||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.gradle.testbase.*
|
import org.jetbrains.kotlin.gradle.testbase.*
|
||||||
import org.jetbrains.kotlin.gradle.util.runProcess
|
import org.jetbrains.kotlin.gradle.util.runProcess
|
||||||
import org.jetbrains.kotlin.gradle.utils.Xcode
|
import org.jetbrains.kotlin.gradle.utils.XcodeUtils
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
import org.junit.jupiter.api.AfterAll
|
import org.junit.jupiter.api.AfterAll
|
||||||
import org.junit.jupiter.api.DisplayName
|
import org.junit.jupiter.api.DisplayName
|
||||||
@@ -21,8 +21,7 @@ import kotlin.test.assertEquals
|
|||||||
@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC])
|
@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC])
|
||||||
class NativeXcodeSimulatorTestsIT : KGPBaseTest() {
|
class NativeXcodeSimulatorTestsIT : KGPBaseTest() {
|
||||||
private val defaultIosSimulator by lazy {
|
private val defaultIosSimulator by lazy {
|
||||||
val xcode = Xcode ?: error("XCode is expected to be defined")
|
XcodeUtils.getDefaultTestDeviceId(KonanTarget.IOS_SIMULATOR_ARM64) ?: error("No simulator found for iOS ARM64")
|
||||||
xcode.getDefaultTestDeviceId(KonanTarget.IOS_SIMULATOR_ARM64) ?: error("No simulator found for iOS ARM64")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("A user-friendly error message is produced when the standalone mode is disabled and no simulator has booted")
|
@DisplayName("A user-friendly error message is produced when the standalone mode is disabled and no simulator has booted")
|
||||||
|
|||||||
+2
-1
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.enabledOnCurrentHost
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.FatFrameworkTask
|
import org.jetbrains.kotlin.gradle.tasks.FatFrameworkTask
|
||||||
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.getFile
|
||||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
import org.jetbrains.kotlin.gradle.utils.mapToFile
|
import org.jetbrains.kotlin.gradle.utils.mapToFile
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
@@ -247,7 +248,7 @@ internal abstract class FrameworkCopy : DefaultTask() {
|
|||||||
|
|
||||||
private fun copy(sourceProvider: Provider<File>) {
|
private fun copy(sourceProvider: Provider<File>) {
|
||||||
val source = sourceProvider.get()
|
val source = sourceProvider.get()
|
||||||
val destination = destinationDirectory.asFile.get()
|
val destination = destinationDirectory.getFile()
|
||||||
|
|
||||||
val destinationFile = File(destination, source.name)
|
val destinationFile = File(destination, source.name)
|
||||||
if (destinationFile.exists()) {
|
if (destinationFile.exists()) {
|
||||||
|
|||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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.plugin.mpp.apple
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.file.ConfigurableFileCollection
|
||||||
|
import org.gradle.api.file.RegularFile
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.getFile
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.onlyIfCompat
|
||||||
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
|
import org.jetbrains.kotlin.konan.target.Xcode
|
||||||
|
|
||||||
|
internal abstract class XcodeVersionTask : DefaultTask() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun locateOrRegister(project: Project): Provider<XcodeVersionTask> {
|
||||||
|
return project.rootProject.locateOrRegisterTask("xcodeVersion") { task ->
|
||||||
|
if (!HostManager.hostIsMac) {
|
||||||
|
task.onlyIfCompat("Task can be run only on MacOS") { false }
|
||||||
|
return@locateOrRegisterTask
|
||||||
|
}
|
||||||
|
|
||||||
|
// xcode-select stores a symlink to a developer dir of currently selected Xcode in "/var/db/xcode_select_link"
|
||||||
|
task.xcodeSelectLink.from("/var/db/xcode_select_link/usr/bin/xcodebuild")
|
||||||
|
|
||||||
|
// DEVELOPER_DIR may override currently selected Xcode (it's respected by xcode-select and xcrun)
|
||||||
|
task.xcodeDeveloperDir.convention(project.providers.environmentVariable("DEVELOPER_DIR"))
|
||||||
|
|
||||||
|
task.outputFile.convention(project.layout.buildDirectory.file("xcode-version.txt"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:InputFiles // @InputFiles instead of @InputFile because it allows non-existing files
|
||||||
|
abstract val xcodeSelectLink: ConfigurableFileCollection
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
@get:Optional
|
||||||
|
abstract val xcodeDeveloperDir: Property<String>
|
||||||
|
|
||||||
|
@get:OutputFile
|
||||||
|
abstract val outputFile: RegularFileProperty
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun execute() {
|
||||||
|
outputFile.getFile().writeText(Xcode.findCurrent().version.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val Provider<XcodeVersionTask>.version: Provider<RegularFile>
|
||||||
|
get() = flatMap { it.outputFile }
|
||||||
+7
-3
@@ -29,7 +29,9 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.ReadyForEx
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.KOTLIN_NATIVE_IGNORE_INCORRECT_DEPENDENCIES
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.KOTLIN_NATIVE_IGNORE_INCORRECT_DEPENDENCIES
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.artifactTypeAttribute
|
import org.jetbrains.kotlin.gradle.plugin.internal.artifactTypeAttribute
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XcodeVersionTask
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.registerEmbedAndSignAppleFrameworkTask
|
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.registerEmbedAndSignAppleFrameworkTask
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.version
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmVariant
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmVariant
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.copyAttributes
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.copyAttributes
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
||||||
@@ -46,7 +48,7 @@ import org.jetbrains.kotlin.gradle.tasks.*
|
|||||||
import org.jetbrains.kotlin.gradle.testing.internal.configureConventions
|
import org.jetbrains.kotlin.gradle.testing.internal.configureConventions
|
||||||
import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry
|
import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry
|
||||||
import org.jetbrains.kotlin.gradle.testing.testTaskName
|
import org.jetbrains.kotlin.gradle.testing.testTaskName
|
||||||
import org.jetbrains.kotlin.gradle.utils.Xcode
|
import org.jetbrains.kotlin.gradle.utils.XcodeUtils
|
||||||
import org.jetbrains.kotlin.gradle.utils.newInstance
|
import org.jetbrains.kotlin.gradle.utils.newInstance
|
||||||
import org.jetbrains.kotlin.konan.target.HostManager
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
@@ -63,6 +65,7 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
|
|||||||
// this afterEvaluate comes from NativeCompilerOptions
|
// this afterEvaluate comes from NativeCompilerOptions
|
||||||
val compilationCompilerOptions = binary.compilation.compilerOptions
|
val compilationCompilerOptions = binary.compilation.compilerOptions
|
||||||
val konanPropertiesBuildService = KonanPropertiesBuildService.registerIfAbsent(project)
|
val konanPropertiesBuildService = KonanPropertiesBuildService.registerIfAbsent(project)
|
||||||
|
val xcodeVersionTask = XcodeVersionTask.locateOrRegister(project)
|
||||||
val linkTask = registerTask<KotlinNativeLink>(
|
val linkTask = registerTask<KotlinNativeLink>(
|
||||||
binary.linkTaskName, listOf(binary)
|
binary.linkTaskName, listOf(binary)
|
||||||
) {
|
) {
|
||||||
@@ -75,6 +78,7 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
|
|||||||
it.toolOptions.freeCompilerArgs.value(compilationCompilerOptions.options.freeCompilerArgs)
|
it.toolOptions.freeCompilerArgs.value(compilationCompilerOptions.options.freeCompilerArgs)
|
||||||
it.toolOptions.freeCompilerArgs.addAll(providers.provider { PropertiesProvider(project).nativeLinkArgs })
|
it.toolOptions.freeCompilerArgs.addAll(providers.provider { PropertiesProvider(project).nativeLinkArgs })
|
||||||
it.runViaBuildToolsApi.value(false).disallowChanges() // K/N is not yet supported
|
it.runViaBuildToolsApi.value(false).disallowChanges() // K/N is not yet supported
|
||||||
|
it.xcodeVersion.set(xcodeVersionTask.version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -584,9 +588,9 @@ class KotlinNativeTargetWithSimulatorTestsConfigurator :
|
|||||||
|
|
||||||
override fun configureTestTask(target: KotlinNativeTargetWithSimulatorTests, testTask: KotlinNativeSimulatorTest) {
|
override fun configureTestTask(target: KotlinNativeTargetWithSimulatorTests, testTask: KotlinNativeSimulatorTest) {
|
||||||
super.configureTestTask(target, testTask)
|
super.configureTestTask(target, testTask)
|
||||||
if (Xcode != null) {
|
if (isTestTaskEnabled(target)) {
|
||||||
val deviceIdProvider = testTask.project.provider {
|
val deviceIdProvider = testTask.project.provider {
|
||||||
Xcode.getDefaultTestDeviceId(target.konanTarget)
|
XcodeUtils.getDefaultTestDeviceId(target.konanTarget)
|
||||||
?: error("Xcode does not support simulator tests for ${target.konanTarget.name}. Check that requested SDK is installed.")
|
?: error("Xcode does not support simulator tests for ${target.konanTarget.name}. Check that requested SDK is installed.")
|
||||||
}
|
}
|
||||||
testTask.device.convention(deviceIdProvider).finalizeValueOnRead()
|
testTask.device.convention(deviceIdProvider).finalizeValueOnRead()
|
||||||
|
|||||||
+1
-8
@@ -13,13 +13,11 @@ import org.gradle.api.Project
|
|||||||
import org.gradle.api.artifacts.Dependency
|
import org.gradle.api.artifacts.Dependency
|
||||||
import org.gradle.api.attributes.Attribute
|
import org.gradle.api.attributes.Attribute
|
||||||
import org.gradle.api.attributes.HasAttributes
|
import org.gradle.api.attributes.HasAttributes
|
||||||
import org.gradle.api.file.Directory
|
|
||||||
import org.gradle.api.file.DirectoryProperty
|
import org.gradle.api.file.DirectoryProperty
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.tasks.AbstractExecTask
|
import org.gradle.api.tasks.AbstractExecTask
|
||||||
import org.gradle.api.tasks.TaskProvider
|
import org.gradle.api.tasks.TaskProvider
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink
|
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink
|
||||||
import org.jetbrains.kotlin.gradle.utils.Xcode
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toUpperCaseAsciiOnly
|
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toUpperCaseAsciiOnly
|
||||||
@@ -280,12 +278,7 @@ class Framework(
|
|||||||
/**
|
/**
|
||||||
* Embed bitcode for the framework or not. See [BitcodeEmbeddingMode].
|
* Embed bitcode for the framework or not. See [BitcodeEmbeddingMode].
|
||||||
*/
|
*/
|
||||||
val embedBitcodeMode = project.objects.property(org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode::class.java).apply {
|
val embedBitcodeMode = project.objects.property(org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode::class.java)
|
||||||
convention(project.provider {
|
|
||||||
Xcode?.defaultBitcodeEmbeddingMode(konanTarget, buildType)
|
|
||||||
?: org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode.DISABLE
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Use 'embedBitcodeMode' property instead.")
|
@Deprecated("Use 'embedBitcodeMode' property instead.")
|
||||||
var embedBitcode: org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
|
var embedBitcode: org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
|
||||||
|
|||||||
+3
-2
@@ -48,7 +48,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.cast
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
internal val ProjectLayout.cocoapodsBuildDirs: CocoapodsBuildDirs
|
internal val ProjectLayout.cocoapodsBuildDirs: CocoapodsBuildDirs
|
||||||
get() = CocoapodsBuildDirs(this)
|
get() = CocoapodsBuildDirs(this)
|
||||||
|
|
||||||
@@ -515,6 +514,8 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
|||||||
else -> error("Unknown cocoapods platform: $family")
|
else -> error("Unknown cocoapods platform: $family")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val xcodeVersionTask = XcodeVersionTask.locateOrRegister(project)
|
||||||
|
|
||||||
val podGenTask = project.registerTask<PodGenTask>(family.toPodGenTaskName) { task ->
|
val podGenTask = project.registerTask<PodGenTask>(family.toPodGenTaskName) { task ->
|
||||||
task.description = "Сreates a synthetic Xcode project to retrieve CocoaPods dependencies"
|
task.description = "Сreates a synthetic Xcode project to retrieve CocoaPods dependencies"
|
||||||
task.podspec.set(podspecTaskProvider.map { it.outputFile })
|
task.podspec.set(podspecTaskProvider.map { it.outputFile })
|
||||||
@@ -524,7 +525,7 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
|||||||
task.family.set(family)
|
task.family.set(family)
|
||||||
task.platformSettings.set(platformSettings)
|
task.platformSettings.set(platformSettings)
|
||||||
task.pods.set(cocoapodsExtension.pods)
|
task.pods.set(cocoapodsExtension.pods)
|
||||||
task.xcodeVersion.set(Xcode?.currentVersion)
|
task.xcodeVersion.set(xcodeVersionTask.version)
|
||||||
}
|
}
|
||||||
|
|
||||||
project.registerTask<PodInstallSyntheticTask>(family.toPodInstallSyntheticTaskName) { task ->
|
project.registerTask<PodInstallSyntheticTask>(family.toPodInstallSyntheticTaskName) { task ->
|
||||||
|
|||||||
+7
-4
@@ -8,6 +8,7 @@
|
|||||||
package org.jetbrains.kotlin.gradle.targets.native.tasks
|
package org.jetbrains.kotlin.gradle.targets.native.tasks
|
||||||
|
|
||||||
import org.gradle.api.file.ProjectLayout
|
import org.gradle.api.file.ProjectLayout
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
import org.gradle.api.provider.ListProperty
|
import org.gradle.api.provider.ListProperty
|
||||||
import org.gradle.api.provider.Property
|
import org.gradle.api.provider.Property
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
@@ -15,8 +16,9 @@ import org.gradle.api.tasks.*
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension.*
|
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.cocoapodsBuildDirs
|
import org.jetbrains.kotlin.gradle.plugin.cocoapods.cocoapodsBuildDirs
|
||||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.platformLiteral
|
import org.jetbrains.kotlin.gradle.plugin.cocoapods.platformLiteral
|
||||||
import org.jetbrains.kotlin.gradle.utils.XcodeVersion
|
import org.jetbrains.kotlin.gradle.utils.parse
|
||||||
import org.jetbrains.kotlin.konan.target.Family
|
import org.jetbrains.kotlin.konan.target.Family
|
||||||
|
import org.jetbrains.kotlin.konan.target.XcodeVersion
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -52,8 +54,9 @@ abstract class PodGenTask @Inject constructor(projectLayout: ProjectLayout) : Co
|
|||||||
@get:Nested
|
@get:Nested
|
||||||
internal abstract val pods: ListProperty<CocoapodsDependency>
|
internal abstract val pods: ListProperty<CocoapodsDependency>
|
||||||
|
|
||||||
@get:Input
|
@get:Optional
|
||||||
internal abstract val xcodeVersion: Property<XcodeVersion>
|
@get:InputFile
|
||||||
|
internal abstract val xcodeVersion: RegularFileProperty
|
||||||
|
|
||||||
@get:OutputFile
|
@get:OutputFile
|
||||||
val podfile: Provider<File> = projectLayout.cocoapodsBuildDirs.synthetic(family).map { it.file("Podfile").asFile }
|
val podfile: Provider<File> = projectLayout.cocoapodsBuildDirs.synthetic(family).map { it.file("Podfile").asFile }
|
||||||
@@ -123,7 +126,7 @@ abstract class PodGenTask @Inject constructor(projectLayout: ProjectLayout) : Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun insertXcode143DeploymentTargetWorkarounds(family: Family): String {
|
private fun insertXcode143DeploymentTargetWorkarounds(family: Family): String {
|
||||||
if (xcodeVersion.get() < XcodeVersion(14, 3)) {
|
if (XcodeVersion.parse(xcodeVersion) < XcodeVersion(14, 3)) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-3
@@ -183,12 +183,18 @@ constructor(
|
|||||||
get() = embedBitcodeMode.get()
|
get() = embedBitcodeMode.get()
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
|
@get:Optional
|
||||||
val embedBitcodeMode: Provider<BitcodeEmbeddingMode> =
|
val embedBitcodeMode: Provider<BitcodeEmbeddingMode> =
|
||||||
(binary as? Framework)?.embedBitcodeMode ?: project.provider { BitcodeEmbeddingMode.DISABLE }
|
(binary as? Framework)?.embedBitcodeMode ?: objectFactory.property()
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
val apiFiles = project.files(project.configurations.getByName(compilation.apiConfigurationName)).filterKlibsPassedToCompiler()
|
val apiFiles = project.files(project.configurations.getByName(compilation.apiConfigurationName)).filterKlibsPassedToCompiler()
|
||||||
|
|
||||||
|
@get:Optional
|
||||||
|
@get:InputFile
|
||||||
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
|
internal val xcodeVersion = objectFactory.fileProperty()
|
||||||
|
|
||||||
private val externalDependenciesArgs by lazy { ExternalDependenciesBuilder(project, compilation).buildCompilerArgs() }
|
private val externalDependenciesArgs by lazy { ExternalDependenciesBuilder(project, compilation).buildCompilerArgs() }
|
||||||
|
|
||||||
private val cacheBuilderSettings by lazy {
|
private val cacheBuilderSettings by lazy {
|
||||||
@@ -224,10 +230,10 @@ constructor(
|
|||||||
args.generateTestRunner = processTests
|
args.generateTestRunner = processTests
|
||||||
args.mainPackage = entryPoint
|
args.mainPackage = entryPoint
|
||||||
|
|
||||||
when (embedBitcodeMode.get()) {
|
when (bitcodeEmbeddingMode()) {
|
||||||
BitcodeEmbeddingMode.BITCODE -> args.embedBitcode = true
|
BitcodeEmbeddingMode.BITCODE -> args.embedBitcode = true
|
||||||
BitcodeEmbeddingMode.MARKER -> args.embedBitcodeMarker = true
|
BitcodeEmbeddingMode.MARKER -> args.embedBitcodeMarker = true
|
||||||
null, BitcodeEmbeddingMode.DISABLE -> Unit
|
BitcodeEmbeddingMode.DISABLE -> Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
args.singleLinkerArguments = (linkerOpts + additionalLinkerOpts).toTypedArray()
|
args.singleLinkerArguments = (linkerOpts + additionalLinkerOpts).toTypedArray()
|
||||||
@@ -391,4 +397,8 @@ constructor(
|
|||||||
private inline fun <reified T : Any> lazyConvention(noinline lazyConventionValue: () -> T): Provider<T> {
|
private inline fun <reified T : Any> lazyConvention(noinline lazyConventionValue: () -> T): Provider<T> {
|
||||||
return objectFactory.providerWithLazyConvention(lazyConventionValue)
|
return objectFactory.providerWithLazyConvention(lazyConventionValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun bitcodeEmbeddingMode(): BitcodeEmbeddingMode {
|
||||||
|
return XcodeUtils.bitcodeEmbeddingMode(outputKind, embedBitcodeMode.orNull, xcodeVersion, konanTarget, debuggable)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -15,10 +15,11 @@ import org.jetbrains.kotlin.gradle.dsl.*
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
|
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
|
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind
|
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XcodeVersionTask
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.version
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.enabledOnCurrentHost
|
import org.jetbrains.kotlin.gradle.plugin.mpp.enabledOnCurrentHost
|
||||||
import org.jetbrains.kotlin.gradle.tasks.dependsOn
|
import org.jetbrains.kotlin.gradle.tasks.dependsOn
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
import org.jetbrains.kotlin.gradle.utils.Xcode
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
import org.jetbrains.kotlin.konan.target.presetName
|
import org.jetbrains.kotlin.konan.target.presetName
|
||||||
@@ -109,6 +110,7 @@ internal fun KotlinNativeArtifact.registerLinkFrameworkTask(
|
|||||||
): TaskProvider<KotlinNativeLinkArtifactTask> {
|
): TaskProvider<KotlinNativeLinkArtifactTask> {
|
||||||
val kind = NativeOutputKind.FRAMEWORK
|
val kind = NativeOutputKind.FRAMEWORK
|
||||||
val destinationDir = project.buildDir.resolve("$outDirName/${target.visibleName}/${buildType.visibleName}")
|
val destinationDir = project.buildDir.resolve("$outDirName/${target.visibleName}/${buildType.visibleName}")
|
||||||
|
val xcodeVersionTask = XcodeVersionTask.locateOrRegister(project)
|
||||||
val resultTask = project.registerTask<KotlinNativeLinkArtifactTask>(
|
val resultTask = project.registerTask<KotlinNativeLinkArtifactTask>(
|
||||||
lowerCamelCaseName("assemble", name, buildType.visibleName, kind.taskNameClassifier, target.presetName, taskNameSuffix),
|
lowerCamelCaseName("assemble", name, buildType.visibleName, kind.taskNameClassifier, target.presetName, taskNameSuffix),
|
||||||
listOf(target, kind.compilerOutputKind)
|
listOf(target, kind.compilerOutputKind)
|
||||||
@@ -121,11 +123,10 @@ internal fun KotlinNativeArtifact.registerLinkFrameworkTask(
|
|||||||
task.debuggable.set(buildType.debuggable)
|
task.debuggable.set(buildType.debuggable)
|
||||||
task.linkerOptions.set(linkerOptions)
|
task.linkerOptions.set(linkerOptions)
|
||||||
task.binaryOptions.set(binaryOptions)
|
task.binaryOptions.set(binaryOptions)
|
||||||
|
task.xcodeVersion.set(xcodeVersionTask.version)
|
||||||
task.staticFramework.set(isStatic)
|
task.staticFramework.set(isStatic)
|
||||||
if (embedBitcode != null) {
|
if (embedBitcode != null) {
|
||||||
task.embedBitcode.set(embedBitcode)
|
task.embedBitcode.set(embedBitcode)
|
||||||
} else if (Xcode != null) {
|
|
||||||
task.embedBitcode.set(project.provider { Xcode.defaultBitcodeEmbeddingMode(target, buildType) })
|
|
||||||
}
|
}
|
||||||
task.libraries.setFrom(project.configurations.getByName(librariesConfigurationName))
|
task.libraries.setFrom(project.configurations.getByName(librariesConfigurationName))
|
||||||
task.exportLibraries.setFrom(project.configurations.getByName(exportConfigurationName))
|
task.exportLibraries.setFrom(project.configurations.getByName(exportConfigurationName))
|
||||||
|
|||||||
+12
-2
@@ -11,6 +11,7 @@ import org.gradle.api.file.ConfigurableFileCollection
|
|||||||
import org.gradle.api.file.DirectoryProperty
|
import org.gradle.api.file.DirectoryProperty
|
||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
import org.gradle.api.file.ProjectLayout
|
import org.gradle.api.file.ProjectLayout
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
import org.gradle.api.model.ObjectFactory
|
import org.gradle.api.model.ObjectFactory
|
||||||
import org.gradle.api.provider.ListProperty
|
import org.gradle.api.provider.ListProperty
|
||||||
import org.gradle.api.provider.MapProperty
|
import org.gradle.api.provider.MapProperty
|
||||||
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
|
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.buildKotlinNativeBinaryLinkerArgs
|
import org.jetbrains.kotlin.gradle.targets.native.tasks.buildKotlinNativeBinaryLinkerArgs
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinToolTask
|
import org.jetbrains.kotlin.gradle.tasks.KotlinToolTask
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.XcodeUtils
|
||||||
import org.jetbrains.kotlin.gradle.utils.newInstance
|
import org.jetbrains.kotlin.gradle.utils.newInstance
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
@@ -73,6 +75,7 @@ abstract class KotlinNativeLinkArtifactTask @Inject constructor(
|
|||||||
abstract val staticFramework: Property<Boolean>
|
abstract val staticFramework: Property<Boolean>
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
|
@get:Optional
|
||||||
abstract val embedBitcode: Property<BitcodeEmbeddingMode>
|
abstract val embedBitcode: Property<BitcodeEmbeddingMode>
|
||||||
|
|
||||||
@get:Classpath
|
@get:Classpath
|
||||||
@@ -90,6 +93,10 @@ abstract class KotlinNativeLinkArtifactTask @Inject constructor(
|
|||||||
@get:Input
|
@get:Input
|
||||||
abstract val binaryOptions: MapProperty<String, String>
|
abstract val binaryOptions: MapProperty<String, String>
|
||||||
|
|
||||||
|
@get:Optional
|
||||||
|
@get:InputFile
|
||||||
|
abstract val xcodeVersion: RegularFileProperty
|
||||||
|
|
||||||
private val nativeBinaryOptions = PropertiesProvider(project).nativeBinaryOptions
|
private val nativeBinaryOptions = PropertiesProvider(project).nativeBinaryOptions
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
@@ -163,7 +170,6 @@ abstract class KotlinNativeLinkArtifactTask @Inject constructor(
|
|||||||
enableEndorsedLibs.value(false).finalizeValue()
|
enableEndorsedLibs.value(false).finalizeValue()
|
||||||
processTests.convention(false)
|
processTests.convention(false)
|
||||||
staticFramework.convention(false)
|
staticFramework.convention(false)
|
||||||
embedBitcode.convention(BitcodeEmbeddingMode.DISABLE)
|
|
||||||
destinationDir.convention(debuggable.flatMap {
|
destinationDir.convention(debuggable.flatMap {
|
||||||
val kind = outputKind.visibleName
|
val kind = outputKind.visibleName
|
||||||
val target = konanTarget.visibleName
|
val target = konanTarget.visibleName
|
||||||
@@ -191,7 +197,7 @@ abstract class KotlinNativeLinkArtifactTask @Inject constructor(
|
|||||||
compilerPlugins = emptyList(),//CompilerPlugins aren't needed here because it's no compilation but linking
|
compilerPlugins = emptyList(),//CompilerPlugins aren't needed here because it's no compilation but linking
|
||||||
processTests = processTests.get(),
|
processTests = processTests.get(),
|
||||||
entryPoint = entryPoint.getOrNull(),
|
entryPoint = entryPoint.getOrNull(),
|
||||||
embedBitcode = embedBitcode.get(),
|
embedBitcode = bitcodeEmbeddingMode(),
|
||||||
linkerOpts = linkerOptions.get(),
|
linkerOpts = linkerOptions.get(),
|
||||||
binaryOptions = allBinaryOptions.get(),
|
binaryOptions = allBinaryOptions.get(),
|
||||||
isStaticFramework = staticFramework.get(),
|
isStaticFramework = staticFramework.get(),
|
||||||
@@ -205,4 +211,8 @@ abstract class KotlinNativeLinkArtifactTask @Inject constructor(
|
|||||||
executionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger)
|
executionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger)
|
||||||
).run(buildArgs)
|
).run(buildArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun bitcodeEmbeddingMode(): BitcodeEmbeddingMode {
|
||||||
|
return XcodeUtils.bitcodeEmbeddingMode(outputKind, embedBitcode.orNull, xcodeVersion, konanTarget, debuggable.get())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
-100
@@ -1,100 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2022 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.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
|
|
||||||
import org.jetbrains.kotlin.konan.target.Architecture.ARM32
|
|
||||||
import org.jetbrains.kotlin.konan.target.Architecture.ARM64
|
|
||||||
import org.jetbrains.kotlin.konan.target.Family
|
|
||||||
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: XcodeVersion by lazy {
|
|
||||||
val out = runCommand(listOf("/usr/bin/xcrun", "xcodebuild", "-version"))
|
|
||||||
parseFromXcodebuild(out) ?: XcodeVersion(1, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val defaultTestDevices: Map<Family, String> by lazy {
|
|
||||||
val osRegex = "-- .* --".toRegex()
|
|
||||||
val deviceRegex = """[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}""".toRegex()
|
|
||||||
|
|
||||||
val out = runCommand(listOf("/usr/bin/xcrun", "simctl", "list", "devices", "available"))
|
|
||||||
|
|
||||||
val result = mutableMapOf<Family, String>()
|
|
||||||
var os: Family? = null
|
|
||||||
out.lines().forEach { s ->
|
|
||||||
val osFound = osRegex.find(s)?.value
|
|
||||||
if (osFound != null) {
|
|
||||||
val osName = osFound.split(" ")[1]
|
|
||||||
os = try {
|
|
||||||
Family.valueOf(osName.toUpperCaseAsciiOnly())
|
|
||||||
} catch (e: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val currentOs = os
|
|
||||||
if (currentOs != null) {
|
|
||||||
val deviceFound = deviceRegex.find(s)?.value
|
|
||||||
if (deviceFound != null) {
|
|
||||||
result[currentOs] = deviceFound
|
|
||||||
os = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getDefaultTestDeviceId(target: KonanTarget): String? = defaultTestDevices[target.family]
|
|
||||||
|
|
||||||
fun defaultBitcodeEmbeddingMode(target: KonanTarget, buildType: NativeBuildType): BitcodeEmbeddingMode {
|
|
||||||
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
|
|
||||||
NativeBuildType.DEBUG -> return BitcodeEmbeddingMode.MARKER
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return BitcodeEmbeddingMode.DISABLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.gradle.api.file.RegularFile
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
|
||||||
|
import org.jetbrains.kotlin.konan.target.*
|
||||||
|
import org.jetbrains.kotlin.konan.target.Architecture.ARM32
|
||||||
|
import org.jetbrains.kotlin.konan.target.Architecture.ARM64
|
||||||
|
import org.jetbrains.kotlin.konan.target.Family.*
|
||||||
|
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toUpperCaseAsciiOnly
|
||||||
|
|
||||||
|
@InternalKotlinGradlePluginApi
|
||||||
|
object XcodeUtils {
|
||||||
|
|
||||||
|
fun bitcodeEmbeddingMode(
|
||||||
|
outputKind: CompilerOutputKind,
|
||||||
|
userMode: BitcodeEmbeddingMode?,
|
||||||
|
xcodeVersion: Provider<RegularFile>,
|
||||||
|
target: KonanTarget,
|
||||||
|
debuggable: Boolean,
|
||||||
|
): BitcodeEmbeddingMode {
|
||||||
|
return when {
|
||||||
|
outputKind != CompilerOutputKind.FRAMEWORK -> BitcodeEmbeddingMode.DISABLE
|
||||||
|
userMode != null -> userMode
|
||||||
|
bitcodeSupported(xcodeVersion, target) -> when (debuggable) {
|
||||||
|
true -> BitcodeEmbeddingMode.MARKER
|
||||||
|
false -> BitcodeEmbeddingMode.BITCODE
|
||||||
|
}
|
||||||
|
else -> BitcodeEmbeddingMode.DISABLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bitcodeSupported(xcodeVersion: Provider<RegularFile>, target: KonanTarget): Boolean {
|
||||||
|
return XcodeVersion.parse(xcodeVersion).major < 14
|
||||||
|
&& target.family in listOf(IOS, WATCHOS, TVOS)
|
||||||
|
&& target.architecture in listOf(ARM32, ARM64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDefaultTestDeviceId(target: KonanTarget): String? = defaultTestDevices[target.family]
|
||||||
|
|
||||||
|
private val defaultTestDevices: Map<Family, String> by lazy {
|
||||||
|
if (!HostManager.hostIsMac) {
|
||||||
|
return@lazy emptyMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
val osRegex = "-- .* --".toRegex()
|
||||||
|
val deviceRegex = """[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}""".toRegex()
|
||||||
|
|
||||||
|
val out = runCommand(listOf("/usr/bin/xcrun", "simctl", "list", "devices", "available"))
|
||||||
|
|
||||||
|
val result = mutableMapOf<Family, String>()
|
||||||
|
var os: Family? = null
|
||||||
|
out.lines().forEach { s ->
|
||||||
|
val osFound = osRegex.find(s)?.value
|
||||||
|
if (osFound != null) {
|
||||||
|
val osName = osFound.split(" ")[1]
|
||||||
|
os = try {
|
||||||
|
Family.valueOf(osName.toUpperCaseAsciiOnly())
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val currentOs = os
|
||||||
|
if (currentOs != null) {
|
||||||
|
val deviceFound = deviceRegex.find(s)?.value
|
||||||
|
if (deviceFound != null) {
|
||||||
|
result[currentOs] = deviceFound
|
||||||
|
os = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun XcodeVersion.Companion.parse(file: Provider<RegularFile>): XcodeVersion {
|
||||||
|
val version = file.getFile().readText()
|
||||||
|
return parse(version) ?: error("Couldn't parse Xcode version from '$version'")
|
||||||
|
}
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("FunctionName")
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.unitTests
|
||||||
|
|
||||||
|
import org.gradle.api.file.RegularFile
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode.*
|
||||||
|
import org.jetbrains.kotlin.gradle.util.buildProject
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.XcodeUtils.bitcodeEmbeddingMode
|
||||||
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind.FRAMEWORK
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget.*
|
||||||
|
import org.jetbrains.kotlin.konan.target.XcodeVersion
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class XcodeUtilsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test bitcode embedding mode selection`() {
|
||||||
|
val project = buildProject()
|
||||||
|
|
||||||
|
fun xcode(major: Int, minor: Int): Provider<RegularFile> {
|
||||||
|
val version = XcodeVersion(major, minor).toString()
|
||||||
|
val file = project.file(version)
|
||||||
|
file.writeText(version)
|
||||||
|
return project.layout.file(project.provider { file })
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(DISABLE, bitcodeEmbeddingMode(FRAMEWORK, null, xcode(14, 1), IOS_ARM64, debuggable = true))
|
||||||
|
assertEquals(MARKER, bitcodeEmbeddingMode(FRAMEWORK, null, xcode(13, 9), IOS_ARM64, debuggable = true))
|
||||||
|
assertEquals(BITCODE, bitcodeEmbeddingMode(FRAMEWORK, null, xcode(13, 4), IOS_ARM64, debuggable = false))
|
||||||
|
assertEquals(DISABLE, bitcodeEmbeddingMode(FRAMEWORK, null, xcode(10, 3), IOS_X64, debuggable = true))
|
||||||
|
assertEquals(DISABLE, bitcodeEmbeddingMode(FRAMEWORK, null, xcode(13, 4), MACOS_ARM64, debuggable = false))
|
||||||
|
}
|
||||||
|
}
|
||||||
-31
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-8
@@ -143,16 +143,10 @@ class XcodeSimulatorExecutor(
|
|||||||
|
|
||||||
private fun downloadRuntimeFor(osName: String) {
|
private fun downloadRuntimeFor(osName: String) {
|
||||||
val version = Xcode.findCurrent().version
|
val version = Xcode.findCurrent().version
|
||||||
val versionSplit = version.split(".")
|
check(version.major >= 14) {
|
||||||
check(versionSplit.size >= 2) {
|
|
||||||
"Unrecognised version of Xcode $version was split to $versionSplit"
|
|
||||||
}
|
|
||||||
val major = versionSplit[0].toInt()
|
|
||||||
val minor = versionSplit[1].toInt()
|
|
||||||
check(major >= 14) {
|
|
||||||
"Was unable to get the required runtimes running on Xcode $version. Check the Xcode installation"
|
"Was unable to get the required runtimes running on Xcode $version. Check the Xcode installation"
|
||||||
}
|
}
|
||||||
if (minor >= 1) {
|
if (version.minor >= 1) {
|
||||||
// Option -downloadPlatform NAME available only since 14.1
|
// Option -downloadPlatform NAME available only since 14.1
|
||||||
hostExecutor.run("/usr/bin/xcrun", "xcodebuild", "-downloadPlatform", osName)
|
hostExecutor.run("/usr/bin/xcrun", "xcodebuild", "-downloadPlatform", osName)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.konan.target
|
|||||||
import org.jetbrains.kotlin.konan.properties.KonanPropertiesLoader
|
import org.jetbrains.kotlin.konan.properties.KonanPropertiesLoader
|
||||||
import org.jetbrains.kotlin.konan.properties.Properties
|
import org.jetbrains.kotlin.konan.properties.Properties
|
||||||
import org.jetbrains.kotlin.konan.util.InternalServer
|
import org.jetbrains.kotlin.konan.util.InternalServer
|
||||||
import kotlin.math.max
|
|
||||||
|
|
||||||
class AppleConfigurablesImpl(
|
class AppleConfigurablesImpl(
|
||||||
target: KonanTarget,
|
target: KonanTarget,
|
||||||
@@ -58,7 +57,7 @@ class AppleConfigurablesImpl(
|
|||||||
val xcode = Xcode.findCurrent()
|
val xcode = Xcode.findCurrent()
|
||||||
|
|
||||||
if (properties.getProperty("ignoreXcodeVersionCheck") != "true") {
|
if (properties.getProperty("ignoreXcodeVersionCheck") != "true") {
|
||||||
properties.getProperty("minimalXcodeVersion")?.let { minimalXcodeVersion ->
|
properties.getProperty("minimalXcodeVersion")?.let(XcodeVersion::parse)?.let { minimalXcodeVersion ->
|
||||||
val currentXcodeVersion = xcode.version
|
val currentXcodeVersion = xcode.version
|
||||||
checkXcodeVersion(minimalXcodeVersion, currentXcodeVersion)
|
checkXcodeVersion(minimalXcodeVersion, currentXcodeVersion)
|
||||||
}
|
}
|
||||||
@@ -68,22 +67,9 @@ class AppleConfigurablesImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkXcodeVersion(minimalVersion: String, currentVersion: String) {
|
private fun checkXcodeVersion(minimalVersion: XcodeVersion, currentVersion: XcodeVersion) {
|
||||||
// Xcode versions contain only numbers (even betas).
|
if (currentVersion < minimalVersion) {
|
||||||
// But we still split by '-' and whitespaces to take into account versions like 11.2-beta.
|
error("Unsupported Xcode version $currentVersion, minimal supported version is $minimalVersion.")
|
||||||
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.")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,35 @@ import org.jetbrains.kotlin.konan.MissingXcodeException
|
|||||||
import org.jetbrains.kotlin.konan.exec.Command
|
import org.jetbrains.kotlin.konan.exec.Command
|
||||||
import org.jetbrains.kotlin.konan.file.File
|
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 {
|
interface Xcode {
|
||||||
val toolchain: String
|
val toolchain: String
|
||||||
val macosxSdk: String
|
val macosxSdk: String
|
||||||
val iphoneosSdk: String
|
val iphoneosSdk: String
|
||||||
val iphonesimulatorSdk: String
|
val iphonesimulatorSdk: String
|
||||||
val version: String
|
val version: XcodeVersion
|
||||||
val appletvosSdk: String
|
val appletvosSdk: String
|
||||||
val appletvsimulatorSdk: String
|
val appletvsimulatorSdk: String
|
||||||
val watchosSdk: String
|
val watchosSdk: String
|
||||||
@@ -87,12 +110,14 @@ internal class CurrentXcode : Xcode {
|
|||||||
override val watchosSdk: String by lazy { getSdkPath("watchos") }
|
override val watchosSdk: String by lazy { getSdkPath("watchos") }
|
||||||
override val watchsimulatorSdk: String by lazy { getSdkPath("watchsimulator") }
|
override val watchsimulatorSdk: String by lazy { getSdkPath("watchsimulator") }
|
||||||
|
|
||||||
internal val xcodebuildVersion: String
|
internal val xcodebuildVersion: XcodeVersion
|
||||||
get() = xcrun("xcodebuild", "-version")
|
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"""")
|
get() = bash("""/usr/libexec/PlistBuddy "$(xcode-select -print-path)/../Info.plist" -c "Print :CFBundleShortVersionString"""")
|
||||||
|
.parseXcodeVersion()
|
||||||
|
|
||||||
override val version by lazy {
|
override val version by lazy {
|
||||||
try {
|
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 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 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user