Register "embedAndSignAppleFrameworkForXcode" anytime but throw error without Xcode environment.

#KT-49971
This commit is contained in:
konstantin.tskhovrebov
2021-11-29 18:39:33 +01:00
committed by Space
parent ab6c8a4abe
commit 14ee13c72e
2 changed files with 73 additions and 47 deletions
@@ -34,7 +34,9 @@ class AppleFrameworkIT : BaseGradleIT() {
customEnvironmentVariables = mapOf( customEnvironmentVariables = mapOf(
"CONFIGURATION" to "debug", "CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123", "SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64" "ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
) )
) )
build("assembleDebugAppleFrameworkForXcodeIosArm64", options = options) { build("assembleDebugAppleFrameworkForXcodeIosArm64", options = options) {
@@ -60,7 +62,9 @@ class AppleFrameworkIT : BaseGradleIT() {
customEnvironmentVariables = mapOf( customEnvironmentVariables = mapOf(
"CONFIGURATION" to "Release", "CONFIGURATION" to "Release",
"SDK_NAME" to "iphonesimulator", "SDK_NAME" to "iphonesimulator",
"ARCHS" to "arm64 x86_64" "ARCHS" to "arm64 x86_64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
) )
) )
build("assembleReleaseAppleFrameworkForXcode", options = options) { build("assembleReleaseAppleFrameworkForXcode", options = options) {
@@ -75,14 +79,11 @@ class AppleFrameworkIT : BaseGradleIT() {
} }
@Test @Test
fun `check there aren't Xcode tasks without Xcode environment`() { fun `check embedAndSignAppleFrameworkForXcode fail`() {
with(Project("sharedAppleFramework")) { with(Project("sharedAppleFramework")) {
build("tasks") { build(":shared:embedAndSignAppleFrameworkForXcode") {
assertSuccessful() assertTasksFailed(":shared:embedAndSignAppleFrameworkForXcode")
assertTasksNotRegistered( assertContains("Please run the embedAndSignAppleFrameworkForXcode task from Xcode")
":shared:assembleDebugAppleFrameworkForXcodeIosArm64",
":shared:embedAndSignAppleFrameworkForXcode"
)
} }
} }
} }
@@ -106,9 +107,7 @@ class AppleFrameworkIT : BaseGradleIT() {
":shared:assembleDebugAppleFrameworkForXcodeIosArm64", ":shared:assembleDebugAppleFrameworkForXcodeIosArm64",
":shared:embedAndSignAppleFrameworkForXcode", ":shared:embedAndSignAppleFrameworkForXcode",
":shared:assembleCustomDebugAppleFrameworkForXcodeIosArm64", ":shared:assembleCustomDebugAppleFrameworkForXcodeIosArm64",
":shared:embedAndSignCustomAppleFrameworkForXcode" ":shared:embedAndSignCustomAppleFrameworkForXcode",
)
assertTasksNotRegistered(
":shared:assembleDebugAppleFrameworkForXcodeIosX64", ":shared:assembleDebugAppleFrameworkForXcodeIosX64",
":shared:assembleReleaseAppleFrameworkForXcodeIosX64", ":shared:assembleReleaseAppleFrameworkForXcodeIosX64",
":shared:assembleReleaseAppleFrameworkForXcodeIosArm64", ":shared:assembleReleaseAppleFrameworkForXcodeIosArm64",
@@ -121,7 +120,7 @@ class AppleFrameworkIT : BaseGradleIT() {
} }
@Test @Test
fun `check there isn't embedAndSignAppleFrameworkForXcode task without required Xcode environments`() { fun `check embedAndSignAppleFrameworkForXcode was registered without required Xcode environments`() {
with(Project("sharedAppleFramework")) { with(Project("sharedAppleFramework")) {
val options: BuildOptions = defaultBuildOptions().copy( val options: BuildOptions = defaultBuildOptions().copy(
customEnvironmentVariables = mapOf( customEnvironmentVariables = mapOf(
@@ -133,16 +132,24 @@ class AppleFrameworkIT : BaseGradleIT() {
build("tasks", options = options) { build("tasks", options = options) {
assertSuccessful() assertSuccessful()
assertTasksRegistered( assertTasksRegistered(
":shared:assembleDebugAppleFrameworkForXcodeIosArm64", ":shared:embedAndSignAppleFrameworkForXcode",
":shared:assembleCustomDebugAppleFrameworkForXcodeIosArm64" ":shared:embedAndSignCustomAppleFrameworkForXcode"
) )
assertTasksNotRegistered( assertTasksNotRegistered(
":shared:embedAndSignAppleFrameworkForXcode", ":shared:assembleReleaseAppleFrameworkForXcodeIosX64",
":shared:assembleDebugAppleFrameworkForXcodeIosX64", ":shared:assembleDebugAppleFrameworkForXcodeIosX64",
":shared:embedAndSignCustomAppleFrameworkForXcode", ":shared:assembleReleaseAppleFrameworkForXcodeIosArm64",
":shared:assembleCustomDebugAppleFrameworkForXcodeIosX64" ":shared:assembleDebugAppleFrameworkForXcodeIosArm64",
":shared:assembleCustomDebugAppleFrameworkForXcodeIosX64",
":shared:assembleCustomReleaseAppleFrameworkForXcodeIosX64",
":shared:assembleCustomDebugAppleFrameworkForXcodeIosArm64",
":shared:assembleCustomReleaseAppleFrameworkForXcodeIosArm64"
) )
} }
build(":shared:embedAndSignCustomAppleFrameworkForXcode", options = options) {
assertTasksFailed(":shared:embedAndSignCustomAppleFrameworkForXcode")
assertContains("Please run the embedAndSignCustomAppleFrameworkForXcode task from Xcode")
}
} }
} }
} }
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.gradle.plugin.mpp.apple package org.jetbrains.kotlin.gradle.plugin.mpp.apple
import org.gradle.api.DefaultTask
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.Task import org.gradle.api.Task
import org.gradle.api.plugins.BasePlugin import org.gradle.api.plugins.BasePlugin
@@ -20,7 +21,6 @@ import org.jetbrains.kotlin.gradle.tasks.locateTask
import org.jetbrains.kotlin.gradle.tasks.registerTask import org.jetbrains.kotlin.gradle.tasks.registerTask
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.toLowerCaseAsciiOnly
import java.io.File import java.io.File
private object XcodeEnvironment { private object XcodeEnvironment {
@@ -61,6 +61,15 @@ private object XcodeEnvironment {
} }
val sign: String? get() = System.getenv("EXPANDED_CODE_SIGN_IDENTITY") val sign: String? get() = System.getenv("EXPANDED_CODE_SIGN_IDENTITY")
override fun toString() = """
XcodeEnvironment:
buildType=$buildType
targets=$targets
frameworkSearchDir=$frameworkSearchDir
embeddedFrameworksDir=$embeddedFrameworksDir
sign=$sign
""".trimIndent()
} }
private fun Project.registerAssembleAppleFrameworkTask(framework: Framework): TaskProvider<out Task>? { private fun Project.registerAssembleAppleFrameworkTask(framework: Framework): TaskProvider<out Task>? {
@@ -90,29 +99,27 @@ private fun Project.registerAssembleAppleFrameworkTask(framework: Framework): Ta
"Specify 'KOTLIN_FRAMEWORK_BUILD_TYPE' to 'debug' or 'release'" "Specify 'KOTLIN_FRAMEWORK_BUILD_TYPE' to 'debug' or 'release'"
) )
} else { } else {
logger.debug( logger.debug("Not registering $frameworkTaskName, since not called from Xcode")
"Not registering $frameworkTaskName, since not called from Xcode " +
"('SDK_NAME', 'ARCHS' and 'CONFIGURATION' not provided)"
)
} }
return null return null
} }
if (frameworkBuildType != envBuildType || !envTargets.contains(frameworkTarget.konanTarget)) return null return when {
!envTargets.contains(frameworkTarget.konanTarget) -> locateOrRegisterTask<DefaultTask>(frameworkTaskName) { task ->
return if (needFatFramework) { task.description = "Packs $frameworkBuildType ${frameworkTarget.name} framework for Xcode"
locateOrRegisterTask<FatFrameworkTask>(frameworkTaskName) { task -> task.isEnabled = false
task.group = BasePlugin.BUILD_GROUP }
needFatFramework -> locateOrRegisterTask<FatFrameworkTask>(frameworkTaskName) { task ->
task.description = "Packs $frameworkBuildType fat framework for Xcode" task.description = "Packs $frameworkBuildType fat framework for Xcode"
task.baseName = framework.baseName task.baseName = framework.baseName
task.destinationDir = appleFrameworkDir(envFrameworkSearchDir) task.destinationDir = appleFrameworkDir(envFrameworkSearchDir)
task.isEnabled = frameworkBuildType == envBuildType
}.also { }.also {
it.configure { task -> task.from(framework) } it.configure { task -> task.from(framework) }
} }
} else { else -> registerTask<Copy>(frameworkTaskName) { task ->
registerTask<Copy>(frameworkTaskName) { task ->
task.group = BasePlugin.BUILD_GROUP
task.description = "Packs $frameworkBuildType ${frameworkTarget.name} framework for Xcode" task.description = "Packs $frameworkBuildType ${frameworkTarget.name} framework for Xcode"
task.isEnabled = frameworkBuildType == envBuildType
task.dependsOn(framework.linkTaskName) task.dependsOn(framework.linkTaskName)
task.from(framework.outputDirectory) task.from(framework.outputDirectory)
task.into(appleFrameworkDir(envFrameworkSearchDir)) task.into(appleFrameworkDir(envFrameworkSearchDir))
@@ -121,8 +128,6 @@ private fun Project.registerAssembleAppleFrameworkTask(framework: Framework): Ta
} }
internal fun Project.registerEmbedAndSignAppleFrameworkTask(framework: Framework) { internal fun Project.registerEmbedAndSignAppleFrameworkTask(framework: Framework) {
val assembleTask = registerAssembleAppleFrameworkTask(framework) ?: return
val envBuildType = XcodeEnvironment.buildType val envBuildType = XcodeEnvironment.buildType
val envTargets = XcodeEnvironment.targets val envTargets = XcodeEnvironment.targets
val envEmbeddedFrameworksDir = XcodeEnvironment.embeddedFrameworksDir val envEmbeddedFrameworksDir = XcodeEnvironment.embeddedFrameworksDir
@@ -132,32 +137,46 @@ internal fun Project.registerEmbedAndSignAppleFrameworkTask(framework: Framework
val frameworkTaskName = lowerCamelCaseName("embedAndSign", framework.namePrefix, "AppleFrameworkForXcode") val frameworkTaskName = lowerCamelCaseName("embedAndSign", framework.namePrefix, "AppleFrameworkForXcode")
if (envBuildType == null || envTargets.isEmpty() || envEmbeddedFrameworksDir == null || envFrameworkSearchDir == null) { if (envBuildType == null || envTargets.isEmpty() || envEmbeddedFrameworksDir == null || envFrameworkSearchDir == null) {
logger.debug( locateOrRegisterTask<DefaultTask>(frameworkTaskName) { task ->
"Not registering $frameworkTaskName, since not called from Xcode " + task.group = BasePlugin.BUILD_GROUP
"('SDK_NAME', 'CONFIGURATION', 'TARGET_BUILD_DIR', 'ARCHS' and 'FRAMEWORKS_FOLDER_PATH' not provided)" task.description = "Embed and sign ${framework.namePrefix} framework as requested by Xcode's environment variables"
) task.doFirst {
val envConfiguration = System.getenv("CONFIGURATION")
if (envConfiguration != null && envBuildType == null) {
throw IllegalStateException(
"Unable to detect Kotlin framework build type for CONFIGURATION=$envConfiguration automatically. " +
"Specify 'KOTLIN_FRAMEWORK_BUILD_TYPE' to 'debug' or 'release'" +
"\n$XcodeEnvironment"
)
} else {
throw IllegalStateException(
"Please run the $frameworkTaskName task from Xcode " +
"('SDK_NAME', 'CONFIGURATION', 'TARGET_BUILD_DIR', 'ARCHS' and 'FRAMEWORKS_FOLDER_PATH' not provided)" +
"\n$XcodeEnvironment"
)
}
}
}
return return
} }
if (framework.buildType != envBuildType || !envTargets.contains(framework.konanTarget)) return val embedAndSignTask = locateOrRegisterTask<Copy>(frameworkTaskName) { task ->
if (locateTask<Copy>(frameworkTaskName) != null) return task.group = BasePlugin.BUILD_GROUP
registerTask<Copy>(frameworkTaskName) { task ->
task.group = "build"
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.dependsOn(assembleTask)
task.inputs.apply { task.inputs.apply {
property("type", envBuildType) property("type", envBuildType)
property("targets", envTargets) property("targets", envTargets)
property("embeddedFrameworksDir", envEmbeddedFrameworksDir) property("embeddedFrameworksDir", envEmbeddedFrameworksDir)
property("sign", envSign) property("sign", envSign)
} }
}
task.from(appleFrameworkDir(envFrameworkSearchDir)) { spec -> val assembleTask = registerAssembleAppleFrameworkTask(framework) ?: return
spec.include(framework.outputFile.name + "/**") if (framework.buildType != envBuildType || !envTargets.contains(framework.konanTarget)) return
}
embedAndSignTask.configure { task ->
task.dependsOn(assembleTask)
task.from(appleFrameworkDir(envFrameworkSearchDir)) { it.include(framework.outputFile.name + "/**") }
task.into(envEmbeddedFrameworksDir) task.into(envEmbeddedFrameworksDir)
if (envSign != null) { if (envSign != null) {