[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.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>
|
||||
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPSourceSetsFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSBrowserFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSNodeFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinMPPFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSBrowserFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSNodeFrameworkSupportProvider"/>
|
||||
<pluginDescriptions implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradlePluginDescription"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinNonJvmGutterConfigurator" />
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModelResolver" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectResolverExtension" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleCoroutineDebugProjectResolver" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.kapt.idea.KaptProjectResolverExtension" order="last"/>
|
||||
<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="org.jetbrains.plugins.gradle">
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinMPPSourceSetsFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJavaFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSBrowserFrameworkSupportProvider"/>
|
||||
<frameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinJSNodeFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinMPPFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJavaFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport
|
||||
implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSBrowserFrameworkSupportProvider"/>
|
||||
<kotlinDslFrameworkSupport
|
||||
implementation="org.jetbrains.kotlin.idea.configuration.KotlinDslGradleKotlinJSNodeFrameworkSupportProvider"/>
|
||||
<pluginDescriptions implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradlePluginDescription"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinNonJvmGutterConfigurator"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModelResolver" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.cocoapods.KotlinCocoaPodsModelResolver" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectResolverExtension" order="first"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleCoroutineDebugProjectResolver" order="last"/>
|
||||
<projectResolve implementation="org.jetbrains.kotlin.kapt.idea.KaptProjectResolverExtension" order="last"/>
|
||||
<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">
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleLibraryDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinTargetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.KotlinJavaMPPSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibraryDataService"/>
|
||||
<externalSystemTaskNotificationListener implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsUpdater"/>
|
||||
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptOutOfSourceNotificationProvider"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleLibraryDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinTargetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.KotlinJavaMPPSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibraryDataService"/>
|
||||
<externalSystemTaskNotificationListener implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsUpdater"/>
|
||||
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptOutOfSourceNotificationProvider"/>
|
||||
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestClassGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestClassGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestMethodGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestMethodGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestClassGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestClassGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinJvmTestMethodGradleConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinMultiplatformJvmTestMethodGradleConfigurationProducer"/>
|
||||
|
||||
</extensions>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.allopen.ide.AllOpenGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.scripting.idea.plugin.ScriptingGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.kapt.idea.KaptGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.noarg.ide.NoArgGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlinx.serialization.idea.KotlinSerializationGradleImportHandler"/>
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.allopen.ide.AllOpenGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.scripting.idea.plugin.ScriptingGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.kapt.idea.KaptGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.noarg.ide.NoArgGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlinx.serialization.idea.KotlinSerializationGradleImportHandler"/>
|
||||
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleModuleConfigurator"/>
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinJsGradleModuleConfigurator"/>
|
||||
<gradleModelFacade implementation="org.jetbrains.kotlin.idea.inspections.gradle.DefaultGradleModelFacade"/>
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleModuleConfigurator"/>
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinJsGradleModuleConfigurator"/>
|
||||
<gradleModelFacade implementation="org.jetbrains.kotlin.idea.inspections.gradle.DefaultGradleModelFacade"/>
|
||||
|
||||
<scriptDefinitionContributor implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsContributor" order="first"/>
|
||||
<scriptAdditionalIdeaDependenciesProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptAdditionalIdeaDependenciesProvider"/>
|
||||
<scriptDefinitionContributor implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsContributor"
|
||||
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.idea.configuration.KotlinGradleSharedMultiplatformModuleBuilder"/>
|
||||
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleWebMultiplatformModuleBuilder"/>
|
||||
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleMobileMultiplatformModuleBuilder"/>
|
||||
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleMobileSharedMultiplatformModuleBuilder"/>
|
||||
</extensions>
|
||||
<moduleBuilder implementation="org.jetbrains.kotlin.ide.konan.gradle.KotlinGradleNativeMultiplatformModuleBuilder"/>
|
||||
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleSharedMultiplatformModuleBuilder"/>
|
||||
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleWebMultiplatformModuleBuilder"/>
|
||||
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleMobileMultiplatformModuleBuilder"/>
|
||||
<moduleBuilder implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleMobileSharedMultiplatformModuleBuilder"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
+13
-4
@@ -9,16 +9,25 @@ package org.jetbrains.kotlin.gradle.plugin.cocoapods
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.NamedDomainObjectSet
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.Nested
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.*
|
||||
import java.io.File
|
||||
|
||||
open class CocoapodsExtension(private val project: Project) {
|
||||
@get:Input
|
||||
val version: String
|
||||
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.
|
||||
*/
|
||||
|
||||
+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.mpp.KotlinNativeTarget
|
||||
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.lowerCamelCaseName
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
|
||||
internal val Project.cocoapodsBuildDirs: CocoapodsBuildDirs
|
||||
get() = CocoapodsBuildDirs(this)
|
||||
@@ -42,6 +50,12 @@ internal class CocoapodsBuildDirs(val project: Project) {
|
||||
|
||||
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> {
|
||||
|
||||
private fun KotlinMultiplatformExtension.supportedTargets() = targets
|
||||
@@ -70,8 +84,9 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.createSyncFrameworkTask(originalDirectory: File, buildingTask: Task) =
|
||||
tasks.create(SYNC_TASK_NAME, Sync::class.java) {
|
||||
private fun Project.createSyncFrameworkTask(originalDirectory: File, buildingTask: Task): Sync? {
|
||||
|
||||
return tasks.create(SYNC_TASK_NAME, Sync::class.java) {
|
||||
it.group = TASK_GROUP
|
||||
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.destinationDir = cocoapodsBuildDirs.framework
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSyncForFatFramework(
|
||||
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(
|
||||
project: Project,
|
||||
kotlinExtension: KotlinMultiplatformExtension,
|
||||
cocoapodsExtension: CocoapodsExtension
|
||||
) {
|
||||
val moduleNames = mutableSetOf<String>()
|
||||
|
||||
|
||||
cocoapodsExtension.pods.all { pod ->
|
||||
if (moduleNames.contains(pod.moduleName)) {
|
||||
return@all
|
||||
@@ -199,10 +197,19 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME).cinterops.create(pod.moduleName) { interop ->
|
||||
|
||||
val interopTask = project.tasks.getByPath(interop.interopProcessingTaskName)
|
||||
|
||||
interopTask.dependsOn(defTask)
|
||||
|
||||
interop.defFile = defTask.outputFile
|
||||
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 ->
|
||||
// Xcode quotes around paths with spaces.
|
||||
// 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" })
|
||||
}
|
||||
|
||||
// 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 { _ ->
|
||||
val hasCompilerOpts = interop.compilerOpts.isNotEmpty()
|
||||
val hasHeaderSearchPath = interop.includeDirs.let {
|
||||
!it.headerFilterDirs.isEmpty || !it.allHeadersDirs.isEmpty
|
||||
}
|
||||
// Since we cannot expand the configuration phase of interop tasks
|
||||
// receiving the required environment variables happens on execution phase.
|
||||
// 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) {
|
||||
"""
|
||||
|Cannot perform cinterop processing for module ${pod.moduleName}: cannot determine headers location.
|
||||
|
|
||||
|Probably the build is executed from command line.
|
||||
|Note that a Kotlin/Native module using CocoaPods dependencies can be built only from Xcode.
|
||||
|
|
||||
|See details at https://kotlinlang.org/docs/reference/native/cocoapods.html#interoperability.
|
||||
""".trimMargin()
|
||||
buildSettings?.cflags?.let { args ->
|
||||
// Xcode quotes around paths with spaces.
|
||||
// Here and below we need to split such paths taking this into account.
|
||||
interop.compilerOpts.addAll(args.splitQuotedArgs())
|
||||
}
|
||||
buildSettings?.headerPaths?.let { args ->
|
||||
interop.compilerOpts.addAll(args.splitQuotedArgs().map { "-I$it" })
|
||||
}
|
||||
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) {
|
||||
|
||||
pluginManager.withPlugin("kotlin-multiplatform") {
|
||||
@@ -247,8 +364,13 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
|
||||
kotlinExtension.addExtension(EXTENSION_NAME, cocoapodsExtension)
|
||||
createDefaultFrameworks(kotlinExtension, cocoapodsExtension)
|
||||
registerDummyFrameworkTask(project, cocoapodsExtension)
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -257,6 +379,12 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
const val EXTENSION_NAME = "cocoapods"
|
||||
const val TASK_GROUP = "CocoaPods"
|
||||
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
|
||||
// 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()
|
||||
|
||||
@OutputFile
|
||||
val outputFile: File = project.projectDir.resolve("$specName.podspec")
|
||||
|
||||
@Input
|
||||
val frameworkNameProvider: Provider<String> = project.provider { settings.frameworkName }
|
||||
@get:OutputFile
|
||||
internal val outputFileProvider: Provider<File> = project.provider { project.file("$specName.podspec") }
|
||||
|
||||
@get:Nested
|
||||
internal lateinit var settings: CocoapodsExtension
|
||||
internal lateinit var cocoapodsExtension: CocoapodsExtension
|
||||
|
||||
// TODO: Handle Framework name customization - rename the framework during sync process.
|
||||
@TaskAction
|
||||
fun generate() {
|
||||
val frameworkDir = project.cocoapodsBuildDirs.framework.relativeTo(outputFile.parentFile).path
|
||||
val dependencies = settings.pods.map { pod ->
|
||||
val frameworkDir = project.cocoapodsBuildDirs.framework.relativeTo(outputFileProvider.get().parentFile).path
|
||||
val dependencies = cocoapodsExtension.pods.map { pod ->
|
||||
val versionSuffix = if (pod.version != null) ", '${pod.version}'" else ""
|
||||
"| spec.dependency '${pod.name}'$versionSuffix"
|
||||
}.joinToString(separator = "\n")
|
||||
@@ -61,67 +57,70 @@ open class PodspecTask : DefaultTask() {
|
||||
val syncTask = "${project.path}:$SYNC_TASK_NAME"
|
||||
|
||||
|
||||
outputFile.writeText(
|
||||
"""
|
||||
|Pod::Spec.new do |spec|
|
||||
| spec.name = '$specName'
|
||||
| spec.version = '${settings.version}'
|
||||
| spec.homepage = '${settings.homepage.orEmpty()}'
|
||||
| spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" }
|
||||
| spec.authors = '${settings.authors.orEmpty()}'
|
||||
| spec.license = '${settings.license.orEmpty()}'
|
||||
| spec.summary = '${settings.summary.orEmpty()}'
|
||||
|
|
||||
| spec.static_framework = true
|
||||
| spec.vendored_frameworks = "$frameworkDir/${frameworkNameProvider.get()}.framework"
|
||||
| spec.libraries = "c++"
|
||||
| spec.module_name = "#{spec.name}_umbrella"
|
||||
|
|
||||
$dependencies
|
||||
|
|
||||
| spec.pod_target_xcconfig = {
|
||||
| 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64',
|
||||
| 'KOTLIN_TARGET[sdk=iphoneos*]' => '$KOTLIN_TARGET_FOR_IOS_DEVICE',
|
||||
| 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x86',
|
||||
| 'KOTLIN_TARGET[sdk=watchos*]' => '$KOTLIN_TARGET_FOR_WATCHOS_DEVICE',
|
||||
| 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64',
|
||||
| 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64',
|
||||
| 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64'
|
||||
| }
|
||||
|
|
||||
| spec.script_phases = [
|
||||
| {
|
||||
| :name => 'Build $specName',
|
||||
| :execution_position => :before_compile,
|
||||
| :shell_path => '/bin/sh',
|
||||
| :script => <<-SCRIPT
|
||||
| set -ev
|
||||
| REPO_ROOT="${'$'}PODS_TARGET_SRCROOT"
|
||||
| "$gradleCommand" -p "${'$'}REPO_ROOT" $syncTask \
|
||||
| -P${KotlinCocoapodsPlugin.TARGET_PROPERTY}=${'$'}KOTLIN_TARGET \
|
||||
| -P${KotlinCocoapodsPlugin.CONFIGURATION_PROPERTY}=${'$'}CONFIGURATION \
|
||||
| -P${KotlinCocoapodsPlugin.CFLAGS_PROPERTY}="${'$'}OTHER_CFLAGS" \
|
||||
| -P${KotlinCocoapodsPlugin.HEADER_PATHS_PROPERTY}="${'$'}HEADER_SEARCH_PATHS" \
|
||||
| -P${KotlinCocoapodsPlugin.FRAMEWORK_PATHS_PROPERTY}="${'$'}FRAMEWORK_SEARCH_PATHS"
|
||||
| SCRIPT
|
||||
| }
|
||||
| ]
|
||||
|end
|
||||
with(outputFileProvider.get()) {
|
||||
writeText(
|
||||
"""
|
||||
|Pod::Spec.new do |spec|
|
||||
| spec.name = '$specName'
|
||||
| spec.version = '${cocoapodsExtension.version}'
|
||||
| spec.homepage = '${cocoapodsExtension.homepage.orEmpty()}'
|
||||
| spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" }
|
||||
| spec.authors = '${cocoapodsExtension.authors.orEmpty()}'
|
||||
| spec.license = '${cocoapodsExtension.license.orEmpty()}'
|
||||
| spec.summary = '${cocoapodsExtension.summary.orEmpty()}'
|
||||
|
|
||||
| spec.static_framework = true
|
||||
| spec.vendored_frameworks = "$frameworkDir/${cocoapodsExtension.frameworkName}.framework"
|
||||
| spec.libraries = "c++"
|
||||
| spec.module_name = "#{spec.name}_umbrella"
|
||||
|
|
||||
$dependencies
|
||||
|
|
||||
| spec.pod_target_xcconfig = {
|
||||
| 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64',
|
||||
| 'KOTLIN_TARGET[sdk=iphoneos*]' => '$KOTLIN_TARGET_FOR_IOS_DEVICE',
|
||||
| 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x86',
|
||||
| 'KOTLIN_TARGET[sdk=watchos*]' => '$KOTLIN_TARGET_FOR_WATCHOS_DEVICE',
|
||||
| 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64',
|
||||
| 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64',
|
||||
| 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64'
|
||||
| }
|
||||
|
|
||||
| spec.script_phases = [
|
||||
| {
|
||||
| :name => 'Build $specName',
|
||||
| :execution_position => :before_compile,
|
||||
| :shell_path => '/bin/sh',
|
||||
| :script => <<-SCRIPT
|
||||
| set -ev
|
||||
| REPO_ROOT="${'$'}PODS_TARGET_SRCROOT/../"
|
||||
| "$gradleCommand" -p "${'$'}REPO_ROOT" $syncTask \
|
||||
| -P${KotlinCocoapodsPlugin.TARGET_PROPERTY}=${'$'}KOTLIN_TARGET \
|
||||
| -P${KotlinCocoapodsPlugin.CONFIGURATION_PROPERTY}=${'$'}CONFIGURATION \
|
||||
| -P${KotlinCocoapodsPlugin.CFLAGS_PROPERTY}="${'$'}OTHER_CFLAGS" \
|
||||
| -P${KotlinCocoapodsPlugin.HEADER_PATHS_PROPERTY}="${'$'}HEADER_SEARCH_PATHS" \
|
||||
| -P${KotlinCocoapodsPlugin.FRAMEWORK_PATHS_PROPERTY}="${'$'}FRAMEWORK_SEARCH_PATHS"
|
||||
| SCRIPT
|
||||
| }
|
||||
| ]
|
||||
|end
|
||||
""".trimMargin()
|
||||
)
|
||||
)
|
||||
|
||||
logger.quiet(
|
||||
"""
|
||||
Generated a podspec file at: ${outputFile.absolutePath}.
|
||||
logger.quiet(
|
||||
"""
|
||||
Generated a podspec file at: ${absolutePath}.
|
||||
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()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a dummy framework in the target directory.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user