[Gradle, Native] Advanced CocoaPods integration.
This commit is contained in:
+24
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.cocoapods
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.EnablePodImportTask
|
||||||
|
import org.jetbrains.plugins.gradle.model.ClassSetProjectImportModelProvider
|
||||||
|
import org.jetbrains.plugins.gradle.model.ProjectImportModelProvider
|
||||||
|
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
|
||||||
|
|
||||||
|
class KotlinCocoaPodsModelResolver : AbstractProjectResolverExtension() {
|
||||||
|
|
||||||
|
override fun getProjectsLoadedModelProvider(): ProjectImportModelProvider {
|
||||||
|
return ClassSetProjectImportModelProvider(
|
||||||
|
setOf(EnablePodImportTask::class.java)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun requiresTaskRunning(): Boolean = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.cocoapods
|
||||||
|
|
||||||
|
class KotlinCocoaPodsModelResolver
|
||||||
+1
@@ -1,2 +1,3 @@
|
|||||||
org.jetbrains.kotlin.gradle.KotlinGradleModelBuilder
|
org.jetbrains.kotlin.gradle.KotlinGradleModelBuilder
|
||||||
org.jetbrains.kotlin.gradle.KotlinMPPGradleModelBuilder
|
org.jetbrains.kotlin.gradle.KotlinMPPGradleModelBuilder
|
||||||
|
org.jetbrains.kotlin.gradle.KotlinCocoaPodsModelBuilder
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.jetbrains.plugins.gradle.tooling.AbstractModelBuilderService
|
||||||
|
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
|
||||||
|
import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext
|
||||||
|
|
||||||
|
private const val POD_IMPORT_TASK_NAME = "podImport"
|
||||||
|
|
||||||
|
interface EnablePodImportTask
|
||||||
|
|
||||||
|
class KotlinCocoaPodsModelBuilder : AbstractModelBuilderService() {
|
||||||
|
override fun canBuild(modelName: String?): Boolean {
|
||||||
|
return EnablePodImportTask::class.java.name == modelName
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildAll(modelName: String, project: Project, context: ModelBuilderContext): Any? {
|
||||||
|
val startParameter = project.gradle.startParameter
|
||||||
|
val taskNames = startParameter.taskNames
|
||||||
|
|
||||||
|
if (project.tasks.findByPath(POD_IMPORT_TASK_NAME) != null && POD_IMPORT_TASK_NAME !in taskNames) {
|
||||||
|
taskNames.add(POD_IMPORT_TASK_NAME)
|
||||||
|
startParameter.setTaskNames(taskNames)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getErrorMessageBuilder(project: Project, e: Exception): ErrorMessageBuilder {
|
||||||
|
return ErrorMessageBuilder.create(
|
||||||
|
project, e, "EnablePodImportTask error"
|
||||||
|
).withDescription("Unable to create $POD_IMPORT_TASK_NAME task.")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,60 +1,65 @@
|
|||||||
<idea-plugin>
|
<idea-plugin>
|
||||||
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
|
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
|
||||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPSourceSetsFrameworkSupportProvider"/>
|
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPSourceSetsFrameworkSupportProvider"/>
|
||||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
|
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
|
||||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSBrowserFrameworkSupportProvider"/>
|
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSBrowserFrameworkSupportProvider"/>
|
||||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSNodeFrameworkSupportProvider"/>
|
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSNodeFrameworkSupportProvider"/>
|
||||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinMPPFrameworkSupportProvider"/>
|
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinMPPFrameworkSupportProvider"/>
|
||||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
|
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
|
||||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSBrowserFrameworkSupportProvider"/>
|
<kotlinDslFrameworkSupport
|
||||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSNodeFrameworkSupportProvider"/>
|
implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSBrowserFrameworkSupportProvider"/>
|
||||||
<pluginDescriptions implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradlePluginDescription"/>
|
<kotlinDslFrameworkSupport
|
||||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinNonJvmGutterConfigurator" />
|
implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSNodeFrameworkSupportProvider"/>
|
||||||
<projectResolve implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModelResolver" order="first"/>
|
<pluginDescriptions implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradlePluginDescription"/>
|
||||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectResolverExtension" order="first"/>
|
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinNonJvmGutterConfigurator"/>
|
||||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleCoroutineDebugProjectResolver" order="last"/>
|
<projectResolve implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModelResolver" order="first"/>
|
||||||
<projectResolve implementation="org.jetbrains.kotlin.kapt.idea.KaptProjectResolverExtension" order="last"/>
|
<projectResolve implementation="org.jetbrains.kotlin.idea.cocoapods.KotlinCocoaPodsModelResolver" order="first"/>
|
||||||
<projectResolve implementation="org.jetbrains.kotlin.allopen.ide.AllOpenProjectResolverExtension" order="last"/>
|
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectResolverExtension" order="first"/>
|
||||||
<projectResolve implementation="org.jetbrains.kotlin.noarg.ide.NoArgProjectResolverExtension" order="last"/>
|
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleCoroutineDebugProjectResolver" order="last"/>
|
||||||
<projectResolve implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverProjectResolverExtension" order="last"/>
|
<projectResolve implementation="org.jetbrains.kotlin.kapt.idea.KaptProjectResolverExtension" order="last"/>
|
||||||
</extensions>
|
<projectResolve implementation="org.jetbrains.kotlin.allopen.ide.AllOpenProjectResolverExtension" order="last"/>
|
||||||
|
<projectResolve implementation="org.jetbrains.kotlin.noarg.ide.NoArgProjectResolverExtension" order="last"/>
|
||||||
|
<projectResolve implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverProjectResolverExtension" order="last"/>
|
||||||
|
</extensions>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleSourceSetDataService"/>
|
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleSourceSetDataService"/>
|
||||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectDataService"/>
|
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectDataService"/>
|
||||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleLibraryDataService"/>
|
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleLibraryDataService"/>
|
||||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinTargetDataService"/>
|
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinTargetDataService"/>
|
||||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.KotlinJavaMPPSourceSetDataService"/>
|
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.KotlinJavaMPPSourceSetDataService"/>
|
||||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibraryDataService"/>
|
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibraryDataService"/>
|
||||||
<externalSystemTaskNotificationListener implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsUpdater"/>
|
<externalSystemTaskNotificationListener implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsUpdater"/>
|
||||||
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptOutOfSourceNotificationProvider"/>
|
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptOutOfSourceNotificationProvider"/>
|
||||||
|
|
||||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestClassGradleConfigurationProducer"/>
|
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestClassGradleConfigurationProducer"/>
|
||||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestClassGradleConfigurationProducer"/>
|
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestClassGradleConfigurationProducer"/>
|
||||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestMethodGradleConfigurationProducer"/>
|
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestMethodGradleConfigurationProducer"/>
|
||||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestMethodGradleConfigurationProducer"/>
|
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestMethodGradleConfigurationProducer"/>
|
||||||
|
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.allopen.ide.AllOpenGradleProjectImportHandler"/>
|
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.allopen.ide.AllOpenGradleProjectImportHandler"/>
|
||||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.scripting.idea.plugin.ScriptingGradleProjectImportHandler"/>
|
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.scripting.idea.plugin.ScriptingGradleProjectImportHandler"/>
|
||||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.kapt.idea.KaptGradleProjectImportHandler"/>
|
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.kapt.idea.KaptGradleProjectImportHandler"/>
|
||||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.noarg.ide.NoArgGradleProjectImportHandler"/>
|
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.noarg.ide.NoArgGradleProjectImportHandler"/>
|
||||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverGradleProjectImportHandler"/>
|
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverGradleProjectImportHandler"/>
|
||||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlinx.serialization.idea.KotlinSerializationGradleImportHandler"/>
|
<gradleProjectImportHandler implementation="org.jetbrains.kotlinx.serialization.idea.KotlinSerializationGradleImportHandler"/>
|
||||||
|
|
||||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleModuleConfigurator"/>
|
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleModuleConfigurator"/>
|
||||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinJsGradleModuleConfigurator"/>
|
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinJsGradleModuleConfigurator"/>
|
||||||
<gradleModelFacade implementation="org.jetbrains.kotlin.idea.inspections.gradle.DefaultGradleModelFacade"/>
|
<gradleModelFacade implementation="org.jetbrains.kotlin.idea.inspections.gradle.DefaultGradleModelFacade"/>
|
||||||
|
|
||||||
<scriptDefinitionContributor implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsContributor" order="first"/>
|
<scriptDefinitionContributor implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsContributor"
|
||||||
<scriptAdditionalIdeaDependenciesProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptAdditionalIdeaDependenciesProvider"/>
|
order="first"/>
|
||||||
|
<scriptAdditionalIdeaDependenciesProvider
|
||||||
|
implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptAdditionalIdeaDependenciesProvider"/>
|
||||||
|
|
||||||
<moduleBuilder implementation="org.jetbrains.kotlin.ide.konan.gradle.KotlinGradleNativeMultiplatformModuleBuilder"/>
|
<moduleBuilder implementation="org.jetbrains.kotlin.ide.konan.gradle.KotlinGradleNativeMultiplatformModuleBuilder"/>
|
||||||
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleSharedMultiplatformModuleBuilder"/>
|
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleSharedMultiplatformModuleBuilder"/>
|
||||||
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleWebMultiplatformModuleBuilder"/>
|
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleWebMultiplatformModuleBuilder"/>
|
||||||
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleMobileMultiplatformModuleBuilder"/>
|
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleMobileMultiplatformModuleBuilder"/>
|
||||||
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleMobileSharedMultiplatformModuleBuilder"/>
|
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleMobileSharedMultiplatformModuleBuilder"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
|
|||||||
+13
-4
@@ -9,16 +9,25 @@ package org.jetbrains.kotlin.gradle.plugin.cocoapods
|
|||||||
import org.gradle.api.Named
|
import org.gradle.api.Named
|
||||||
import org.gradle.api.NamedDomainObjectSet
|
import org.gradle.api.NamedDomainObjectSet
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.tasks.Input
|
import org.gradle.api.tasks.*
|
||||||
import org.gradle.api.tasks.Internal
|
import java.io.File
|
||||||
import org.gradle.api.tasks.Nested
|
|
||||||
import org.gradle.api.tasks.Optional
|
|
||||||
|
|
||||||
open class CocoapodsExtension(private val project: Project) {
|
open class CocoapodsExtension(private val project: Project) {
|
||||||
@get:Input
|
@get:Input
|
||||||
val version: String
|
val version: String
|
||||||
get() = project.version.toString()
|
get() = project.version.toString()
|
||||||
|
|
||||||
|
@Optional
|
||||||
|
@InputFile
|
||||||
|
var podfile: File? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure path to the Podfile.
|
||||||
|
*/
|
||||||
|
fun podfile(path: String) {
|
||||||
|
podfile = project.file(path)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure authors of the pod built from this project.
|
* Configure authors of the pod built from this project.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+167
-39
@@ -16,12 +16,20 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.addExtension
|
import org.jetbrains.kotlin.gradle.plugin.addExtension
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
||||||
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
|
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
|
||||||
import org.jetbrains.kotlin.gradle.tasks.*
|
import org.jetbrains.kotlin.gradle.targets.native.tasks.PodBuildSettingsProperties
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.native.tasks.PodBuildTask
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.native.tasks.PodInstallTask
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.native.tasks.PodSetupBuildTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.DefFileTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.DummyFrameworkTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.FatFrameworkTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.PodspecTask
|
||||||
import org.jetbrains.kotlin.gradle.utils.asValidTaskName
|
import org.jetbrains.kotlin.gradle.utils.asValidTaskName
|
||||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
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 java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
internal val Project.cocoapodsBuildDirs: CocoapodsBuildDirs
|
internal val Project.cocoapodsBuildDirs: CocoapodsBuildDirs
|
||||||
get() = CocoapodsBuildDirs(this)
|
get() = CocoapodsBuildDirs(this)
|
||||||
@@ -42,6 +50,12 @@ internal class CocoapodsBuildDirs(val project: Project) {
|
|||||||
|
|
||||||
internal fun String.asValidFrameworkName() = replace('-', '_')
|
internal fun String.asValidFrameworkName() = replace('-', '_')
|
||||||
|
|
||||||
|
internal val KotlinNativeTarget.toBuildSetupTaskName: String
|
||||||
|
get() = lowerCamelCaseName(KotlinCocoapodsPlugin.POD_SETUP_BUILD_TASK_NAME, disambiguationClassifier)
|
||||||
|
|
||||||
|
internal val KotlinNativeTarget.toBuildDependenciesTaskName: String
|
||||||
|
get() = lowerCamelCaseName(KotlinCocoapodsPlugin.POD_BUILD_DEPENDENCIES_TASK_NAME, disambiguationClassifier)
|
||||||
|
|
||||||
open class KotlinCocoapodsPlugin : Plugin<Project> {
|
open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||||
|
|
||||||
private fun KotlinMultiplatformExtension.supportedTargets() = targets
|
private fun KotlinMultiplatformExtension.supportedTargets() = targets
|
||||||
@@ -70,8 +84,9 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Project.createSyncFrameworkTask(originalDirectory: File, buildingTask: Task) =
|
private fun Project.createSyncFrameworkTask(originalDirectory: File, buildingTask: Task): Sync? {
|
||||||
tasks.create(SYNC_TASK_NAME, Sync::class.java) {
|
|
||||||
|
return tasks.create(SYNC_TASK_NAME, Sync::class.java) {
|
||||||
it.group = TASK_GROUP
|
it.group = TASK_GROUP
|
||||||
it.description = "Copies a framework for given platform and build type into the CocoaPods build directory"
|
it.description = "Copies a framework for given platform and build type into the CocoaPods build directory"
|
||||||
|
|
||||||
@@ -79,6 +94,7 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
|||||||
it.from(originalDirectory)
|
it.from(originalDirectory)
|
||||||
it.destinationDir = cocoapodsBuildDirs.framework
|
it.destinationDir = cocoapodsBuildDirs.framework
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createSyncForFatFramework(
|
private fun createSyncForFatFramework(
|
||||||
project: Project,
|
project: Project,
|
||||||
@@ -153,32 +169,14 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createPodspecGenerationTask(
|
|
||||||
project: Project,
|
|
||||||
cocoapodsExtension: CocoapodsExtension
|
|
||||||
) {
|
|
||||||
val dummyFrameworkTask = project.tasks.create("generateDummyFramework", DummyFrameworkTask::class.java) {
|
|
||||||
it.settings = cocoapodsExtension
|
|
||||||
}
|
|
||||||
|
|
||||||
project.tasks.create("podspec", PodspecTask::class.java) {
|
|
||||||
it.group = TASK_GROUP
|
|
||||||
it.description = "Generates a podspec file for CocoaPods import"
|
|
||||||
it.settings = cocoapodsExtension
|
|
||||||
it.dependsOn(dummyFrameworkTask)
|
|
||||||
val generateWrapper = project.findProperty(GENERATE_WRAPPER_PROPERTY)?.toString()?.toBoolean() ?: false
|
|
||||||
if (generateWrapper) {
|
|
||||||
it.dependsOn(":wrapper")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createInterops(
|
private fun createInterops(
|
||||||
project: Project,
|
project: Project,
|
||||||
kotlinExtension: KotlinMultiplatformExtension,
|
kotlinExtension: KotlinMultiplatformExtension,
|
||||||
cocoapodsExtension: CocoapodsExtension
|
cocoapodsExtension: CocoapodsExtension
|
||||||
) {
|
) {
|
||||||
val moduleNames = mutableSetOf<String>()
|
val moduleNames = mutableSetOf<String>()
|
||||||
|
|
||||||
|
|
||||||
cocoapodsExtension.pods.all { pod ->
|
cocoapodsExtension.pods.all { pod ->
|
||||||
if (moduleNames.contains(pod.moduleName)) {
|
if (moduleNames.contains(pod.moduleName)) {
|
||||||
return@all
|
return@all
|
||||||
@@ -199,10 +197,19 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
|||||||
target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME).cinterops.create(pod.moduleName) { interop ->
|
target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME).cinterops.create(pod.moduleName) { interop ->
|
||||||
|
|
||||||
val interopTask = project.tasks.getByPath(interop.interopProcessingTaskName)
|
val interopTask = project.tasks.getByPath(interop.interopProcessingTaskName)
|
||||||
|
|
||||||
interopTask.dependsOn(defTask)
|
interopTask.dependsOn(defTask)
|
||||||
|
|
||||||
interop.defFile = defTask.outputFile
|
interop.defFile = defTask.outputFile
|
||||||
interop.packageName = "cocoapods.${pod.moduleName}"
|
interop.packageName = "cocoapods.${pod.moduleName}"
|
||||||
|
|
||||||
|
|
||||||
|
if (project.findProperty(TARGET_PROPERTY) == null && project.findProperty(CONFIGURATION_PROPERTY) == null) {
|
||||||
|
val podBuildTaskProvider = project.tasks.named(target.toBuildDependenciesTaskName, PodBuildTask::class.java)
|
||||||
|
interopTask.inputs.file(podBuildTaskProvider.get().buildSettingsFileProvider)
|
||||||
|
interopTask.dependsOn(podBuildTaskProvider)
|
||||||
|
}
|
||||||
|
|
||||||
project.findProperty(CFLAGS_PROPERTY)?.toString()?.let { args ->
|
project.findProperty(CFLAGS_PROPERTY)?.toString()?.let { args ->
|
||||||
// Xcode quotes around paths with spaces.
|
// Xcode quotes around paths with spaces.
|
||||||
// Here and below we need to split such paths taking this into account.
|
// Here and below we need to split such paths taking this into account.
|
||||||
@@ -215,23 +222,30 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
|||||||
interop.compilerOpts.addAll(args.splitQuotedArgs().map { "-F$it" })
|
interop.compilerOpts.addAll(args.splitQuotedArgs().map { "-F$it" })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show a human-readable error messages if the interop is created
|
|
||||||
// but there are no parameters set by Xcode or manually by user (KT-31062).
|
|
||||||
interopTask.doFirst { _ ->
|
interopTask.doFirst { _ ->
|
||||||
val hasCompilerOpts = interop.compilerOpts.isNotEmpty()
|
// Since we cannot expand the configuration phase of interop tasks
|
||||||
val hasHeaderSearchPath = interop.includeDirs.let {
|
// receiving the required environment variables happens on execution phase.
|
||||||
!it.headerFilterDirs.isEmpty || !it.allHeadersDirs.isEmpty
|
// TODO This needs to be fixed to improve UP-TO-DATE checks.
|
||||||
}
|
if (project.findProperty(TARGET_PROPERTY) == null && project.findProperty(CONFIGURATION_PROPERTY) == null) {
|
||||||
|
val podBuildTaskProvider = project.tasks.named(target.toBuildDependenciesTaskName, PodBuildTask::class.java)
|
||||||
|
val buildSettings =
|
||||||
|
podBuildTaskProvider.get().buildSettingsFileProvider.get()
|
||||||
|
?.inputStream()
|
||||||
|
?.use {
|
||||||
|
PodBuildSettingsProperties.readSettingsFromStream(it)
|
||||||
|
}
|
||||||
|
|
||||||
check(hasCompilerOpts || hasHeaderSearchPath) {
|
buildSettings?.cflags?.let { args ->
|
||||||
"""
|
// Xcode quotes around paths with spaces.
|
||||||
|Cannot perform cinterop processing for module ${pod.moduleName}: cannot determine headers location.
|
// Here and below we need to split such paths taking this into account.
|
||||||
|
|
interop.compilerOpts.addAll(args.splitQuotedArgs())
|
||||||
|Probably the build is executed from command line.
|
}
|
||||||
|Note that a Kotlin/Native module using CocoaPods dependencies can be built only from Xcode.
|
buildSettings?.headerPaths?.let { args ->
|
||||||
|
|
interop.compilerOpts.addAll(args.splitQuotedArgs().map { "-I$it" })
|
||||||
|See details at https://kotlinlang.org/docs/reference/native/cocoapods.html#interoperability.
|
}
|
||||||
""".trimMargin()
|
buildSettings?.frameworkPaths?.let { args ->
|
||||||
|
interop.compilerOpts.addAll(args.splitQuotedArgs().map { "-F$it" })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,6 +253,109 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun registerDummyFrameworkTask(
|
||||||
|
project: Project,
|
||||||
|
cocoapodsExtension: CocoapodsExtension
|
||||||
|
) {
|
||||||
|
project.tasks.register(DUMMY_FRAMEWORK_TASK_NAME, DummyFrameworkTask::class.java) {
|
||||||
|
it.settings = cocoapodsExtension
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun registerPodspecTask(
|
||||||
|
project: Project,
|
||||||
|
cocoapodsExtension: CocoapodsExtension
|
||||||
|
) {
|
||||||
|
val dummyFrameworkTaskProvider = project.tasks.named(DUMMY_FRAMEWORK_TASK_NAME)
|
||||||
|
|
||||||
|
project.tasks.register(POD_SPEC_TASK_NAME, PodspecTask::class.java) {
|
||||||
|
it.group = TASK_GROUP
|
||||||
|
it.description = "Generates a podspec file for CocoaPods import"
|
||||||
|
it.cocoapodsExtension = cocoapodsExtension
|
||||||
|
it.dependsOn(dummyFrameworkTaskProvider)
|
||||||
|
val generateWrapper = project.findProperty(GENERATE_WRAPPER_PROPERTY)?.toString()?.toBoolean() ?: false
|
||||||
|
if (generateWrapper) {
|
||||||
|
it.dependsOn(":wrapper")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun registerPodInstallTask(
|
||||||
|
project: Project,
|
||||||
|
cocoapodsExtension: CocoapodsExtension
|
||||||
|
) {
|
||||||
|
|
||||||
|
val podspecTaskProvider = project.tasks.named(POD_SPEC_TASK_NAME, PodspecTask::class.java)
|
||||||
|
|
||||||
|
project.tasks.register(POD_INSTALL_TASK_NAME, PodInstallTask::class.java) {
|
||||||
|
it.group = TASK_GROUP
|
||||||
|
it.description = "Invokes `pod install` call within Podfile location directory"
|
||||||
|
it.cocoapodsExtension = cocoapodsExtension
|
||||||
|
it.dependsOn(podspecTaskProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun registerPodSetupBuildTasks(
|
||||||
|
project: Project,
|
||||||
|
kotlinExtension: KotlinMultiplatformExtension,
|
||||||
|
cocoapodsExtension: CocoapodsExtension
|
||||||
|
) {
|
||||||
|
|
||||||
|
val podInstallTaskProvider = project.tasks.named(POD_INSTALL_TASK_NAME, PodInstallTask::class.java)
|
||||||
|
|
||||||
|
kotlinExtension.supportedTargets().all { target ->
|
||||||
|
project.tasks.register(target.toBuildSetupTaskName, PodSetupBuildTask::class.java) {
|
||||||
|
it.group = TASK_GROUP
|
||||||
|
it.kotlinNativeTarget = target
|
||||||
|
it.description = "Collect environment variables from .xcworkspace file"
|
||||||
|
it.cocoapodsExtension = cocoapodsExtension
|
||||||
|
it.podsXcodeProjDirProvider = podInstallTaskProvider.get().podsXcodeProjDirProvider
|
||||||
|
it.dependsOn(podInstallTaskProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun registerPodBuildTasks(
|
||||||
|
project: Project,
|
||||||
|
kotlinExtension: KotlinMultiplatformExtension,
|
||||||
|
cocoapodsExtension: CocoapodsExtension
|
||||||
|
) {
|
||||||
|
|
||||||
|
kotlinExtension.supportedTargets().all { target ->
|
||||||
|
|
||||||
|
val podSetupBuildTaskProvider = project.tasks.named(target.toBuildSetupTaskName, PodSetupBuildTask::class.java)
|
||||||
|
|
||||||
|
project.tasks.register(target.toBuildDependenciesTaskName, PodBuildTask::class.java) {
|
||||||
|
it.group = TASK_GROUP
|
||||||
|
it.description = "Calls `xcodebuild` on xcworkspace for the pod scheme"
|
||||||
|
it.kotlinNativeTarget = target
|
||||||
|
it.cocoapodsExtension = cocoapodsExtension
|
||||||
|
it.podsXcodeProjDirProvider = (podSetupBuildTaskProvider.get()).podsXcodeProjDirProvider
|
||||||
|
it.buildSettingsFileProvider = (podSetupBuildTaskProvider.get()).buildSettingsFileProvider
|
||||||
|
it.dependsOn(podSetupBuildTaskProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun registerPodImportTask(
|
||||||
|
project: Project,
|
||||||
|
kotlinExtension: KotlinMultiplatformExtension
|
||||||
|
) {
|
||||||
|
|
||||||
|
project.tasks.register(POD_IMPORT_TASK_NAME) {
|
||||||
|
it.group = TASK_GROUP
|
||||||
|
it.description = "Called on Gradle sync, depends on Cinterop tasks for every used pod"
|
||||||
|
|
||||||
|
kotlinExtension.supportedTargets().all { target ->
|
||||||
|
target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME).cinterops.all { interop ->
|
||||||
|
val interopTaskProvider = project.tasks.named(interop.interopProcessingTaskName)
|
||||||
|
it.dependsOn(interopTaskProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun apply(project: Project): Unit = with(project) {
|
override fun apply(project: Project): Unit = with(project) {
|
||||||
|
|
||||||
pluginManager.withPlugin("kotlin-multiplatform") {
|
pluginManager.withPlugin("kotlin-multiplatform") {
|
||||||
@@ -247,8 +364,13 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
|||||||
|
|
||||||
kotlinExtension.addExtension(EXTENSION_NAME, cocoapodsExtension)
|
kotlinExtension.addExtension(EXTENSION_NAME, cocoapodsExtension)
|
||||||
createDefaultFrameworks(kotlinExtension, cocoapodsExtension)
|
createDefaultFrameworks(kotlinExtension, cocoapodsExtension)
|
||||||
|
registerDummyFrameworkTask(project, cocoapodsExtension)
|
||||||
createSyncTask(project, kotlinExtension)
|
createSyncTask(project, kotlinExtension)
|
||||||
createPodspecGenerationTask(project, cocoapodsExtension)
|
registerPodspecTask(project, cocoapodsExtension)
|
||||||
|
registerPodInstallTask(project, cocoapodsExtension)
|
||||||
|
registerPodSetupBuildTasks(project, kotlinExtension, cocoapodsExtension)
|
||||||
|
registerPodBuildTasks(project, kotlinExtension, cocoapodsExtension)
|
||||||
|
registerPodImportTask(project, kotlinExtension)
|
||||||
createInterops(project, kotlinExtension, cocoapodsExtension)
|
createInterops(project, kotlinExtension, cocoapodsExtension)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,6 +379,12 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
|||||||
const val EXTENSION_NAME = "cocoapods"
|
const val EXTENSION_NAME = "cocoapods"
|
||||||
const val TASK_GROUP = "CocoaPods"
|
const val TASK_GROUP = "CocoaPods"
|
||||||
const val SYNC_TASK_NAME = "syncFramework"
|
const val SYNC_TASK_NAME = "syncFramework"
|
||||||
|
const val POD_SPEC_TASK_NAME = "podspec"
|
||||||
|
const val DUMMY_FRAMEWORK_TASK_NAME = "generateDummyFramework"
|
||||||
|
const val POD_INSTALL_TASK_NAME = "podInstall"
|
||||||
|
const val POD_SETUP_BUILD_TASK_NAME = "podSetupBuild"
|
||||||
|
const val POD_BUILD_DEPENDENCIES_TASK_NAME = "podBuildDependencies"
|
||||||
|
const val POD_IMPORT_TASK_NAME = "podImport"
|
||||||
|
|
||||||
// We don't move these properties in PropertiesProvider because
|
// We don't move these properties in PropertiesProvider because
|
||||||
// they are not intended to be overridden in local.properties.
|
// they are not intended to be overridden in local.properties.
|
||||||
|
|||||||
+279
@@ -0,0 +1,279 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.targets.native.tasks
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
import org.gradle.api.tasks.Optional
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.cocoapods.cocoapodsBuildDirs
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.native.tasks.PodBuildTask.Companion.toValidSDK
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.math.BigInteger
|
||||||
|
import java.security.MessageDigest
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
abstract class AdvancedCocoapodsTask : DefaultTask() {
|
||||||
|
@get:Nested
|
||||||
|
lateinit var cocoapodsExtension: CocoapodsExtension
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun commonInvoke() {
|
||||||
|
podfileCheck(cocoapodsExtension)
|
||||||
|
specificInvoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun specificInvoke()
|
||||||
|
|
||||||
|
private fun podfileCheck(cocoapodsExtension: CocoapodsExtension) {
|
||||||
|
check(cocoapodsExtension.podfile != null) {
|
||||||
|
"Execution of task '$name' requires the path to the Podfile. Specify it in the file ${project.buildFile.absolutePath}."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The task takes the path to the Podfile and calls `pod install`
|
||||||
|
* to obtain sources or artifacts for the declared dependencies.
|
||||||
|
* This task is a part of CocoaPods integration infrastructure.
|
||||||
|
*/
|
||||||
|
open class PodInstallTask : AdvancedCocoapodsTask() {
|
||||||
|
|
||||||
|
@get:InputFile
|
||||||
|
@get:Optional
|
||||||
|
internal val podfileProvider: Provider<File?> = project.provider { cocoapodsExtension.podfile }
|
||||||
|
|
||||||
|
@get:OutputDirectory
|
||||||
|
@get:Optional
|
||||||
|
internal val podsXcodeProjDirProvider: Provider<File?> = project.provider {
|
||||||
|
cocoapodsExtension.podfile
|
||||||
|
?.parentFile
|
||||||
|
?.resolve("Pods")
|
||||||
|
?.resolve("Pods.xcodeproj")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun specificInvoke() {
|
||||||
|
val podfileDir = podfileProvider.get()!!.parentFile
|
||||||
|
val podInstallProcess = ProcessBuilder("pod", "install").apply {
|
||||||
|
directory(podfileDir)
|
||||||
|
inheritIO()
|
||||||
|
}.start()
|
||||||
|
val podInstallRetCode = podInstallProcess.waitFor()
|
||||||
|
check(podInstallRetCode == 0) { "Unable to run 'pod install', return code $podInstallRetCode" }
|
||||||
|
|
||||||
|
val podsXcprojFile = podsXcodeProjDirProvider.get()
|
||||||
|
check(podsXcprojFile != null && podsXcprojFile.exists() && podsXcprojFile.isDirectory) {
|
||||||
|
"The directory 'Pods/Pods.xcodeproj' was not created as a result of the `pod install` call."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class PodSetupBuildTask : AdvancedCocoapodsTask() {
|
||||||
|
@get:InputDirectory
|
||||||
|
@get:Optional
|
||||||
|
internal lateinit var podsXcodeProjDirProvider: Provider<File?>
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
lateinit var kotlinNativeTarget: KotlinNativeTarget
|
||||||
|
|
||||||
|
@get:OutputFile
|
||||||
|
@get:Optional
|
||||||
|
internal val buildSettingsFileProvider: Provider<File?> =
|
||||||
|
project.provider {
|
||||||
|
project
|
||||||
|
.cocoapodsBuildDirs
|
||||||
|
.root
|
||||||
|
.resolve("buildSettings")
|
||||||
|
.resolve(kotlinNativeTarget.toBuildSettingsFileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun specificInvoke() {
|
||||||
|
val podsXcodeProjDir = podsXcodeProjDirProvider.get()
|
||||||
|
|
||||||
|
val buildSettingsReceivingCommand = listOf(
|
||||||
|
"xcodebuild", "-showBuildSettings",
|
||||||
|
"-project", podsXcodeProjDir!!.name,
|
||||||
|
"-scheme", cocoapodsExtension.frameworkName,
|
||||||
|
"-sdk", kotlinNativeTarget.toValidSDK
|
||||||
|
)
|
||||||
|
|
||||||
|
val buildSettingsProcess = ProcessBuilder(buildSettingsReceivingCommand)
|
||||||
|
.apply {
|
||||||
|
directory(podsXcodeProjDir!!.parentFile)
|
||||||
|
}.start()
|
||||||
|
|
||||||
|
val buildSettingsRetCode = buildSettingsProcess.waitFor()
|
||||||
|
check(buildSettingsRetCode == 0) {
|
||||||
|
"Unable to run '${buildSettingsReceivingCommand.joinToString(" ")}' return code $buildSettingsRetCode"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val stdOut = buildSettingsProcess.inputStream
|
||||||
|
|
||||||
|
val buildSettingsProperties = PodBuildSettingsProperties.readSettingsFromStream(stdOut)
|
||||||
|
buildSettingsProperties.writeSettings(buildSettingsFileProvider.get()!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val KotlinNativeTarget.toBuildSettingsFileName: String
|
||||||
|
get() = "build-settings-$disambiguationClassifier.properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The task compiles external cocoa pods sources.
|
||||||
|
*/
|
||||||
|
open class PodBuildTask : AdvancedCocoapodsTask() {
|
||||||
|
@get:InputDirectory
|
||||||
|
@get:Optional
|
||||||
|
internal lateinit var podsXcodeProjDirProvider: Provider<File?>
|
||||||
|
|
||||||
|
@get:InputFile
|
||||||
|
@get:Optional
|
||||||
|
internal lateinit var buildSettingsFileProvider: Provider<File?>
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
lateinit var kotlinNativeTarget: KotlinNativeTarget
|
||||||
|
|
||||||
|
@get:OutputFile
|
||||||
|
@get:Optional
|
||||||
|
internal val buildDirHashFileProvider: Provider<File?> =
|
||||||
|
project.provider {
|
||||||
|
project
|
||||||
|
.cocoapodsBuildDirs
|
||||||
|
.root
|
||||||
|
.resolve("buildDirHashSums")
|
||||||
|
.resolve(kotlinNativeTarget.toBuildDirHashSumFileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun specificInvoke() {
|
||||||
|
val podBuildSettings = PodBuildSettingsProperties.readSettingsFromStream(
|
||||||
|
FileInputStream(buildSettingsFileProvider.get())
|
||||||
|
)
|
||||||
|
|
||||||
|
val podsXcodeProjDir = podsXcodeProjDirProvider.get()
|
||||||
|
|
||||||
|
cocoapodsExtension.pods.all {
|
||||||
|
|
||||||
|
val podXcodeBuildCommand = listOf(
|
||||||
|
"xcodebuild",
|
||||||
|
"-project", podsXcodeProjDir!!.name,
|
||||||
|
"-scheme", it.moduleName,
|
||||||
|
"-sdk", kotlinNativeTarget.toValidSDK,
|
||||||
|
"-configuration", podBuildSettings.configuration
|
||||||
|
)
|
||||||
|
|
||||||
|
val podBuildProcess = ProcessBuilder(podXcodeBuildCommand)
|
||||||
|
.apply {
|
||||||
|
directory(podsXcodeProjDir!!.parentFile)
|
||||||
|
inheritIO()
|
||||||
|
}.start()
|
||||||
|
|
||||||
|
val podBuildRetCode = podBuildProcess.waitFor()
|
||||||
|
check(podBuildRetCode == 0) {
|
||||||
|
"Unable to run '${podXcodeBuildCommand.joinToString(" ")}' return code $podBuildRetCode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val buildDirHashSumFile = buildDirHashFileProvider.get()!!
|
||||||
|
buildDirHashSumFile!!.parentFile.mkdirs()
|
||||||
|
buildDirHashSumFile!!.createNewFile()
|
||||||
|
check(buildDirHashSumFile!!.exists()) {
|
||||||
|
"Unable to create file ${buildDirHashSumFile.toRelativeString(project.projectDir)}!"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildDirHashSumFile.writeText(getFileChecksumStr(project.file(podBuildSettings.buildDir)))
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private fun getFileChecksumStr(file: File): String {
|
||||||
|
val digest = MessageDigest.getInstance("SHA-1")
|
||||||
|
file.walkTopDown().forEach {
|
||||||
|
val byteArray = ByteArray(1024)
|
||||||
|
var bytesCount = 0
|
||||||
|
if (it.isFile) {
|
||||||
|
val inputStream = it.inputStream()
|
||||||
|
while (inputStream.read(byteArray).also { bt -> bytesCount = bt } != -1) {
|
||||||
|
digest.update(byteArray, 0, bytesCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val buildDirHashSumStr = BigInteger(1, digest.digest()).toString(16).padStart(32, '0')
|
||||||
|
return buildDirHashSumStr
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KotlinNativeTarget.toBuildDirHashSumFileName: String
|
||||||
|
get() = "build-dir-hash-$disambiguationClassifier.txt"
|
||||||
|
|
||||||
|
internal val KotlinNativeTarget.toValidSDK: String
|
||||||
|
get() {
|
||||||
|
return when (konanTarget) {
|
||||||
|
KonanTarget.IOS_X64 -> "iphonesimulator"
|
||||||
|
KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64 -> "iphoneos"
|
||||||
|
KonanTarget.WATCHOS_X86, KonanTarget.WATCHOS_X64 -> "watchsimulator"
|
||||||
|
KonanTarget.WATCHOS_ARM32, KonanTarget.WATCHOS_ARM64 -> "watchos"
|
||||||
|
KonanTarget.TVOS_X64 -> "appletvsimulator"
|
||||||
|
KonanTarget.TVOS_ARM64 -> "appletvos"
|
||||||
|
KonanTarget.MACOS_X64 -> "macos"
|
||||||
|
else -> throw Error("Bad target ${konanTarget.name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal data class PodBuildSettingsProperties(
|
||||||
|
internal val buildDir: String,
|
||||||
|
internal val configuration: String,
|
||||||
|
internal val cflags: String? = null,
|
||||||
|
internal val headerPaths: String? = null,
|
||||||
|
internal val frameworkPaths: String? = null
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun writeSettings(buildSettingsFile: File) {
|
||||||
|
buildSettingsFile.parentFile.mkdirs()
|
||||||
|
buildSettingsFile.createNewFile()
|
||||||
|
|
||||||
|
check(buildSettingsFile.exists()) { "Unable to create file ${buildSettingsFile.path}!" }
|
||||||
|
|
||||||
|
with(Properties()) {
|
||||||
|
setProperty(BUILD_DIR, buildDir)
|
||||||
|
setProperty(CONFIGURATION, configuration)
|
||||||
|
cflags?.let { setProperty(OTHER_CFLAGS, it) }
|
||||||
|
headerPaths?.let { setProperty(HEADER_SEARCH_PATHS, it) }
|
||||||
|
frameworkPaths?.let { setProperty(FRAMEWORK_SEARCH_PATHS, it) }
|
||||||
|
buildSettingsFile.outputStream().use {
|
||||||
|
store(it, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val BUILD_DIR: String = "BUILD_DIR"
|
||||||
|
const val CONFIGURATION: String = "CONFIGURATION"
|
||||||
|
const val OTHER_CFLAGS: String = "OTHER_CFLAGS"
|
||||||
|
const val HEADER_SEARCH_PATHS: String = "HEADER_SEARCH_PATHS"
|
||||||
|
const val FRAMEWORK_SEARCH_PATHS: String = "FRAMEWORK_SEARCH_PATHS"
|
||||||
|
|
||||||
|
fun readSettingsFromStream(inputStream: InputStream): PodBuildSettingsProperties {
|
||||||
|
with(Properties()) {
|
||||||
|
load(inputStream)
|
||||||
|
return PodBuildSettingsProperties(
|
||||||
|
getProperty(BUILD_DIR),
|
||||||
|
getProperty(CONFIGURATION),
|
||||||
|
getProperty(OTHER_CFLAGS),
|
||||||
|
getProperty(HEADER_SEARCH_PATHS),
|
||||||
|
getProperty(FRAMEWORK_SEARCH_PATHS)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+60
-61
@@ -28,20 +28,16 @@ open class PodspecTask : DefaultTask() {
|
|||||||
|
|
||||||
private val specName = project.name.asValidFrameworkName()
|
private val specName = project.name.asValidFrameworkName()
|
||||||
|
|
||||||
@OutputFile
|
@get:OutputFile
|
||||||
val outputFile: File = project.projectDir.resolve("$specName.podspec")
|
internal val outputFileProvider: Provider<File> = project.provider { project.file("$specName.podspec") }
|
||||||
|
|
||||||
@Input
|
|
||||||
val frameworkNameProvider: Provider<String> = project.provider { settings.frameworkName }
|
|
||||||
|
|
||||||
@get:Nested
|
@get:Nested
|
||||||
internal lateinit var settings: CocoapodsExtension
|
internal lateinit var cocoapodsExtension: CocoapodsExtension
|
||||||
|
|
||||||
// TODO: Handle Framework name customization - rename the framework during sync process.
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun generate() {
|
fun generate() {
|
||||||
val frameworkDir = project.cocoapodsBuildDirs.framework.relativeTo(outputFile.parentFile).path
|
val frameworkDir = project.cocoapodsBuildDirs.framework.relativeTo(outputFileProvider.get().parentFile).path
|
||||||
val dependencies = settings.pods.map { pod ->
|
val dependencies = cocoapodsExtension.pods.map { pod ->
|
||||||
val versionSuffix = if (pod.version != null) ", '${pod.version}'" else ""
|
val versionSuffix = if (pod.version != null) ", '${pod.version}'" else ""
|
||||||
"| spec.dependency '${pod.name}'$versionSuffix"
|
"| spec.dependency '${pod.name}'$versionSuffix"
|
||||||
}.joinToString(separator = "\n")
|
}.joinToString(separator = "\n")
|
||||||
@@ -61,67 +57,70 @@ open class PodspecTask : DefaultTask() {
|
|||||||
val syncTask = "${project.path}:$SYNC_TASK_NAME"
|
val syncTask = "${project.path}:$SYNC_TASK_NAME"
|
||||||
|
|
||||||
|
|
||||||
outputFile.writeText(
|
with(outputFileProvider.get()) {
|
||||||
"""
|
writeText(
|
||||||
|Pod::Spec.new do |spec|
|
"""
|
||||||
| spec.name = '$specName'
|
|Pod::Spec.new do |spec|
|
||||||
| spec.version = '${settings.version}'
|
| spec.name = '$specName'
|
||||||
| spec.homepage = '${settings.homepage.orEmpty()}'
|
| spec.version = '${cocoapodsExtension.version}'
|
||||||
| spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" }
|
| spec.homepage = '${cocoapodsExtension.homepage.orEmpty()}'
|
||||||
| spec.authors = '${settings.authors.orEmpty()}'
|
| spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" }
|
||||||
| spec.license = '${settings.license.orEmpty()}'
|
| spec.authors = '${cocoapodsExtension.authors.orEmpty()}'
|
||||||
| spec.summary = '${settings.summary.orEmpty()}'
|
| spec.license = '${cocoapodsExtension.license.orEmpty()}'
|
||||||
|
|
| spec.summary = '${cocoapodsExtension.summary.orEmpty()}'
|
||||||
| spec.static_framework = true
|
|
|
||||||
| spec.vendored_frameworks = "$frameworkDir/${frameworkNameProvider.get()}.framework"
|
| spec.static_framework = true
|
||||||
| spec.libraries = "c++"
|
| spec.vendored_frameworks = "$frameworkDir/${cocoapodsExtension.frameworkName}.framework"
|
||||||
| spec.module_name = "#{spec.name}_umbrella"
|
| spec.libraries = "c++"
|
||||||
|
|
| spec.module_name = "#{spec.name}_umbrella"
|
||||||
$dependencies
|
|
|
||||||
|
|
$dependencies
|
||||||
| spec.pod_target_xcconfig = {
|
|
|
||||||
| 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64',
|
| spec.pod_target_xcconfig = {
|
||||||
| 'KOTLIN_TARGET[sdk=iphoneos*]' => '$KOTLIN_TARGET_FOR_IOS_DEVICE',
|
| 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64',
|
||||||
| 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x86',
|
| 'KOTLIN_TARGET[sdk=iphoneos*]' => '$KOTLIN_TARGET_FOR_IOS_DEVICE',
|
||||||
| 'KOTLIN_TARGET[sdk=watchos*]' => '$KOTLIN_TARGET_FOR_WATCHOS_DEVICE',
|
| 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x86',
|
||||||
| 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64',
|
| 'KOTLIN_TARGET[sdk=watchos*]' => '$KOTLIN_TARGET_FOR_WATCHOS_DEVICE',
|
||||||
| 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64',
|
| 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64',
|
||||||
| 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64'
|
| 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64',
|
||||||
| }
|
| 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64'
|
||||||
|
|
| }
|
||||||
| spec.script_phases = [
|
|
|
||||||
| {
|
| spec.script_phases = [
|
||||||
| :name => 'Build $specName',
|
| {
|
||||||
| :execution_position => :before_compile,
|
| :name => 'Build $specName',
|
||||||
| :shell_path => '/bin/sh',
|
| :execution_position => :before_compile,
|
||||||
| :script => <<-SCRIPT
|
| :shell_path => '/bin/sh',
|
||||||
| set -ev
|
| :script => <<-SCRIPT
|
||||||
| REPO_ROOT="${'$'}PODS_TARGET_SRCROOT"
|
| set -ev
|
||||||
| "$gradleCommand" -p "${'$'}REPO_ROOT" $syncTask \
|
| REPO_ROOT="${'$'}PODS_TARGET_SRCROOT/../"
|
||||||
| -P${KotlinCocoapodsPlugin.TARGET_PROPERTY}=${'$'}KOTLIN_TARGET \
|
| "$gradleCommand" -p "${'$'}REPO_ROOT" $syncTask \
|
||||||
| -P${KotlinCocoapodsPlugin.CONFIGURATION_PROPERTY}=${'$'}CONFIGURATION \
|
| -P${KotlinCocoapodsPlugin.TARGET_PROPERTY}=${'$'}KOTLIN_TARGET \
|
||||||
| -P${KotlinCocoapodsPlugin.CFLAGS_PROPERTY}="${'$'}OTHER_CFLAGS" \
|
| -P${KotlinCocoapodsPlugin.CONFIGURATION_PROPERTY}=${'$'}CONFIGURATION \
|
||||||
| -P${KotlinCocoapodsPlugin.HEADER_PATHS_PROPERTY}="${'$'}HEADER_SEARCH_PATHS" \
|
| -P${KotlinCocoapodsPlugin.CFLAGS_PROPERTY}="${'$'}OTHER_CFLAGS" \
|
||||||
| -P${KotlinCocoapodsPlugin.FRAMEWORK_PATHS_PROPERTY}="${'$'}FRAMEWORK_SEARCH_PATHS"
|
| -P${KotlinCocoapodsPlugin.HEADER_PATHS_PROPERTY}="${'$'}HEADER_SEARCH_PATHS" \
|
||||||
| SCRIPT
|
| -P${KotlinCocoapodsPlugin.FRAMEWORK_PATHS_PROPERTY}="${'$'}FRAMEWORK_SEARCH_PATHS"
|
||||||
| }
|
| SCRIPT
|
||||||
| ]
|
| }
|
||||||
|end
|
| ]
|
||||||
|
|end
|
||||||
""".trimMargin()
|
""".trimMargin()
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.quiet(
|
logger.quiet(
|
||||||
"""
|
"""
|
||||||
Generated a podspec file at: ${outputFile.absolutePath}.
|
Generated a podspec file at: ${absolutePath}.
|
||||||
To include it in your Xcode project, add the following dependency snippet in your Podfile:
|
To include it in your Xcode project, add the following dependency snippet in your Podfile:
|
||||||
|
|
||||||
pod '$specName', :path => '${outputFile.parentFile.absolutePath}'
|
pod '$specName', :path => '${parentFile.absolutePath}'
|
||||||
|
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a dummy framework in the target directory.
|
* Creates a dummy framework in the target directory.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user