[Gradle] Forbid using embedAndSign together with Pod-dependencies

^KT-64096 Verification Pending
This commit is contained in:
Artem Daugel-Dauge
2024-02-17 17:52:23 +09:00
committed by Space Team
parent f5de0f9399
commit 7ab691fcef
4 changed files with 69 additions and 9 deletions
@@ -21,6 +21,8 @@ import org.jetbrains.kotlin.gradle.util.runProcess
import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.condition.OS import org.junit.jupiter.api.condition.OS
import org.junit.jupiter.api.io.TempDir
import java.nio.file.Path
import java.util.zip.ZipFile import java.util.zip.ZipFile
import kotlin.io.path.* import kotlin.io.path.*
import kotlin.test.assertContains import kotlin.test.assertContains
@@ -1049,6 +1051,31 @@ class CocoaPodsIT : KGPBaseTest() {
} }
} }
@DisplayName("Build fails when embedAndSign task is used with pod-dependencies")
@GradleTest
fun testEmbedAndSignNotUsedWithPodDepsDiagnostic(gradleVersion: GradleVersion, @TempDir tempDir: Path) {
nativeProjectWithCocoapodsAndIosAppPodFile(
gradleVersion = gradleVersion,
environmentVariables = EnvironmentalVariables(
"CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64",
"TARGET_BUILD_DIR" to tempDir.absolutePathString(),
"FRAMEWORKS_FOLDER_PATH" to "frameworks",
"BUILT_PRODUCTS_DIR" to tempDir.absolutePathString(),
)
) {
buildGradleKts.addKotlinBlock("iosArm64()")
buildGradleKts.addCocoapodsBlock("""pod("Base64", version="1.1.2")""")
buildAndFail(":embedAndSignPodAppleFrameworkForXcode") {
assertHasDiagnostic(CocoapodsPluginDiagnostics.EmbedAndSignUsedWithPodDependencies)
}
}
}
private fun TestProject.buildAndFailWithCocoapodsWrapper( private fun TestProject.buildAndFailWithCocoapodsWrapper(
vararg buildArguments: String, vararg buildArguments: String,
assertions: BuildResult.() -> Unit = {}, assertions: BuildResult.() -> Unit = {},
@@ -17,6 +17,7 @@ import org.gradle.work.DisableCachingByDefault
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeBinaryContainer import org.jetbrains.kotlin.gradle.dsl.KotlinNativeBinaryContainer
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.plugin.diagnostics.UsesKotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic
import org.jetbrains.kotlin.gradle.plugin.mpp.Framework import org.jetbrains.kotlin.gradle.plugin.mpp.Framework
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
@@ -217,11 +218,7 @@ internal fun Project.registerEmbedAndSignAppleFrameworkTask(framework: Framework
val envSign = XcodeEnvironment.sign val envSign = XcodeEnvironment.sign
val userScriptSandboxingEnabled = XcodeEnvironment.userScriptSandboxingEnabled val userScriptSandboxingEnabled = XcodeEnvironment.userScriptSandboxingEnabled
val frameworkTaskName = lowerCamelCaseName( val frameworkTaskName = framework.embedAndSignTaskName()
AppleXcodeTasks.embedAndSignTaskPrefix,
framework.namePrefix,
AppleXcodeTasks.embedAndSignTaskPostfix
)
if (envBuildType == null || envTargets.isEmpty() || envEmbeddedFrameworksDir == null) { if (envBuildType == null || envTargets.isEmpty() || envEmbeddedFrameworksDir == null) {
locateOrRegisterTask<DefaultTask>(frameworkTaskName) { task -> locateOrRegisterTask<DefaultTask>(frameworkTaskName) { task ->
@@ -250,7 +247,7 @@ internal fun Project.registerEmbedAndSignAppleFrameworkTask(framework: Framework
} }
} }
val embedAndSignTask = locateOrRegisterTask<FrameworkCopy>(frameworkTaskName) { task -> val embedAndSignTask = locateOrRegisterTask<EmbedAndSignTask>(frameworkTaskName) { task ->
task.group = BasePlugin.BUILD_GROUP task.group = BasePlugin.BUILD_GROUP
task.description = "Embed and sign ${framework.namePrefix} framework as requested by Xcode's environment variables" task.description = "Embed and sign ${framework.namePrefix} framework as requested by Xcode's environment variables"
task.isEnabled = !framework.isStatic task.isEnabled = !framework.isStatic
@@ -288,6 +285,12 @@ internal fun Project.registerEmbedAndSignAppleFrameworkTask(framework: Framework
} }
} }
private fun Framework.embedAndSignTaskName(): String = lowerCamelCaseName(
AppleXcodeTasks.embedAndSignTaskPrefix,
namePrefix,
AppleXcodeTasks.embedAndSignTaskPostfix
)
private val Framework.namePrefix: String private val Framework.namePrefix: String
get() = KotlinNativeBinaryContainer.extractPrefixFromBinaryName( get() = KotlinNativeBinaryContainer.extractPrefixFromBinaryName(
name, name,
@@ -316,7 +319,7 @@ private fun Project.appleFrameworkDir(frameworkTaskName: String): Provider<File>
* To preserve these symlinks we are using the `cp` command instead. * To preserve these symlinks we are using the `cp` command instead.
* See https://youtrack.jetbrains.com/issue/KT-48594. * See https://youtrack.jetbrains.com/issue/KT-48594.
*/ */
@DisableCachingByDefault @DisableCachingByDefault(because = "Caching breaks symlinks inside frameworks")
internal abstract class FrameworkCopy : DefaultTask() { internal abstract class FrameworkCopy : DefaultTask() {
@get:Inject @get:Inject
@@ -359,3 +362,6 @@ internal abstract class FrameworkCopy : DefaultTask() {
fun dsymFile(framework: Provider<File>): Provider<File> = framework.map { File(it.path + ".dSYM") } fun dsymFile(framework: Provider<File>): Provider<File> = framework.map { File(it.path + ".dSYM") }
} }
} }
@DisableCachingByDefault(because = "Caching breaks symlinks inside frameworks")
internal abstract class EmbedAndSignTask : FrameworkCopy(), UsesKotlinToolingDiagnostics
@@ -6,8 +6,7 @@
package org.jetbrains.kotlin.gradle.targets.native.cocoapods package org.jetbrains.kotlin.gradle.targets.native.cocoapods
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic.Severity.ERROR import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic.Severity.*
import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic.Severity.WARNING
import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnosticFactory import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnosticFactory
@InternalKotlinGradlePluginApi // used in integration tests @InternalKotlinGradlePluginApi // used in integration tests
@@ -52,4 +51,13 @@ object CocoapodsPluginDiagnostics {
operator fun invoke(podName: String, dependencyName: String) = build("Couldn't find declaration of pod '$dependencyName' (interop-binding dependency of pod '${podName}')") operator fun invoke(podName: String, dependencyName: String) = build("Couldn't find declaration of pod '$dependencyName' (interop-binding dependency of pod '${podName}')")
} }
object EmbedAndSignUsedWithPodDependencies : ToolingDiagnosticFactory(FATAL) {
operator fun invoke() = build(
"""
'embedAndSign' task can not be used in a project with dependencies to pods.
Please use CocoaPods for integration into Xcode.
""".trimIndent()
)
}
} }
@@ -815,6 +815,24 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
} }
} }
private fun checkEmbedAndSignNotUsedTogetherWithPodDependencies(project: Project, kotlinExtension: KotlinMultiplatformExtension, cocoapodsExtension: CocoapodsExtension) {
cocoapodsExtension.pods.all {
SingleActionPerProject.run(project, "assertEmbedAndSignNotUsedTogetherWithPodDependencies") {
kotlinExtension.targets.withType<KotlinNativeTarget>().all { target ->
target.binaries.withType<Framework>().all {
project.tasks.withType<EmbedAndSignTask>().all { embedAndSignTask ->
embedAndSignTask.doFirst {
embedAndSignTask.reportDiagnostic(CocoapodsPluginDiagnostics.EmbedAndSignUsedWithPodDependencies())
}
}
}
}
}
}
}
private fun Project.gradleWrapperPath(): Provider<String?> { private fun Project.gradleWrapperPath(): Provider<String?> {
return provider { rootProject.tasks.locateTask<Wrapper>("wrapper")?.get()?.scriptFile?.absolutePath } return provider { rootProject.tasks.locateTask<Wrapper>("wrapper")?.get()?.scriptFile?.absolutePath }
} }
@@ -873,6 +891,7 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
createInterops(project, kotlinExtension, cocoapodsExtension) createInterops(project, kotlinExtension, cocoapodsExtension)
configureLinkingOptions(project, cocoapodsExtension) configureLinkingOptions(project, cocoapodsExtension)
checkLinkOnlyNotUsedWithStaticFramework(project, cocoapodsExtension) checkLinkOnlyNotUsedWithStaticFramework(project, cocoapodsExtension)
checkEmbedAndSignNotUsedTogetherWithPodDependencies(project, kotlinExtension, cocoapodsExtension)
} }
} }