[Gradle] Xcode version too high warning

Adds new warning diagnostic that checks that selected Xcode version is not higher than latest tested with the current Kotlin version

^KT-62373 Verification Pending
This commit is contained in:
Artem Daugel-Dauge
2024-01-15 10:02:26 +01:00
committed by Space Team
parent e822375461
commit fff5a412ec
21 changed files with 199 additions and 95 deletions
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.gradle.native
import org.gradle.api.JavaVersion
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.testbase.TestVersions.Gradle
import org.jetbrains.kotlin.gradle.util.replaceText
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.condition.OS
@@ -19,7 +21,7 @@ import kotlin.io.path.*
@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC])
@DisplayName("Tests for K/N with Apple Framework")
@GradleTestVersions(minVersion = TestVersions.Gradle.G_7_0)
@GradleTestVersions(minVersion = Gradle.G_7_0)
@NativeGradlePluginTests
class AppleFrameworkIT : KGPBaseTest() {
@@ -576,6 +578,23 @@ class AppleFrameworkIT : KGPBaseTest() {
}
}
}
// Should always be green because the CI Xcode version must be supported
@DisplayName("Xcode version too high diagnostic isn't emitted")
@GradleTest
@GradleTestVersions(minVersion = Gradle.G_7_4)
fun testXcodeVersionTooHighDiagnosticNotEmitted(gradleVersion: GradleVersion) {
nativeProject(
"sharedAppleFramework",
gradleVersion,
// enable CC to make sure that external process isn't run during configuration
buildOptions = defaultBuildOptions.copy(configurationCache = true),
) {
build(":shared:linkReleaseFrameworkIosSimulatorArm64") {
assertNoDiagnostic(KotlinToolingDiagnostics.XcodeVersionTooHighWarning)
}
}
}
}
private val GradleProject.darwinBuildProductsDir: Path
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.gradle.native
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.targets.native.cocoapods.CocoapodsPluginDiagnostics
import org.junit.jupiter.api.DisplayName
@@ -47,6 +48,8 @@ class AppleFrameworkNonMacIT : KGPBaseTest() {
assertTasksSkipped(":shared:linkDebugFrameworkWatchosX64")
assertTasksSkipped(":shared:assembleDebugWatchosFatFrameworkForSharedXCFramework")
assertTasksSkipped(":shared:assembleSharedDebugXCFramework")
assertNoDiagnostic(KotlinToolingDiagnostics.XcodeVersionTooHighWarning)
}
}
}
@@ -520,6 +520,9 @@ internal class PropertiesProvider private constructor(private val project: Proje
val appleCopyFrameworkToBuiltProductsDir: Boolean
get() = booleanProperty(PropertyNames.KOTLIN_APPLE_COPY_FRAMEWORK_TO_BUILT_PRODUCTS_DIR) ?: true
val appleIgnoreXcodeVersionCompatibility: Boolean
get() = booleanProperty(PropertyNames.KOTLIN_APPLE_XCODE_COMPATIBILITY_NOWARN) ?: false
/**
* Enables kotlin native toolchain in native projects.
*/
@@ -673,6 +676,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
val KOTLIN_PROJECT_PERSISTENT_DIR_GRADLE_DISABLE_WRITE = property("kotlin.project.persistent.dir.gradle.disableWrite")
val KOTLIN_NATIVE_TOOLCHAIN_ENABLED = property("kotlin.native.toolchain.enabled")
val KOTLIN_APPLE_COPY_FRAMEWORK_TO_BUILT_PRODUCTS_DIR = property("kotlin.apple.copyFrameworkToBuiltProductsDir")
val KOTLIN_APPLE_XCODE_COMPATIBILITY_NOWARN = property("kotlin.apple.xcodeCompatibility.nowarn")
val KOTLIN_APPLE_COCOAPODS_EXECUTABLE = property("kotlin.apple.cocoapods.bin")
val KOTLIN_SWIFT_EXPORT_ENABLED = property("kotlin.swift-export.enabled")
@@ -209,7 +209,7 @@ object KotlinToolingDiagnostics {
Kotlin Multiplatform <-> Android Gradle Plugin compatibility issue:
The applied Android Gradle Plugin version ($androidGradlePluginVersionString) is higher
than the maximum known to the Kotlin Gradle Plugin.
Tooling stability in such configuration isn't tested, please report encountered issues to https://kotl.in/issue"
Tooling stability in such configuration isn't tested, please report encountered issues to https://kotl.in/issue
Minimum supported Android Gradle Plugin version: $minSupported
Maximum tested Android Gradle Plugin version: $maxTested
@@ -784,6 +784,20 @@ object KotlinToolingDiagnostics {
""".trimIndent()
)
}
object XcodeVersionTooHighWarning : ToolingDiagnosticFactory(WARNING) {
operator fun invoke(xcodeVersionString: String, maxTested: String) = build(
"""
Kotlin <-> Xcode compatibility issue:
The selected Xcode version ($xcodeVersionString) is higher than the maximum known to the Kotlin Gradle Plugin.
Stability in such configuration hasn't been tested, please report encountered issues to https://kotl.in/issue
Maximum tested Xcode version: $maxTested
To suppress this message add '${PropertiesProvider.PropertyNames.KOTLIN_APPLE_XCODE_COMPATIBILITY_NOWARN}=true' to your gradle.properties
""".trimIndent()
)
}
}
private fun String.indentLines(nSpaces: Int = 4, skipFirstLine: Boolean = true): String {
@@ -37,14 +37,11 @@ internal abstract class KotlinToolingDiagnosticsCollector : BuildService<BuildSe
}
fun report(task: UsesKotlinToolingDiagnostics, diagnostic: ToolingDiagnostic) {
val options = task.diagnosticRenderingOptions.get()
if (!diagnostic.isSuppressed(options)) {
renderReportedDiagnostic(diagnostic, task.logger, options)
}
report(task, task.logger, diagnostic)
}
fun report(transform: TransformActionUsingKotlinToolingDiagnostics<*>, logger: Logger, diagnostic: ToolingDiagnostic) {
val options = transform.parameters.diagnosticRenderingOptions.get()
fun report(from: UsesKotlinToolingDiagnosticsParameters, logger: Logger, diagnostic: ToolingDiagnostic) {
val options = from.diagnosticRenderingOptions.get()
if (!diagnostic.isSuppressed(options)) {
renderReportedDiagnostic(diagnostic, logger, options)
}
@@ -9,19 +9,22 @@ import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.artifacts.transform.TransformAction
import org.gradle.api.artifacts.transform.TransformParameters
import org.gradle.api.artifacts.transform.TransformSpec
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
import org.gradle.api.provider.Property
import org.gradle.api.services.BuildService
import org.gradle.api.services.BuildServiceParameters
import org.gradle.api.tasks.Internal
internal interface UsesKotlinToolingDiagnostics : Task {
internal interface UsesKotlinToolingDiagnosticsParameters {
@get:Internal
val toolingDiagnosticsCollector: Property<KotlinToolingDiagnosticsCollector>
@get:Internal
val diagnosticRenderingOptions: Property<ToolingDiagnosticRenderingOptions>
}
internal interface UsesKotlinToolingDiagnostics : UsesKotlinToolingDiagnosticsParameters, Task {
fun reportDiagnostic(diagnostic: ToolingDiagnostic) {
toolingDiagnosticsCollector.get().report(this, diagnostic)
}
@@ -29,20 +32,14 @@ internal interface UsesKotlinToolingDiagnostics : Task {
/**
* Use this interface to make your [TransformAction] able to report [ToolingDiagnostic].
* You must use [setupTransformActionToolingDiagnostics] to set up [TransformActionUsingKotlinToolingDiagnostics.Parameters].
* You must use [setupKotlinToolingDiagnosticsParameters] to set up the parameters.
*/
internal interface TransformActionUsingKotlinToolingDiagnostics<P : TransformActionUsingKotlinToolingDiagnostics.Parameters> :
TransformAction<P> {
interface Parameters : TransformParameters {
@get:Internal
val toolingDiagnosticsCollector: Property<KotlinToolingDiagnosticsCollector>
@get:Internal
val diagnosticRenderingOptions: Property<ToolingDiagnosticRenderingOptions>
}
interface Parameters : TransformParameters, UsesKotlinToolingDiagnosticsParameters
fun reportDiagnostic(diagnostic: ToolingDiagnostic) {
parameters.toolingDiagnosticsCollector.get().report(this, logger, diagnostic)
parameters.toolingDiagnosticsCollector.get().report(parameters, logger, diagnostic)
}
companion object {
@@ -50,7 +47,24 @@ internal interface TransformActionUsingKotlinToolingDiagnostics<P : TransformAct
}
}
internal fun TransformSpec<out TransformActionUsingKotlinToolingDiagnostics.Parameters>.setupTransformActionToolingDiagnostics(project: Project) {
parameters.toolingDiagnosticsCollector.set(project.kotlinToolingDiagnosticsCollectorProvider)
parameters.diagnosticRenderingOptions.set(ToolingDiagnosticRenderingOptions.forProject(project))
/**
* Use this interface to make your [BuildService] able to report [ToolingDiagnostic].
* You must use [setupKotlinToolingDiagnosticsParameters] to set up the parameters.
*/
internal interface BuildServiceUsingKotlinToolingDiagnostics<P : BuildServiceUsingKotlinToolingDiagnostics.Parameters> :
BuildService<P> {
interface Parameters : BuildServiceParameters, UsesKotlinToolingDiagnosticsParameters
fun reportDiagnostic(diagnostic: ToolingDiagnostic) {
parameters.toolingDiagnosticsCollector.get().report(parameters, logger, diagnostic)
}
companion object {
internal val logger: Logger = Logging.getLogger(Project::class.java)
}
}
internal fun UsesKotlinToolingDiagnosticsParameters.setupKotlinToolingDiagnosticsParameters(project: Project) {
toolingDiagnosticsCollector.set(project.kotlinToolingDiagnosticsCollectorProvider)
diagnosticRenderingOptions.set(ToolingDiagnosticRenderingOptions.forProject(project))
}
@@ -0,0 +1,52 @@
/*
* 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.Project
import org.gradle.api.logging.Logging
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.diagnostics.BuildServiceUsingKotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.XcodeVersionTooHighWarning
import org.jetbrains.kotlin.gradle.plugin.diagnostics.setupKotlinToolingDiagnosticsParameters
import org.jetbrains.kotlin.gradle.utils.registerClassLoaderScopedBuildService
import org.jetbrains.kotlin.konan.target.Xcode
import org.jetbrains.kotlin.konan.target.XcodeVersion
internal abstract class XcodeVersionService : BuildServiceUsingKotlinToolingDiagnostics<XcodeVersionService.Parameters> {
interface Parameters : BuildServiceUsingKotlinToolingDiagnostics.Parameters {
val ignoreVersionCompatibilityCheck: Property<Boolean>
}
companion object {
fun registerIfAbsent(project: Project): Provider<XcodeVersionService> {
return project.gradle.registerClassLoaderScopedBuildService(XcodeVersionService::class) { spec ->
spec.parameters.setupKotlinToolingDiagnosticsParameters(project)
spec.parameters.ignoreVersionCompatibilityCheck.convention(project.kotlinPropertiesProvider.appleIgnoreXcodeVersionCompatibility)
}
}
}
private val logger = Logging.getLogger(this::class.java)
val version: XcodeVersion by lazy {
Xcode.findCurrent().version.also(::checkVersionCompatibility)
}
private fun checkVersionCompatibility(xcodeVersion: XcodeVersion) = with(parameters) {
if (!ignoreVersionCompatibilityCheck.get() && xcodeVersion > XcodeVersion.maxTested) {
toolingDiagnosticsCollector.get().report(
this, logger,
XcodeVersionTooHighWarning(
xcodeVersionString = xcodeVersion.toString(),
maxTested = XcodeVersion.maxTested.toString(),
)
)
}
}
}
@@ -7,30 +7,67 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.apple
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.Task
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.gradle.work.DisableCachingByDefault
import org.jetbrains.kotlin.gradle.plugin.KotlinProjectSetupAction
import org.jetbrains.kotlin.gradle.plugin.launch
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
import org.jetbrains.kotlin.gradle.tasks.withType
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
import org.jetbrains.kotlin.konan.target.XcodeVersion
internal val XcodeVersionSetupAction = KotlinProjectSetupAction {
launch {
val xcodeVersionTask = XcodeVersionTask.locateOrRegister(this@KotlinProjectSetupAction)
tasks.withType<UsesXcodeVersion>().configureEach { task ->
task._xcodeVersion.set(xcodeVersionTask.flatMap { it.outputFile })
}
}
}
internal interface UsesXcodeVersion : Task {
@Suppress("PropertyName")
@get:PathSensitive(PathSensitivity.RELATIVE)
@get:Optional
@get:InputFile
val _xcodeVersion: RegularFileProperty
@get:Internal
val xcodeVersion: XcodeVersion?
get() = if (HostManager.hostIsMac) {
val version = _xcodeVersion.getFile().readText()
XcodeVersion.parse(version) ?: error("Couldn't parse Xcode version from '$version'")
} else {
null
}
}
@DisableCachingByDefault
internal abstract class XcodeVersionTask : DefaultTask() {
companion object {
fun locateOrRegister(project: Project): Provider<XcodeVersionTask> {
return project.rootProject.locateOrRegisterTask("xcodeVersion") { task ->
return project.locateOrRegisterTask("xcodeVersion") { task ->
if (!HostManager.hostIsMac) {
task.onlyIfCompat("Task can be run only on MacOS") { false }
return@locateOrRegisterTask
}
val service = XcodeVersionService.registerIfAbsent(project)
task.usesService(service)
task.service.convention(service)
// 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")
@@ -42,6 +79,9 @@ internal abstract class XcodeVersionTask : DefaultTask() {
}
}
@get:Internal
abstract val service: Property<XcodeVersionService>
@get:PathSensitive(PathSensitivity.ABSOLUTE)
@get:InputFiles // @InputFiles instead of @InputFile because it allows non-existing files
abstract val xcodeSelectLink: ConfigurableFileCollection
@@ -51,13 +91,11 @@ internal abstract class XcodeVersionTask : DefaultTask() {
abstract val xcodeDeveloperDir: Property<String>
@get:OutputFile
@get:Optional
abstract val outputFile: RegularFileProperty
@TaskAction
fun execute() {
outputFile.getFile().writeText(Xcode.findCurrent().version.toString())
outputFile.getFile().writeText(service.get().version.toString())
}
}
internal val Provider<XcodeVersionTask>.version: Provider<RegularFile>
get() = flatMap { it.outputFile }
}
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImportSetupAction
import org.jetbrains.kotlin.gradle.plugin.ide.IdeResolveDependenciesTaskSetupAction
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.AddBuildListenerForXCodeSetupAction
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XcodeVersionSetupAction
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.*
import org.jetbrains.kotlin.gradle.plugin.mpp.internal.DeprecatedMppGradlePropertiesMigrationSetupAction
import org.jetbrains.kotlin.gradle.plugin.mpp.resources.RegisterMultiplatformResourcesPublicationExtensionAction
@@ -72,6 +73,7 @@ internal fun Project.registerKotlinPluginExtensions() {
register(project, IdeMultiplatformImportSetupAction)
register(project, IdeResolveDependenciesTaskSetupAction)
register(project, CInteropCommonizedCInteropApiElementsConfigurationsSetupAction)
register(project, XcodeVersionSetupAction)
register(project, AddBuildListenerForXCodeSetupAction)
register(project, CreateFatFrameworksSetupAction)
register(project, KotlinRegisterCompilationArchiveTasksExtension)
@@ -16,8 +16,6 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.launchInStage
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XcodeVersionTask
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.version
import org.jetbrains.kotlin.gradle.targets.KotlinTargetSideEffect
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink
import org.jetbrains.kotlin.gradle.tasks.dependsOn
@@ -77,7 +75,7 @@ private fun Project.createLinkTask(binary: NativeBinary) {
// this afterEvaluate comes from NativeCompilerOptions
@Suppress("DEPRECATION") val compilationCompilerOptions = binary.compilation.compilerOptions
val konanPropertiesBuildService = KonanPropertiesBuildService.registerIfAbsent(project)
val xcodeVersionTask = XcodeVersionTask.locateOrRegister(project)
val linkTask = registerTask<KotlinNativeLink>(
binary.linkTaskName, listOf(binary)
) { task ->
@@ -93,7 +91,6 @@ private fun Project.createLinkTask(binary: NativeBinary) {
task.toolOptions.freeCompilerArgs.value(compilationCompilerOptions.options.freeCompilerArgs)
task.toolOptions.freeCompilerArgs.addAll(providers.provider { PropertiesProvider(project).nativeLinkArgs })
task.runViaBuildToolsApi.value(false).disallowChanges() // K/N is not yet supported
task.xcodeVersion.set(xcodeVersionTask.version)
// Frameworks actively uses symlinks.
// Gradle build cache transforms symlinks into regular files https://guides.gradle.org/using-build-cache/#symbolic_links
@@ -524,8 +524,6 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
else -> error("Unknown cocoapods platform: $family")
}
val xcodeVersionTask = XcodeVersionTask.locateOrRegister(project)
val podGenTask = project.registerTask<PodGenTask>(family.toPodGenTaskName) { task ->
task.description = "Сreates a synthetic Xcode project to retrieve CocoaPods dependencies"
task.podName.set(project.provider { cocoapodsExtension.name })
@@ -533,7 +531,6 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
task.family.set(family)
task.platformSettings.set(platformSettings)
task.pods.set(cocoapodsExtension.pods)
task.xcodeVersion.set(xcodeVersionTask.version)
}
project.registerTask<PodInstallSyntheticTask>(family.toPodInstallSyntheticTaskName) { task ->
@@ -8,7 +8,6 @@
package org.jetbrains.kotlin.gradle.targets.native.tasks
import org.gradle.api.file.ProjectLayout
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
@@ -17,7 +16,7 @@ import org.gradle.work.DisableCachingByDefault
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.parse
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.UsesXcodeVersion
import org.jetbrains.kotlin.konan.target.Family
import org.jetbrains.kotlin.konan.target.XcodeVersion
import java.io.File
@@ -27,7 +26,7 @@ import javax.inject.Inject
* The task generates a synthetic project with all cocoapods dependencies
*/
@DisableCachingByDefault
abstract class PodGenTask @Inject constructor(projectLayout: ProjectLayout) : CocoapodsTask() {
abstract class PodGenTask @Inject constructor(projectLayout: ProjectLayout) : CocoapodsTask(), UsesXcodeVersion {
init {
onlyIf {
@@ -50,11 +49,6 @@ abstract class PodGenTask @Inject constructor(projectLayout: ProjectLayout) : Co
@get:Nested
internal abstract val pods: ListProperty<CocoapodsDependency>
@get:PathSensitive(PathSensitivity.RELATIVE)
@get:Optional
@get:InputFile
internal abstract val xcodeVersion: RegularFileProperty
@get:OutputFile
val podfile: Provider<File> = projectLayout.cocoapodsBuildDirs.synthetic(family).map { it.file("Podfile").asFile }
@@ -122,7 +116,7 @@ abstract class PodGenTask @Inject constructor(projectLayout: ProjectLayout) : Co
}
private fun insertXcode143DeploymentTargetWorkarounds(family: Family): String {
if (XcodeVersion.parse(xcodeVersion) < XcodeVersion(14, 3)) {
if (xcodeVersion.let { version -> version != null && version < XcodeVersion(14, 3) }) {
return ""
}
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.categoryByName
import org.jetbrains.kotlin.gradle.plugin.cocoapods.asValidFrameworkName
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.UsesXcodeVersion
import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf
import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService
import org.jetbrains.kotlin.gradle.targets.native.UsesKonanPropertiesBuildService
@@ -57,6 +58,7 @@ constructor(
) : AbstractKotlinCompileTool<K2NativeCompilerArguments>(objectFactory),
UsesKonanPropertiesBuildService,
UsesBuildMetricsService,
UsesXcodeVersion,
KotlinToolTask<KotlinCommonCompilerToolOptions>,
UsesKotlinNativeBundleBuildService {
@@ -199,11 +201,6 @@ constructor(
attributes.setAttribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY))
}.filterKlibsPassedToCompiler()
@get:Optional
@get:InputFile
@get:PathSensitive(PathSensitivity.RELATIVE)
internal val xcodeVersion = objectFactory.fileProperty()
private val externalDependenciesArgs by lazy {
@Suppress("DEPRECATION")
ExternalDependenciesBuilder(project, compilation).buildCompilerArgs()
@@ -15,8 +15,6 @@ import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
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.tasks.dependsOn
import org.jetbrains.kotlin.gradle.tasks.registerTask
@@ -110,7 +108,6 @@ internal fun KotlinNativeArtifact.registerLinkFrameworkTask(
): TaskProvider<KotlinNativeLinkArtifactTask> {
val kind = NativeOutputKind.FRAMEWORK
val destinationDir = project.layout.buildDirectory.dir("$outDirName/${target.visibleName}/${buildType.visibleName}")
val xcodeVersionTask = XcodeVersionTask.locateOrRegister(project)
val resultTask = project.registerTask<KotlinNativeLinkArtifactTask>(
lowerCamelCaseName("assemble", name, buildType.visibleName, kind.taskNameClassifier, target.presetName, taskNameSuffix),
listOf(target, kind.compilerOutputKind)
@@ -123,7 +120,6 @@ internal fun KotlinNativeArtifact.registerLinkFrameworkTask(
task.debuggable.set(buildType.debuggable)
task.linkerOptions.set(linkerOptions)
task.binaryOptions.set(binaryOptions)
task.xcodeVersion.set(xcodeVersionTask.version)
task.staticFramework.set(isStatic)
if (embedBitcode != null) {
task.embedBitcode.set(embedBitcode)
@@ -11,7 +11,6 @@ import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileCollection
import org.gradle.api.file.ProjectLayout
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.MapProperty
@@ -30,6 +29,7 @@ import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.UsesXcodeVersion
import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter
import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService
import org.jetbrains.kotlin.gradle.targets.native.tasks.buildKotlinNativeBinaryLinkerArgs
@@ -56,8 +56,9 @@ abstract class KotlinNativeLinkArtifactTask @Inject constructor(
private val projectLayout: ProjectLayout,
) : DefaultTask(),
UsesBuildMetricsService,
KotlinToolTask<KotlinCommonCompilerToolOptions>,
UsesKotlinNativeBundleBuildService {
UsesKotlinNativeBundleBuildService,
UsesXcodeVersion,
KotlinToolTask<KotlinCommonCompilerToolOptions> {
@get:Input
abstract val baseName: Property<String>
@@ -100,11 +101,6 @@ abstract class KotlinNativeLinkArtifactTask @Inject constructor(
@get:Input
abstract val binaryOptions: MapProperty<String, String>
@get:PathSensitive(PathSensitivity.RELATIVE)
@get:Optional
@get:InputFile
abstract val xcodeVersion: RegularFileProperty
private val nativeBinaryOptions = PropertiesProvider(project).nativeBinaryOptions
@get:Input
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.gradle.internal.transforms.BuildToolsApiClasspathEnt
import org.jetbrains.kotlin.gradle.plugin.BUILD_TOOLS_API_CLASSPATH_CONFIGURATION_NAME
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationInfo
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.diagnostics.setupTransformActionToolingDiagnostics
import org.jetbrains.kotlin.gradle.plugin.diagnostics.setupKotlinToolingDiagnosticsParameters
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation
@@ -183,13 +183,13 @@ internal open class BaseKotlinCompileConfig<TASK : KotlinCompile> : AbstractKotl
it.from.setAttribute(ARTIFACT_TYPE_ATTRIBUTE, JAR_ARTIFACT_TYPE)
it.to.setAttribute(ARTIFACT_TYPE_ATTRIBUTE, CLASSPATH_ENTRY_SNAPSHOT_ARTIFACT_TYPE)
it.configureCommonParameters(kgpVersion, classLoadersCachingService, classpath, jvmToolchain, runKotlinCompilerViaBuildToolsApi, suppressVersionInconsistencyChecks)
it.setupTransformActionToolingDiagnostics(project)
it.parameters.setupKotlinToolingDiagnosticsParameters(project)
}
project.dependencies.registerTransform(BuildToolsApiClasspathEntrySnapshotTransform::class.java) {
it.from.setAttribute(ARTIFACT_TYPE_ATTRIBUTE, DIRECTORY_ARTIFACT_TYPE)
it.to.setAttribute(ARTIFACT_TYPE_ATTRIBUTE, CLASSPATH_ENTRY_SNAPSHOT_ARTIFACT_TYPE)
it.configureCommonParameters(kgpVersion, classLoadersCachingService, classpath, jvmToolchain, runKotlinCompilerViaBuildToolsApi, suppressVersionInconsistencyChecks)
it.setupTransformActionToolingDiagnostics(project)
it.parameters.setupKotlinToolingDiagnosticsParameters(project)
}
}
@@ -5,8 +5,6 @@
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.*
@@ -20,7 +18,7 @@ object XcodeUtils {
fun bitcodeEmbeddingMode(
outputKind: CompilerOutputKind,
userMode: BitcodeEmbeddingMode?,
xcodeVersion: Provider<RegularFile>,
xcodeVersion: XcodeVersion?,
target: KonanTarget,
debuggable: Boolean,
): BitcodeEmbeddingMode {
@@ -35,14 +33,10 @@ object XcodeUtils {
}
}
private fun bitcodeSupported(xcodeVersion: Provider<RegularFile>, target: KonanTarget): Boolean {
return XcodeVersion.parse(xcodeVersion).major < 14
private fun bitcodeSupported(xcodeVersion: XcodeVersion?, target: KonanTarget): Boolean {
return xcodeVersion != null
&& xcodeVersion.major < 14
&& target.family in listOf(IOS, WATCHOS, TVOS)
&& target.architecture in listOf(ARM32, ARM64)
}
}
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'")
}
@@ -7,10 +7,7 @@
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.*
@@ -22,19 +19,10 @@ 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))
assertEquals(DISABLE, bitcodeEmbeddingMode(FRAMEWORK, null, XcodeVersion(14, 1), IOS_ARM64, debuggable = true))
assertEquals(MARKER, bitcodeEmbeddingMode(FRAMEWORK, null, XcodeVersion(13, 9), IOS_ARM64, debuggable = true))
assertEquals(BITCODE, bitcodeEmbeddingMode(FRAMEWORK, null, XcodeVersion(13, 4), IOS_ARM64, debuggable = false))
assertEquals(DISABLE, bitcodeEmbeddingMode(FRAMEWORK, null, XcodeVersion(10, 3), IOS_X64, debuggable = true))
assertEquals(DISABLE, bitcodeEmbeddingMode(FRAMEWORK, null, XcodeVersion(13, 4), MACOS_ARM64, debuggable = false))
}
}
@@ -1,7 +1,7 @@
[IncompatibleAgpVersionTooHighWarning | WARNING] Kotlin Multiplatform <-> Android Gradle Plugin compatibility issue:
The applied Android Gradle Plugin version (9.0.0) is higher
than the maximum known to the Kotlin Gradle Plugin.
Tooling stability in such configuration isn't tested, please report encountered issues to https://kotl.in/issue"
Tooling stability in such configuration isn't tested, please report encountered issues to https://kotl.in/issue
Minimum supported Android Gradle Plugin version: 4.2
Maximum tested Android Gradle Plugin version: 8.0
@@ -1,7 +1,7 @@
[IncompatibleAgpVersionTooHighWarning | WARNING] Kotlin Multiplatform <-> Android Gradle Plugin compatibility issue:
The applied Android Gradle Plugin version (8.1.0) is higher
than the maximum known to the Kotlin Gradle Plugin.
Tooling stability in such configuration isn't tested, please report encountered issues to https://kotl.in/issue"
Tooling stability in such configuration isn't tested, please report encountered issues to https://kotl.in/issue
Minimum supported Android Gradle Plugin version: 4.2
Maximum tested Android Gradle Plugin version: 8.0
@@ -41,6 +41,8 @@ data class XcodeVersion(val major: Int, val minor: Int) : Comparable<XcodeVersio
minor = split.getOrNull(1)?.toIntOrNull() ?: return null,
)
}
val maxTested = XcodeVersion(15, 1)
}
}