[Gradle, Cocoapods] refactor I/O, improve Up-To-Date
all synthetic tasks are per pod tasks receive parts of extension as inputs
This commit is contained in:
+345
-43
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.gradle
|
||||
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.DUMMY_FRAMEWORK_TASK_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_BUILD_DEPENDENCIES_TASK_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_BUILD_TASK_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_DOWNLOAD_TASK_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_GEN_TASK_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_IMPORT_TASK_NAME
|
||||
@@ -16,10 +16,8 @@ import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Compan
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.POD_SPEC_TASK_NAME
|
||||
import org.jetbrains.kotlin.gradle.util.modify
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.junit.Assume.assumeFalse
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
@@ -46,7 +44,7 @@ class CocoaPodsIT : BaseGradleIT() {
|
||||
private val podspecTaskName = ":$POD_SPEC_TASK_NAME"
|
||||
private val podDownloadTaskName = ":$POD_DOWNLOAD_TASK_NAME"
|
||||
private val podGenTaskName = ":$POD_GEN_TASK_NAME"
|
||||
private val podBuildTaskName = ":$POD_BUILD_DEPENDENCIES_TASK_NAME"
|
||||
private val podBuildTaskName = ":$POD_BUILD_TASK_NAME"
|
||||
private val podSetupBuildTaskName = ":$POD_SETUP_BUILD_TASK_NAME"
|
||||
private val podImportTaskName = ":$POD_IMPORT_TASK_NAME"
|
||||
private val podInstallTaskName = ":$POD_INSTALL_TASK_NAME"
|
||||
@@ -54,14 +52,30 @@ class CocoaPodsIT : BaseGradleIT() {
|
||||
|
||||
private val defaultPodRepo = "https://github.com/AFNetworking/AFNetworking"
|
||||
private val defaultPodName = "AFNetworking"
|
||||
private val downloadUrlPodName = "podspecWithFilesExample"
|
||||
private val downloadUrlRepoName = "https://github.com/alozhkin/podspecWithFilesExample/raw/master"
|
||||
private val defaultTarget = "IOS"
|
||||
private val defaultFamily = "IOS"
|
||||
private val defaultSDK = "iphonesimulator"
|
||||
private val defaultPodDownloadTaskName = podDownloadTaskName + defaultPodName
|
||||
private val defaultPodGenTaskName = podGenTaskName + defaultFamily
|
||||
private val defaultBuildTaskName = podBuildTaskName + defaultSDK.capitalize()
|
||||
private val defaultSetupBuildTaskName = podSetupBuildTaskName + defaultSDK.capitalize()
|
||||
private val defaultPodDownloadTaskName = podDownloadFullTaskName()
|
||||
private val defaultPodGenTaskName = podGenFullTaskName()
|
||||
private val defaultBuildTaskName = podBuildFullTaskName()
|
||||
private val defaultSetupBuildTaskName = podSetupBuildFullTaskName()
|
||||
private val defaultCinteropTaskName = cinteropTaskName + defaultPodName + defaultTarget
|
||||
private val downloadUrlTaskName = podDownloadTaskName + downloadUrlPodName.capitalize()
|
||||
|
||||
private fun podDownloadFullTaskName(podName: String = defaultPodName) = podDownloadTaskName + podName.capitalize()
|
||||
|
||||
private fun podGenFullTaskName(familyName: String = defaultFamily) = podGenTaskName + familyName.capitalize()
|
||||
|
||||
private fun podSetupBuildFullTaskName(podName: String = defaultPodName, sdkName: String = defaultSDK) =
|
||||
podSetupBuildTaskName + podName.capitalize() + sdkName.capitalize()
|
||||
|
||||
private fun podBuildFullTaskName(podName: String = defaultPodName, sdkName: String = defaultSDK) =
|
||||
podBuildTaskName + podName.capitalize() + sdkName.capitalize()
|
||||
|
||||
private fun cinteropFullTaskName(podName: String = defaultPodName, targetName: String = defaultTarget) =
|
||||
cinteropTaskName + podName.capitalize() + targetName.capitalize()
|
||||
|
||||
private lateinit var hooks: CustomHooks
|
||||
private lateinit var project: BaseGradleIT.Project
|
||||
@@ -118,10 +132,10 @@ class CocoaPodsIT : BaseGradleIT() {
|
||||
)
|
||||
|
||||
@Test
|
||||
fun testPodImportUseFrameworksSingle() = doTestImportSingle(ImportMode.FRAMEWORKS)
|
||||
fun testPodImportSingle() = doTestImportSingle()
|
||||
|
||||
@Test
|
||||
fun testPodImportUseModularHeadersSingle() = doTestImportSingle(ImportMode.MODULAR_HEADERS)
|
||||
fun testPodImportMultiple() = doTestImportMultiple()
|
||||
|
||||
@Test
|
||||
fun testPodspecMultiple() = doTestPodspec(
|
||||
@@ -173,20 +187,14 @@ class CocoaPodsIT : BaseGradleIT() {
|
||||
)
|
||||
|
||||
@Test
|
||||
fun testPodImportUseFrameworksMultiple() = doTestImportMultiple(ImportMode.FRAMEWORKS)
|
||||
|
||||
@Test
|
||||
fun testPodImportUseModularHeadersMultiple() = doTestImportMultiple(ImportMode.MODULAR_HEADERS)
|
||||
|
||||
@Test
|
||||
fun testSpecReposDownloads() {
|
||||
fun testSpecReposImport() {
|
||||
val podName = "example"
|
||||
val podRepo = "https://github.com/alozhkin/spec_repo_example"
|
||||
val podRepo = "https://github.com/alozhkin/spec_repo"
|
||||
with(project.gradleBuildScript()) {
|
||||
addPod(podName)
|
||||
addSpecRepo(podRepo)
|
||||
}
|
||||
project.testDownload(listOf(podRepo))
|
||||
project.testImportWithAsserts(listOf(podRepo))
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -275,19 +283,6 @@ class CocoaPodsIT : BaseGradleIT() {
|
||||
project.test(":kotlin-library:podDownload")
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
fun testSubspecWithModuleName() {
|
||||
with(project.gradleBuildScript()) {
|
||||
addPod("AFNetworking/Reachability", "moduleName = \"CustomName\"")
|
||||
addPod("AFNetworking/Security")
|
||||
}
|
||||
hooks.addHook {
|
||||
assertTasksExecuted(defaultCinteropTaskName, cinteropTaskName + "AFNetworking/Security" + defaultTarget)
|
||||
}
|
||||
project.testImportWithAsserts()
|
||||
}
|
||||
|
||||
|
||||
// up-to-date tests
|
||||
|
||||
@@ -355,6 +350,282 @@ class CocoaPodsIT : BaseGradleIT() {
|
||||
project.testSynthetic(defaultPodGenTaskName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUTDPodAdded() {
|
||||
with(project.gradleBuildScript()) {
|
||||
addPod(defaultPodName, produceGitBlock(defaultPodRepo))
|
||||
}
|
||||
project.testImport(listOf(defaultPodRepo))
|
||||
|
||||
val anotherPodName = "Alamofire"
|
||||
val anotherPodRepo = "https://github.com/Alamofire/Alamofire"
|
||||
with(project.gradleBuildScript()) {
|
||||
addPod(anotherPodName, produceGitBlock(anotherPodRepo))
|
||||
}
|
||||
hooks.rewriteHooks {
|
||||
assertTasksExecuted(
|
||||
podspecTaskName,
|
||||
podDownloadFullTaskName(anotherPodName),
|
||||
defaultPodGenTaskName,
|
||||
podSetupBuildFullTaskName(anotherPodName),
|
||||
podBuildFullTaskName(anotherPodName),
|
||||
cinteropFullTaskName(anotherPodName)
|
||||
)
|
||||
assertTasksUpToDate(
|
||||
defaultPodDownloadTaskName,
|
||||
defaultSetupBuildTaskName,
|
||||
defaultBuildTaskName,
|
||||
defaultCinteropTaskName
|
||||
)
|
||||
}
|
||||
project.testImport(listOf(defaultPodRepo, anotherPodRepo))
|
||||
|
||||
with(project.gradleBuildScript()) {
|
||||
removePod(anotherPodName)
|
||||
}
|
||||
hooks.rewriteHooks {
|
||||
assertTasksNotRegisteredByPrefix(
|
||||
listOf(
|
||||
podDownloadFullTaskName(anotherPodName),
|
||||
podBuildFullTaskName(anotherPodName),
|
||||
cinteropFullTaskName(anotherPodName)
|
||||
)
|
||||
)
|
||||
assertTasksUpToDate(
|
||||
defaultBuildTaskName,
|
||||
defaultPodDownloadTaskName,
|
||||
defaultSetupBuildTaskName,
|
||||
defaultCinteropTaskName
|
||||
)
|
||||
}
|
||||
project.testImport(listOf(defaultPodRepo))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testImportSubspecs() {
|
||||
with(project.gradleBuildScript()) {
|
||||
addPod("SDWebImage/Core")
|
||||
addPod("SDWebImage/MapKit")
|
||||
}
|
||||
project.testImport(listOf(defaultPodRepo))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUTDTargetAdded() {
|
||||
with(project.gradleBuildScript()) {
|
||||
addPod(defaultPodName, produceGitBlock(defaultPodRepo))
|
||||
appendToCocoapodsBlock("osx.deploymentTarget = \"13.5\"")
|
||||
}
|
||||
project.testImport(listOf(defaultPodRepo))
|
||||
|
||||
val anotherTarget = "MacosX64"
|
||||
val anotherSdk = "macosx"
|
||||
val anotherFamily = "OSX"
|
||||
with(project.gradleBuildScript()) {
|
||||
appendToKotlinBlock(anotherTarget.decapitalize() + "()")
|
||||
}
|
||||
hooks.rewriteHooks {
|
||||
assertTasksExecuted(
|
||||
podGenFullTaskName(anotherFamily),
|
||||
podSetupBuildFullTaskName(sdkName = anotherSdk),
|
||||
podBuildFullTaskName(sdkName = anotherSdk),
|
||||
cinteropFullTaskName(targetName = anotherTarget)
|
||||
)
|
||||
assertTasksUpToDate(
|
||||
podspecTaskName,
|
||||
defaultPodDownloadTaskName,
|
||||
defaultPodGenTaskName,
|
||||
defaultSetupBuildTaskName,
|
||||
defaultBuildTaskName,
|
||||
defaultCinteropTaskName
|
||||
)
|
||||
}
|
||||
project.testImport(listOf(defaultPodRepo))
|
||||
|
||||
with(project.gradleBuildScript()) {
|
||||
var text = readText()
|
||||
text = text.replace(anotherTarget.decapitalize() + "()", "")
|
||||
writeText(text)
|
||||
}
|
||||
hooks.rewriteHooks {
|
||||
assertTasksNotRegisteredByPrefix(
|
||||
listOf(
|
||||
podGenFullTaskName(anotherFamily),
|
||||
podSetupBuildFullTaskName(sdkName = anotherSdk),
|
||||
podBuildFullTaskName(sdkName = anotherSdk),
|
||||
cinteropFullTaskName(targetName = anotherTarget)
|
||||
)
|
||||
)
|
||||
assertTasksUpToDate(
|
||||
podspecTaskName,
|
||||
defaultPodDownloadTaskName,
|
||||
defaultPodGenTaskName,
|
||||
defaultSetupBuildTaskName,
|
||||
defaultBuildTaskName,
|
||||
defaultCinteropTaskName
|
||||
)
|
||||
}
|
||||
project.testImport(listOf(defaultPodRepo))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUTDPodspec() {
|
||||
project.testWithWrapper(podspecTaskName)
|
||||
hooks.addHook {
|
||||
assertTasksExecuted(podspecTaskName)
|
||||
}
|
||||
with(project.gradleBuildScript()) {
|
||||
appendToCocoapodsBlock("license = \"new license name\"")
|
||||
}
|
||||
project.testWithWrapper(podspecTaskName)
|
||||
with(project.gradleBuildScript()) {
|
||||
appendToCocoapodsBlock("license = \"new license name\"")
|
||||
}
|
||||
hooks.rewriteHooks {
|
||||
assertTasksUpToDate(podspecTaskName)
|
||||
}
|
||||
project.testWithWrapper(podspecTaskName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUTDPodspecDeploymentTarget() {
|
||||
project.testWithWrapper(podspecTaskName)
|
||||
hooks.addHook {
|
||||
assertTasksExecuted(podspecTaskName)
|
||||
}
|
||||
with(project.gradleBuildScript()) {
|
||||
appendToCocoapodsBlock("ios.deploymentTarget = \"12.5\"")
|
||||
}
|
||||
project.testWithWrapper(podspecTaskName)
|
||||
hooks.rewriteHooks {
|
||||
assertTasksUpToDate(podspecTaskName)
|
||||
}
|
||||
project.testWithWrapper(podspecTaskName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUTDDownload() {
|
||||
val gitRepo = downloadUrlRepoName.substringBeforeLast("/").substringBeforeLast("/")
|
||||
with(project.gradleBuildScript()) {
|
||||
addPod(downloadUrlPodName, produceGitBlock(repo = gitRepo))
|
||||
}
|
||||
hooks.addHook {
|
||||
assertTasksExecuted(downloadUrlTaskName)
|
||||
}
|
||||
project.testDownload(listOf(gitRepo))
|
||||
with(project.gradleBuildScript()) {
|
||||
changePod(downloadUrlPodName, produceGitBlock(repo = gitRepo, commitName = "f52f035018b4f3fe253d50ce85a7e0652a62ee9b"))
|
||||
}
|
||||
project.testDownload(listOf(gitRepo))
|
||||
hooks.rewriteHooks {
|
||||
assertTasksUpToDate(downloadUrlTaskName)
|
||||
}
|
||||
project.testDownload(listOf(gitRepo))
|
||||
val podArchivePath = "$downloadUrlRepoName/$downloadUrlPodName.tar.gz"
|
||||
with(project.gradleBuildScript()) {
|
||||
changePod(downloadUrlPodName, "source = url(\"$podArchivePath\")")
|
||||
}
|
||||
hooks.rewriteHooks {
|
||||
assertTasksExecuted(downloadUrlTaskName)
|
||||
}
|
||||
project.testDownload(listOf(podArchivePath))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUTDPodGen() {
|
||||
with(project.gradleBuildScript()) {
|
||||
addPod(defaultPodName)
|
||||
}
|
||||
val repos = listOf(
|
||||
"https://github.com/alozhkin/spec_repo_example",
|
||||
"https://github.com/alozhkin/spec_repo_example_2"
|
||||
)
|
||||
for (repo in repos) {
|
||||
assumeTrue(isRepoAvailable(repo))
|
||||
}
|
||||
hooks.addHook {
|
||||
assertTasksExecuted(defaultPodGenTaskName)
|
||||
}
|
||||
project.testSynthetic(defaultPodGenTaskName)
|
||||
with(project.gradleBuildScript()) {
|
||||
addSpecRepo("https://github.com/alozhkin/spec_repo_example")
|
||||
}
|
||||
project.testSynthetic(defaultPodGenTaskName)
|
||||
with(project.gradleBuildScript()) {
|
||||
addSpecRepo("https://github.com/alozhkin/spec_repo_example_2")
|
||||
}
|
||||
project.testSynthetic(defaultPodGenTaskName)
|
||||
hooks.rewriteHooks {
|
||||
assertTasksUpToDate(defaultPodGenTaskName)
|
||||
}
|
||||
project.testSynthetic(defaultPodGenTaskName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUTDBuild() {
|
||||
with(project.gradleBuildScript()) {
|
||||
addPod(defaultPodName, produceGitBlock())
|
||||
}
|
||||
hooks.addHook {
|
||||
assertTasksExecuted(defaultBuildTaskName)
|
||||
}
|
||||
project.testImport()
|
||||
|
||||
val repo = "$downloadUrlRepoName/$downloadUrlPodName.tar.gz"
|
||||
with(project.gradleBuildScript()) {
|
||||
addPod(downloadUrlPodName, "source = url(\"$repo\")")
|
||||
}
|
||||
val urlTaskName = podBuildFullTaskName(downloadUrlPodName)
|
||||
hooks.rewriteHooks {
|
||||
assertTasksUpToDate(defaultBuildTaskName)
|
||||
assertTasksExecuted(urlTaskName)
|
||||
}
|
||||
project.testImport()
|
||||
|
||||
val anotherTarget = "MacosX64"
|
||||
val anotherSdk = "macosx"
|
||||
with(project.gradleBuildScript()) {
|
||||
appendToCocoapodsBlock("osx.deploymentTarget = \"13.5\"")
|
||||
appendToKotlinBlock(anotherTarget.decapitalize() + "()")
|
||||
}
|
||||
val anotherSdkDefaultPodTaskName = podBuildFullTaskName(sdkName = anotherSdk)
|
||||
val anotherTargetUrlTaskName = podBuildFullTaskName(downloadUrlPodName, anotherSdk)
|
||||
hooks.rewriteHooks {
|
||||
assertTasksUpToDate(defaultBuildTaskName, urlTaskName)
|
||||
assertTasksExecuted(anotherSdkDefaultPodTaskName, anotherTargetUrlTaskName)
|
||||
}
|
||||
project.testImport()
|
||||
|
||||
hooks.rewriteHooks {
|
||||
assertTasksUpToDate(defaultBuildTaskName, urlTaskName, anotherSdkDefaultPodTaskName, anotherTargetUrlTaskName)
|
||||
}
|
||||
project.testImport()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPodBuildUTDClean() {
|
||||
with(project.gradleBuildScript()) {
|
||||
addPod(defaultPodName, produceGitBlock())
|
||||
}
|
||||
hooks.addHook {
|
||||
assertTasksExecuted(defaultBuildTaskName)
|
||||
}
|
||||
project.testImport()
|
||||
|
||||
hooks.rewriteHooks {}
|
||||
project.test(":clean")
|
||||
|
||||
hooks.addHook {
|
||||
assertTasksExecuted(defaultBuildTaskName)
|
||||
}
|
||||
project.testImport()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPodInstallWithoutPodFile() {
|
||||
project.testSynthetic(podInstallTaskName)
|
||||
}
|
||||
|
||||
|
||||
// groovy tests
|
||||
|
||||
@@ -395,6 +666,13 @@ class CocoaPodsIT : BaseGradleIT() {
|
||||
project.testImportWithAsserts(listOf(repo))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun supportPodsWithDependencies() {
|
||||
with(project.gradleBuildScript()) {
|
||||
addPod("AlamofireImage")
|
||||
}
|
||||
project.testImportWithAsserts()
|
||||
}
|
||||
|
||||
// paths
|
||||
|
||||
@@ -408,7 +686,7 @@ class CocoaPodsIT : BaseGradleIT() {
|
||||
|
||||
// test configuration phase
|
||||
|
||||
private class CustomHooks() {
|
||||
private class CustomHooks {
|
||||
private val hooks = mutableSetOf<CompiledProject.() -> Unit>()
|
||||
|
||||
fun addHook(hook: CompiledProject.() -> Unit) {
|
||||
@@ -427,21 +705,21 @@ class CocoaPodsIT : BaseGradleIT() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun doTestImportSingle(importMode: ImportMode) {
|
||||
private fun doTestImportSingle() {
|
||||
val project = getProjectByName(cocoapodsSingleKtPod)
|
||||
val subprojects = listOf("kotlin-library")
|
||||
doTestPodImport(project, subprojects, importMode)
|
||||
doTestPodImport(project, subprojects)
|
||||
}
|
||||
|
||||
private fun doTestImportMultiple(importMode: ImportMode) {
|
||||
private fun doTestImportMultiple() {
|
||||
val project = getProjectByName(cocoapodsMultipleKtPods)
|
||||
val subprojects = listOf("kotlin-library", "second-library")
|
||||
doTestPodImport(project, subprojects, importMode)
|
||||
doTestPodImport(project, subprojects)
|
||||
}
|
||||
|
||||
private fun doTestPodImport(project: BaseGradleIT.Project, subprojects: List<String>, importMode: ImportMode) {
|
||||
private fun doTestPodImport(project: BaseGradleIT.Project, subprojects: List<String>) {
|
||||
with(project) {
|
||||
preparePodfile("ios-app", importMode)
|
||||
preparePodfile("ios-app", ImportMode.FRAMEWORKS)
|
||||
}
|
||||
project.testImportWithAsserts()
|
||||
subprojects.forEach {
|
||||
@@ -468,10 +746,10 @@ class CocoaPodsIT : BaseGradleIT() {
|
||||
project.testDownload(listOf(repo))
|
||||
}
|
||||
|
||||
fun doTestPodDownloadUrl(
|
||||
private fun doTestPodDownloadUrl(
|
||||
fileExtension: String,
|
||||
podName: String = "podspecWithFilesExample",
|
||||
repoPath: String = "https://github.com/alozhkin/podspecWithFilesExample/raw/master",
|
||||
podName: String = downloadUrlPodName,
|
||||
repoPath: String = downloadUrlRepoName,
|
||||
archiveName: String = podName,
|
||||
flatten: Boolean = false
|
||||
) {
|
||||
@@ -554,6 +832,30 @@ class CocoaPodsIT : BaseGradleIT() {
|
||||
appendToCocoapodsBlock(podBlock)
|
||||
}
|
||||
|
||||
private fun File.removePod(podName: String) {
|
||||
val text = readText()
|
||||
val begin = text.indexOf("""pod("$podName")""")
|
||||
require(begin != -1) { "Pod doesn't exist in file" }
|
||||
var index = begin + """pod("$podName")""".length - 1
|
||||
if (text.indexOf("""pod("$podName") {""", startIndex = begin) != -1) {
|
||||
index += 2
|
||||
var bracket = 1
|
||||
while (bracket != 0) {
|
||||
if (text[++index] == '{') {
|
||||
bracket++
|
||||
} else if (text[index] == '}') {
|
||||
bracket--
|
||||
}
|
||||
}
|
||||
}
|
||||
writeText(text.removeRange(begin..index))
|
||||
}
|
||||
|
||||
private fun File.changePod(podName: String, newConfiguration: String? = null) {
|
||||
removePod(podName)
|
||||
addPod(podName, newConfiguration)
|
||||
}
|
||||
|
||||
private fun File.addSpecRepo(specRepo: String) = appendToCocoapodsBlock("url(\"$specRepo\")".wrap("specRepos"))
|
||||
|
||||
private fun File.appendToKotlinBlock(str: String) = appendLine(str.wrap("kotlin"))
|
||||
@@ -691,7 +993,7 @@ class CocoaPodsIT : BaseGradleIT() {
|
||||
assertTasksExecutedByPrefix(listOf("$taskPrefix:$POD_GEN_TASK_NAME"))
|
||||
}
|
||||
|
||||
with(listOf(POD_SETUP_BUILD_TASK_NAME, POD_BUILD_DEPENDENCIES_TASK_NAME).map { "$taskPrefix:$it" }) {
|
||||
with(listOf(POD_SETUP_BUILD_TASK_NAME, POD_BUILD_TASK_NAME).map { "$taskPrefix:$it" }) {
|
||||
if (buildScriptText.matches("pod\\(.*\\)".toRegex())) {
|
||||
assertTasksRegisteredByPrefix(this)
|
||||
assertTasksExecutedByPrefix(this)
|
||||
|
||||
+92
-60
@@ -11,6 +11,7 @@ import org.gradle.api.Project
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.Sync
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.jetbrains.kotlin.daemon.common.trimQuotes
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
@@ -29,6 +30,7 @@ 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.util.*
|
||||
|
||||
internal val Project.cocoapodsBuildDirs: CocoapodsBuildDirs
|
||||
get() = CocoapodsBuildDirs(this)
|
||||
@@ -68,17 +70,17 @@ private val Family.toPodGenTaskName: String
|
||||
name
|
||||
)
|
||||
|
||||
private val String.toSetupBuildTaskName: String
|
||||
get() = lowerCamelCaseName(
|
||||
KotlinCocoapodsPlugin.POD_SETUP_BUILD_TASK_NAME,
|
||||
this
|
||||
)
|
||||
private fun String.toSetupBuildTaskName(pod: CocoapodsDependency): String = lowerCamelCaseName(
|
||||
KotlinCocoapodsPlugin.POD_SETUP_BUILD_TASK_NAME,
|
||||
pod.schemeName,
|
||||
this
|
||||
)
|
||||
|
||||
private val String.toBuildDependenciesTaskName: String
|
||||
get() = lowerCamelCaseName(
|
||||
KotlinCocoapodsPlugin.POD_BUILD_DEPENDENCIES_TASK_NAME,
|
||||
this
|
||||
)
|
||||
private fun String.toBuildDependenciesTaskName(pod: CocoapodsDependency): String = lowerCamelCaseName(
|
||||
KotlinCocoapodsPlugin.POD_BUILD_TASK_NAME,
|
||||
pod.schemeName,
|
||||
this
|
||||
)
|
||||
|
||||
private val CocoapodsDependency.toPodDownloadTaskName: String
|
||||
get() = lowerCamelCaseName(
|
||||
@@ -225,7 +227,7 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
val defTask = project.registerTask<DefFileTask>(
|
||||
lowerCamelCaseName("generateDef", pod.moduleName).asValidTaskName()
|
||||
) {
|
||||
it.pod = pod
|
||||
it.pod = project.provider { pod }
|
||||
it.description = "Generates a def file for CocoaPods dependencies with module ${pod.moduleName}"
|
||||
// This task is an implementation detail so we don't add it in any group
|
||||
// to avoid showing it in the `tasks` output.
|
||||
@@ -248,8 +250,8 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
&& project.findProperty(CONFIGURATION_PROPERTY) == null
|
||||
) {
|
||||
val podBuildTaskProvider =
|
||||
project.tasks.named(target.toValidSDK.toBuildDependenciesTaskName, PodBuildTask::class.java)
|
||||
interopTask.inputs.file(podBuildTaskProvider.get().buildSettingsFileProvider)
|
||||
project.tasks.named(target.toValidSDK.toBuildDependenciesTaskName(pod), PodBuildTask::class.java)
|
||||
interopTask.inputs.file(podBuildTaskProvider.get().buildSettingsFile)
|
||||
interopTask.dependsOn(podBuildTaskProvider)
|
||||
}
|
||||
|
||||
@@ -275,9 +277,9 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
&& project.findProperty(CONFIGURATION_PROPERTY) == null
|
||||
) {
|
||||
val podBuildTaskProvider =
|
||||
project.tasks.named(target.toValidSDK.toBuildDependenciesTaskName, PodBuildTask::class.java)
|
||||
project.tasks.named(target.toValidSDK.toBuildDependenciesTaskName(pod), PodBuildTask::class.java)
|
||||
val buildSettings =
|
||||
podBuildTaskProvider.get().buildSettingsFileProvider.get()
|
||||
podBuildTaskProvider.get().buildSettingsFile.get()
|
||||
.inputStream()
|
||||
.use {
|
||||
PodBuildSettingsProperties.readSettingsFromStream(it)
|
||||
@@ -291,9 +293,14 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
buildSettings.headerPaths?.let { args ->
|
||||
interop.compilerOpts.addAll(args.splitQuotedArgs().map { "-I$it" })
|
||||
}
|
||||
buildSettings.frameworkPaths?.let { args ->
|
||||
interop.compilerOpts.addAll(args.splitQuotedArgs().map { "-F$it" })
|
||||
}
|
||||
|
||||
val frameworkPaths = buildSettings.frameworkPaths
|
||||
val configurationBuildDir = buildSettings.configurationBuildDir
|
||||
val frameworkPathsSelfIncluding = mutableListOf<String>()
|
||||
frameworkPathsSelfIncluding += configurationBuildDir.trimQuotes()
|
||||
frameworkPaths?.let { frameworkPathsSelfIncluding.addAll(it.splitQuotedArgs()) }
|
||||
|
||||
interop.compilerOpts.addAll(frameworkPathsSelfIncluding.map { "-F$it" })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,7 +313,7 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
cocoapodsExtension: CocoapodsExtension
|
||||
) {
|
||||
project.tasks.register(DUMMY_FRAMEWORK_TASK_NAME, DummyFrameworkTask::class.java) {
|
||||
it.cocoapodsExtension = cocoapodsExtension
|
||||
it.frameworkName = project.provider { cocoapodsExtension.frameworkName }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,7 +326,18 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
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.needPodspec = project.provider { cocoapodsExtension.needPodspec }
|
||||
it.pods.set(cocoapodsExtension.pods)
|
||||
it.version = project.provider { cocoapodsExtension.version }
|
||||
it.homepage.set(cocoapodsExtension.homepage)
|
||||
it.license.set(cocoapodsExtension.license)
|
||||
it.authors.set(cocoapodsExtension.authors)
|
||||
it.summary.set(cocoapodsExtension.summary)
|
||||
it.frameworkName = project.provider { cocoapodsExtension.frameworkName }
|
||||
it.ios = project.provider { cocoapodsExtension.ios }
|
||||
it.osx = project.provider { cocoapodsExtension.osx }
|
||||
it.tvos = project.provider { cocoapodsExtension.tvos }
|
||||
it.watchos = project.provider { cocoapodsExtension.watchos }
|
||||
it.dependsOn(dummyFrameworkTaskProvider)
|
||||
val generateWrapper = project.findProperty(GENERATE_WRAPPER_PROPERTY)?.toString()?.toBoolean() ?: false
|
||||
if (generateWrapper) {
|
||||
@@ -335,13 +353,13 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
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.podfile.set(cocoapodsExtension.podfile)
|
||||
it.onlyIf { isAvailableToProduceSynthetic }
|
||||
|
||||
//TODO avoid subproject task management here
|
||||
project.allprojects.map { it.tasks.named(POD_SPEC_TASK_NAME, PodspecTask::class.java) }
|
||||
.forEach { podspecTaskProvider ->
|
||||
podspecTaskProvider.get().takeIf { task -> task.cocoapodsExtension.needPodspec }
|
||||
podspecTaskProvider.get().takeIf { task -> task.needPodspec.get() }
|
||||
?.also { task -> it.inputs.file(task.outputFileProvider) }
|
||||
it.dependsOn(podspecTaskProvider)
|
||||
}
|
||||
@@ -361,12 +379,10 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
val podSource = pod.source
|
||||
val downloadPodTask = when (podSource) {
|
||||
is Git -> project.tasks.register(pod.toPodDownloadTaskName, PodDownloadGitTask::class.java) {
|
||||
it.cocoapodsExtension = cocoapodsExtension
|
||||
it.podName = project.provider { pod.name }
|
||||
it.podSource = project.provider { podSource as Git }
|
||||
}
|
||||
is Url -> project.tasks.register(pod.toPodDownloadTaskName, PodDownloadUrlTask::class.java) {
|
||||
it.cocoapodsExtension = cocoapodsExtension
|
||||
it.podName = project.provider { pod.name }
|
||||
it.podSource = project.provider { podSource as Url }
|
||||
}
|
||||
@@ -394,10 +410,10 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
|
||||
project.tasks.register(family.toPodGenTaskName, PodGenTask::class.java) {
|
||||
it.description = "Сreates a synthetic Xcode project to retrieve CocoaPods dependencies"
|
||||
it.podspecProvider = podspecTaskProvider.get().outputFileProvider
|
||||
it.podspec = podspecTaskProvider.map { task -> task.outputFileProvider.get() }
|
||||
it.specRepos = project.provider { cocoapodsExtension.specRepos }
|
||||
it.family = family
|
||||
it.cocoapodsExtension = cocoapodsExtension
|
||||
it.dependsOn(podspecTaskProvider)
|
||||
it.pods.set(cocoapodsExtension.pods)
|
||||
it.dependsOn(downloadPods)
|
||||
it.onlyIf { isAvailableToProduceSynthetic }
|
||||
}
|
||||
@@ -409,30 +425,36 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
kotlinExtension: KotlinMultiplatformExtension,
|
||||
cocoapodsExtension: CocoapodsExtension
|
||||
) {
|
||||
val sdks = mutableSetOf<String>()
|
||||
val schemeNames = mutableSetOf<String>()
|
||||
|
||||
kotlinExtension.supportedTargets().all { target ->
|
||||
cocoapodsExtension.pods.all { pod ->
|
||||
|
||||
val sdk = target.toValidSDK
|
||||
if (sdk in sdks) {
|
||||
if (schemeNames.contains(pod.schemeName)) {
|
||||
return@all
|
||||
}
|
||||
sdks += sdk
|
||||
schemeNames.add(pod.schemeName)
|
||||
|
||||
val podGenTaskProvider = project.tasks.named(target.konanTarget.family.toPodGenTaskName, PodGenTask::class.java)
|
||||
val sdks = mutableSetOf<String>()
|
||||
|
||||
project.tasks.register(sdk.toSetupBuildTaskName, PodSetupBuildTask::class.java) {
|
||||
it.group = TASK_GROUP
|
||||
it.description = "Collect environment variables from .xcworkspace file"
|
||||
it.cocoapodsExtension = cocoapodsExtension
|
||||
it.sdk = project.provider { sdk }
|
||||
kotlinExtension.supportedTargets().all loop@{ target ->
|
||||
|
||||
val podspecTaskProvider = project.tasks.named(POD_SPEC_TASK_NAME, PodspecTask::class.java)
|
||||
it.schemeName = podspecTaskProvider.map { it.specName }
|
||||
val sdk = target.toValidSDK
|
||||
if (sdk in sdks) {
|
||||
return@loop
|
||||
}
|
||||
sdks += sdk
|
||||
|
||||
it.podsXcodeProjDirProvider = podGenTaskProvider.get().podsXcodeProjDirProvider
|
||||
it.dependsOn(podGenTaskProvider)
|
||||
it.onlyIf { isAvailableToProduceSynthetic }
|
||||
val podGenTaskProvider = project.tasks.named(target.konanTarget.family.toPodGenTaskName, PodGenTask::class.java)
|
||||
project.tasks.register(sdk.toSetupBuildTaskName(pod), PodSetupBuildTask::class.java) {
|
||||
it.group = TASK_GROUP
|
||||
it.description = "Collect environment variables from .xcworkspace file"
|
||||
it.pod = project.provider { pod }
|
||||
it.sdk = project.provider { sdk }
|
||||
it.podsXcodeProjDir = podGenTaskProvider.map { podGen -> podGen.podsXcodeProjDir.get() }
|
||||
it.frameworkName = project.provider { cocoapodsExtension.frameworkName }
|
||||
it.dependsOn(podGenTaskProvider)
|
||||
it.onlyIf { isAvailableToProduceSynthetic }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -442,27 +464,38 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
kotlinExtension: KotlinMultiplatformExtension,
|
||||
cocoapodsExtension: CocoapodsExtension
|
||||
) {
|
||||
val sdks = mutableSetOf<String>()
|
||||
val schemeNames = mutableSetOf<String>()
|
||||
|
||||
kotlinExtension.supportedTargets().all { target ->
|
||||
cocoapodsExtension.pods.all { pod ->
|
||||
|
||||
val sdk = target.toValidSDK
|
||||
if (sdk in sdks) {
|
||||
if (schemeNames.contains(pod.schemeName)) {
|
||||
return@all
|
||||
}
|
||||
sdks += sdk
|
||||
schemeNames.add(pod.schemeName)
|
||||
|
||||
val podSetupBuildTaskProvider = project.tasks.named(sdk.toSetupBuildTaskName, PodSetupBuildTask::class.java)
|
||||
val sdks = mutableSetOf<String>()
|
||||
|
||||
project.tasks.register(sdk.toBuildDependenciesTaskName, PodBuildTask::class.java) {
|
||||
it.group = TASK_GROUP
|
||||
it.description = "Calls `xcodebuild` on xcworkspace for the pod scheme"
|
||||
it.sdk = project.provider { sdk }
|
||||
it.cocoapodsExtension = cocoapodsExtension
|
||||
it.podsXcodeProjDirProvider = podSetupBuildTaskProvider.get().podsXcodeProjDirProvider
|
||||
it.buildSettingsFileProvider = podSetupBuildTaskProvider.get().buildSettingsFileProvider
|
||||
it.dependsOn(podSetupBuildTaskProvider)
|
||||
it.onlyIf { isAvailableToProduceSynthetic }
|
||||
kotlinExtension.supportedTargets().all loop@{ target ->
|
||||
|
||||
val sdk = target.toValidSDK
|
||||
|
||||
if (sdk in sdks) {
|
||||
return@loop
|
||||
}
|
||||
sdks += sdk
|
||||
|
||||
val podSetupBuildTaskProvider =
|
||||
project.tasks.named(sdk.toSetupBuildTaskName(pod), PodSetupBuildTask::class.java)
|
||||
|
||||
project.tasks.register(sdk.toBuildDependenciesTaskName(pod), PodBuildTask::class.java) {
|
||||
it.group = TASK_GROUP
|
||||
it.description = "Calls `xcodebuild` on xcworkspace for the pod scheme"
|
||||
it.sdk = project.provider { sdk }
|
||||
it.pod = project.provider { pod }
|
||||
it.podsXcodeProjDir = podSetupBuildTaskProvider.map { task -> task.podsXcodeProjDir.get() }
|
||||
it.buildSettingsFile = podSetupBuildTaskProvider.map { task -> task.buildSettingsFile.get() }
|
||||
it.onlyIf { isAvailableToProduceSynthetic }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -471,7 +504,6 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
project: Project,
|
||||
kotlinExtension: KotlinMultiplatformExtension
|
||||
) {
|
||||
|
||||
val podInstallTaskProvider = project.tasks.named(POD_INSTALL_TASK_NAME, PodInstallTask::class.java)
|
||||
project.tasks.register(POD_IMPORT_TASK_NAME) {
|
||||
it.group = TASK_GROUP
|
||||
@@ -531,7 +563,7 @@ open class KotlinCocoapodsPlugin : Plugin<Project> {
|
||||
const val POD_DOWNLOAD_TASK_NAME = "podDownload"
|
||||
const val POD_GEN_TASK_NAME = "podGen"
|
||||
const val POD_SETUP_BUILD_TASK_NAME = "podSetupBuild"
|
||||
const val POD_BUILD_DEPENDENCIES_TASK_NAME = "podBuildDependencies"
|
||||
const val POD_BUILD_TASK_NAME = "podBuild"
|
||||
const val POD_IMPORT_TASK_NAME = "podImport"
|
||||
|
||||
// We don't move these properties in PropertiesProvider because
|
||||
|
||||
+140
-102
@@ -7,15 +7,14 @@ package org.jetbrains.kotlin.gradle.targets.native.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.artifacts.repositories.ArtifactRepository
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.file.FileTree
|
||||
import org.gradle.api.file.RelativePath
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension.CocoapodsDependency.PodLocation.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.asValidFrameworkName
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.cocoapodsBuildDirs
|
||||
import org.jetbrains.kotlin.konan.target.Family
|
||||
import java.io.File
|
||||
@@ -34,6 +33,9 @@ private val Family.platformLiteral: String
|
||||
else -> throw IllegalArgumentException("Bad family ${this.name}")
|
||||
}
|
||||
|
||||
val CocoapodsDependency.schemeName: String
|
||||
get() = name.split("/")[0]
|
||||
|
||||
/**
|
||||
* The task takes the path to the Podfile and calls `pod install`
|
||||
* to obtain sources or artifacts for the declared dependencies.
|
||||
@@ -41,24 +43,24 @@ private val Family.platformLiteral: String
|
||||
*/
|
||||
open class PodInstallTask : DefaultTask() {
|
||||
init {
|
||||
onlyIf { cocoapodsExtension?.podfile != null }
|
||||
onlyIf { podfile.isPresent }
|
||||
}
|
||||
|
||||
@get:Optional
|
||||
@get:Nested
|
||||
internal var cocoapodsExtension: CocoapodsExtension? = null
|
||||
@get:Input
|
||||
internal val podfile = project.objects.property(File::class.java)
|
||||
|
||||
@get:Optional
|
||||
@get:OutputDirectory
|
||||
internal val podsXcodeProjDirProvider: Provider<File>?
|
||||
get() = cocoapodsExtension?.podfile?.let {
|
||||
get() = podfile.orNull?.let {
|
||||
project.provider { it.parentFile.resolve("Pods").resolve("Pods.xcodeproj") }
|
||||
}
|
||||
|
||||
|
||||
@TaskAction
|
||||
fun doPodInstall() {
|
||||
cocoapodsExtension?.podfile?.parentFile?.also { podfileDir ->
|
||||
podfile.orNull?.parentFile?.also { podfileDir ->
|
||||
val podInstallProcess = ProcessBuilder("pod", "install").apply {
|
||||
directory(podfileDir)
|
||||
}.start()
|
||||
@@ -81,25 +83,12 @@ open class PodInstallTask : DefaultTask() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
abstract class CocoapodsWithSyntheticTask : DefaultTask() {
|
||||
init {
|
||||
onlyIf {
|
||||
cocoapodsExtension.pods.isNotEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
@get:Nested
|
||||
internal lateinit var cocoapodsExtension: CocoapodsExtension
|
||||
}
|
||||
|
||||
abstract class PodDownloadTask : CocoapodsWithSyntheticTask() {
|
||||
abstract class DownloadCocoapodsTask : DefaultTask() {
|
||||
@get:Input
|
||||
internal lateinit var podName: Provider<String>
|
||||
}
|
||||
|
||||
|
||||
open class PodDownloadUrlTask : PodDownloadTask() {
|
||||
open class PodDownloadUrlTask : DownloadCocoapodsTask() {
|
||||
|
||||
@get:Nested
|
||||
internal lateinit var podSource: Provider<Url>
|
||||
@@ -181,8 +170,7 @@ open class PodDownloadUrlTask : PodDownloadTask() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
open class PodDownloadGitTask : PodDownloadTask() {
|
||||
open class PodDownloadGitTask : DownloadCocoapodsTask() {
|
||||
|
||||
@get:Nested
|
||||
internal lateinit var podSource: Provider<Git>
|
||||
@@ -328,19 +316,31 @@ private fun runCommand(
|
||||
* The task takes the path to the .podspec file and calls `pod gen`
|
||||
* to create synthetic xcode project and workspace.
|
||||
*/
|
||||
open class PodGenTask : CocoapodsWithSyntheticTask() {
|
||||
open class PodGenTask : DefaultTask() {
|
||||
|
||||
init {
|
||||
onlyIf {
|
||||
pods.get().isNotEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
@get:InputFile
|
||||
internal lateinit var podspecProvider: Provider<File>
|
||||
internal lateinit var podspec: Provider<File>
|
||||
|
||||
@get:Internal
|
||||
lateinit var family: Family
|
||||
|
||||
@get:Nested
|
||||
internal lateinit var specRepos: Provider<SpecRepos>
|
||||
|
||||
@get:Nested
|
||||
val pods = project.objects.listProperty(CocoapodsDependency::class.java)
|
||||
|
||||
@get:OutputDirectory
|
||||
internal val podsXcodeProjDirProvider: Provider<File>
|
||||
internal val podsXcodeProjDir: Provider<File>
|
||||
get() = project.provider {
|
||||
project.cocoapodsBuildDirs.synthetic(family)
|
||||
.resolve(podspecProvider.get().nameWithoutExtension)
|
||||
.resolve(podspec.get().nameWithoutExtension)
|
||||
.resolve("Pods")
|
||||
.resolve("Pods.xcodeproj")
|
||||
}
|
||||
@@ -348,18 +348,18 @@ open class PodGenTask : CocoapodsWithSyntheticTask() {
|
||||
@TaskAction
|
||||
fun generate() {
|
||||
val syntheticDir = project.cocoapodsBuildDirs.synthetic(family).apply { mkdirs() }
|
||||
val localPodspecPaths = cocoapodsExtension.pods.mapNotNull { it.source?.getLocalPath(project, it.name) }
|
||||
val localPodspecPaths = pods.get().mapNotNull { it.source?.getLocalPath(project, it.name) }
|
||||
|
||||
val sources = cocoapodsExtension.specRepos.getAll().toMutableList()
|
||||
sources += URI("https://cdn.cocoapods.org")
|
||||
val specRepos = specRepos.get().getAll().toMutableList()
|
||||
specRepos += URI("https://cdn.cocoapods.org")
|
||||
|
||||
val podGenProcessArgs = listOfNotNull(
|
||||
"pod", "gen",
|
||||
"--platforms=${family.platformLiteral}",
|
||||
"--gen-directory=${syntheticDir.absolutePath}",
|
||||
localPodspecPaths.takeIf { it.isNotEmpty() }?.joinToString(separator = ",")?.let { "--local-sources=$it" },
|
||||
sources.takeIf { it.isNotEmpty() }?.joinToString(separator = ",")?.let { "--sources=$it" },
|
||||
podspecProvider.get().absolutePath
|
||||
specRepos.takeIf { it.isNotEmpty() }?.joinToString(separator = ",")?.let { "--sources=$it" },
|
||||
podspec.get().absolutePath
|
||||
)
|
||||
|
||||
val podGenProcess = ProcessBuilder(podGenProcessArgs).apply {
|
||||
@@ -388,7 +388,7 @@ open class PodGenTask : CocoapodsWithSyntheticTask() {
|
||||
).joinToString("\n")
|
||||
}
|
||||
|
||||
val podsXcprojFile = podsXcodeProjDirProvider.get()
|
||||
val podsXcprojFile = podsXcodeProjDir.get()
|
||||
check(podsXcprojFile.exists() && podsXcprojFile.isDirectory) {
|
||||
"The directory '${podsXcprojFile.path}' was not created as a result of the `pod gen` call."
|
||||
}
|
||||
@@ -396,35 +396,35 @@ open class PodGenTask : CocoapodsWithSyntheticTask() {
|
||||
}
|
||||
|
||||
|
||||
open class PodSetupBuildTask : CocoapodsWithSyntheticTask() {
|
||||
open class PodSetupBuildTask : DefaultTask() {
|
||||
|
||||
@get:InputDirectory
|
||||
internal lateinit var podsXcodeProjDirProvider: Provider<File>
|
||||
@get:Input
|
||||
lateinit var frameworkName: Provider<String>
|
||||
|
||||
@get:Input
|
||||
internal lateinit var sdk: Provider<String>
|
||||
|
||||
@Input
|
||||
lateinit var schemeName: Provider<String>
|
||||
@get:Nested
|
||||
lateinit var pod: Provider<CocoapodsDependency>
|
||||
|
||||
@get:OutputFile
|
||||
internal val buildSettingsFileProvider: Provider<File> = project.provider {
|
||||
internal val buildSettingsFile: Provider<File> = project.provider {
|
||||
project.cocoapodsBuildDirs
|
||||
.buildSettings
|
||||
.resolve(sdk.get().toBuildSettingsFileName)
|
||||
.resolve(getBuildSettingFileName(pod.get(), sdk.get()))
|
||||
}
|
||||
|
||||
private val String.toBuildSettingsFileName: String
|
||||
get() = "build-settings-$this.properties"
|
||||
@get:Internal
|
||||
internal lateinit var podsXcodeProjDir: Provider<File>
|
||||
|
||||
@TaskAction
|
||||
fun setupBuild() {
|
||||
val podsXcodeProjDir = podsXcodeProjDirProvider.get()
|
||||
val podsXcodeProjDir = podsXcodeProjDir.get()
|
||||
|
||||
val buildSettingsReceivingCommand = listOf(
|
||||
"xcodebuild", "-showBuildSettings",
|
||||
"-project", podsXcodeProjDir.name,
|
||||
"-scheme", schemeName.get(),
|
||||
"-scheme", pod.get().schemeName,
|
||||
"-sdk", sdk.get()
|
||||
)
|
||||
|
||||
@@ -442,113 +442,151 @@ open class PodSetupBuildTask : CocoapodsWithSyntheticTask() {
|
||||
}
|
||||
|
||||
val stdOut = buildSettingsProcess.inputStream
|
||||
|
||||
val buildSettingsProperties = PodBuildSettingsProperties.readSettingsFromStream(stdOut)
|
||||
buildSettingsFileProvider.get().let { buildSettingsProperties.writeSettings(it) }
|
||||
buildSettingsFile.get().let {
|
||||
buildSettingsProperties.writeSettings(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBuildSettingFileName(pod: CocoapodsDependency, sdk: String): String =
|
||||
"build-settings-$sdk-${pod.schemeName}.properties"
|
||||
|
||||
/**
|
||||
* The task compiles external cocoa pods sources.
|
||||
*/
|
||||
open class PodBuildTask : CocoapodsWithSyntheticTask() {
|
||||
|
||||
@get:InputDirectory
|
||||
internal lateinit var podsXcodeProjDirProvider: Provider<File>
|
||||
open class PodBuildTask : DefaultTask() {
|
||||
|
||||
@get:InputFile
|
||||
internal lateinit var buildSettingsFileProvider: Provider<File>
|
||||
internal lateinit var buildSettingsFile: Provider<File>
|
||||
|
||||
@get:Nested
|
||||
internal lateinit var pod: Provider<CocoapodsDependency>
|
||||
|
||||
@get:InputFiles
|
||||
internal val srcDir: FileTree
|
||||
get() = project.fileTree(
|
||||
buildSettingsFile.map {
|
||||
PodBuildSettingsProperties.readSettingsFromStream(
|
||||
FileInputStream(it)
|
||||
).podsTargetSrcRoot
|
||||
}
|
||||
)
|
||||
|
||||
@get:Internal
|
||||
internal var buildDir: Provider<File> = project.provider {
|
||||
project.file(
|
||||
PodBuildSettingsProperties.readSettingsFromStream(
|
||||
FileInputStream(buildSettingsFile.get())
|
||||
).buildDir
|
||||
)
|
||||
}
|
||||
|
||||
@get:Input
|
||||
internal lateinit var sdk: Provider<String>
|
||||
|
||||
@get:Optional
|
||||
@get:OutputDirectory
|
||||
internal var buildDirProvider: Provider<File>? = null
|
||||
@get:OutputFiles
|
||||
internal val buildResult: Provider<FileCollection>? = project.provider {
|
||||
project.fileTree(buildDir.get()) {
|
||||
it.include("**/${pod.get().schemeName}.*/")
|
||||
it.include("**/${pod.get().schemeName}/")
|
||||
}
|
||||
}
|
||||
|
||||
private val CocoapodsExtension.CocoapodsDependency.schemeName: String
|
||||
get() = name.split("/")[0]
|
||||
@get:Internal
|
||||
internal lateinit var podsXcodeProjDir: Provider<File>
|
||||
|
||||
@TaskAction
|
||||
fun buildDependencies() {
|
||||
val podBuildSettings = PodBuildSettingsProperties.readSettingsFromStream(
|
||||
FileInputStream(buildSettingsFileProvider.get())
|
||||
FileInputStream(buildSettingsFile.get())
|
||||
)
|
||||
|
||||
val podsXcodeProjDir = podsXcodeProjDirProvider.get()
|
||||
val podsXcodeProjDir = podsXcodeProjDir.get()
|
||||
|
||||
cocoapodsExtension.pods.all {
|
||||
val podXcodeBuildCommand = listOf(
|
||||
"xcodebuild",
|
||||
"-project", podsXcodeProjDir.name,
|
||||
"-scheme", pod.get().schemeName,
|
||||
"-sdk", sdk.get(),
|
||||
"-configuration", podBuildSettings.configuration
|
||||
)
|
||||
|
||||
val podXcodeBuildCommand = listOf(
|
||||
"xcodebuild",
|
||||
"-project", podsXcodeProjDir.name,
|
||||
"-scheme", it.schemeName,
|
||||
"-sdk", sdk.get(),
|
||||
"-configuration", podBuildSettings.configuration
|
||||
)
|
||||
val podBuildProcess = ProcessBuilder(podXcodeBuildCommand)
|
||||
.apply {
|
||||
directory(podsXcodeProjDir.parentFile)
|
||||
inheritIO()
|
||||
}.start()
|
||||
|
||||
val podBuildProcess = ProcessBuilder(podXcodeBuildCommand)
|
||||
.apply {
|
||||
directory(podsXcodeProjDir.parentFile)
|
||||
inheritIO()
|
||||
}.start()
|
||||
|
||||
val podBuildRetCode = podBuildProcess.waitFor()
|
||||
check(podBuildRetCode == 0) {
|
||||
listOf(
|
||||
"Executing of '${podXcodeBuildCommand.joinToString(" ")}' failed with code $podBuildRetCode and message:",
|
||||
podBuildProcess.errorStream.use { it.reader().readText() }
|
||||
).joinToString("\n")
|
||||
}
|
||||
val podBuildRetCode = podBuildProcess.waitFor()
|
||||
check(podBuildRetCode == 0) {
|
||||
listOf(
|
||||
"Executing of '${podXcodeBuildCommand.joinToString(" ")}' failed with code $podBuildRetCode and message:",
|
||||
podBuildProcess.errorStream.use { it.reader().readText() }
|
||||
).joinToString("\n")
|
||||
}
|
||||
buildDirProvider = project.provider { project.file(podBuildSettings.buildDir) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal data class PodBuildSettingsProperties(
|
||||
internal val buildDir: String,
|
||||
internal val configuration: String,
|
||||
internal val configurationBuildDir: String,
|
||||
internal val podsTargetSrcRoot: String,
|
||||
internal val cflags: String? = null,
|
||||
internal val headerPaths: String? = null,
|
||||
internal val frameworkPaths: String? = null
|
||||
) {
|
||||
|
||||
fun writeSettings(buildSettingsFile: File) {
|
||||
fun writeSettings(
|
||||
buildSettingsFile: File
|
||||
) {
|
||||
buildSettingsFile.parentFile.mkdirs()
|
||||
buildSettingsFile.delete()
|
||||
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)
|
||||
}
|
||||
with(buildSettingsFile) {
|
||||
appendText("$BUILD_DIR=$buildDir\n")
|
||||
appendText("$CONFIGURATION=$configuration\n")
|
||||
appendText("$CONFIGURATION_BUILD_DIR=$configurationBuildDir\n")
|
||||
appendText("$PODS_TARGET_SRCROOT=$podsTargetSrcRoot\n")
|
||||
cflags?.let { appendText("$OTHER_CFLAGS=$it\n") }
|
||||
headerPaths?.let { appendText("$HEADER_SEARCH_PATHS=$it\n") }
|
||||
frameworkPaths?.let { appendText("$FRAMEWORK_SEARCH_PATHS=$it") }
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
const val BUILD_DIR = "BUILD_DIR"
|
||||
const val CONFIGURATION = "CONFIGURATION"
|
||||
const val CONFIGURATION_BUILD_DIR = "CONFIGURATION_BUILD_DIR"
|
||||
const val PODS_TARGET_SRCROOT = "PODS_TARGET_SRCROOT"
|
||||
const val OTHER_CFLAGS = "OTHER_CFLAGS"
|
||||
const val HEADER_SEARCH_PATHS = "HEADER_SEARCH_PATHS"
|
||||
const val FRAMEWORK_SEARCH_PATHS = "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)
|
||||
readProperty(BUILD_DIR),
|
||||
readProperty(CONFIGURATION),
|
||||
readProperty(CONFIGURATION_BUILD_DIR),
|
||||
readProperty(PODS_TARGET_SRCROOT),
|
||||
readNullableProperty(OTHER_CFLAGS),
|
||||
readNullableProperty(HEADER_SEARCH_PATHS),
|
||||
readNullableProperty(FRAMEWORK_SEARCH_PATHS)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Properties.readProperty(propertyName: String) =
|
||||
readNullableProperty(propertyName) ?: error("$propertyName property is absent")
|
||||
|
||||
private fun Properties.readNullableProperty(propertyName: String) =
|
||||
getProperty(propertyName)
|
||||
}
|
||||
}
|
||||
|
||||
+60
-24
@@ -15,6 +15,7 @@ import org.gradle.api.tasks.wrapper.Wrapper
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.COCOAPODS_EXTENSION_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.KotlinCocoapodsPlugin.Companion.GENERATE_WRAPPER_PROPERTY
|
||||
@@ -38,18 +39,55 @@ open class PodspecTask : DefaultTask() {
|
||||
internal val outputFileProvider: Provider<File>
|
||||
get() = project.provider { project.file("$specName.podspec") }
|
||||
|
||||
@get:Input
|
||||
internal lateinit var needPodspec: Provider<Boolean>
|
||||
|
||||
@get:Nested
|
||||
internal lateinit var cocoapodsExtension: CocoapodsExtension
|
||||
val pods = project.objects.listProperty(CocoapodsDependency::class.java)
|
||||
|
||||
@get:Input
|
||||
internal lateinit var version: Provider<String>
|
||||
|
||||
@get:Input
|
||||
@get:Optional
|
||||
internal val homepage = project.objects.property(String::class.java)
|
||||
|
||||
@get:Input
|
||||
@get:Optional
|
||||
internal val license = project.objects.property(String::class.java)
|
||||
|
||||
@get:Input
|
||||
@get:Optional
|
||||
internal val authors = project.objects.property(String::class.java)
|
||||
|
||||
@get:Input
|
||||
@get:Optional
|
||||
internal val summary = project.objects.property(String::class.java)
|
||||
|
||||
@get:Input
|
||||
internal lateinit var frameworkName: Provider<String>
|
||||
|
||||
@get:Nested
|
||||
internal lateinit var ios: Provider<PodspecPlatformSettings>
|
||||
|
||||
@get:Nested
|
||||
internal lateinit var osx: Provider<PodspecPlatformSettings>
|
||||
|
||||
@get:Nested
|
||||
internal lateinit var tvos: Provider<PodspecPlatformSettings>
|
||||
|
||||
@get:Nested
|
||||
internal lateinit var watchos: Provider<PodspecPlatformSettings>
|
||||
|
||||
init {
|
||||
onlyIf { cocoapodsExtension.needPodspec }
|
||||
onlyIf { needPodspec.get() }
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun generate() {
|
||||
|
||||
val frameworkDir = project.cocoapodsBuildDirs.framework.relativeTo(outputFileProvider.get().parentFile).path
|
||||
val dependencies = cocoapodsExtension.pods.map { pod ->
|
||||
val dependencies = pods.get().map { pod ->
|
||||
val versionSuffix = if (pod.version != null) ", '${pod.version}'" else ""
|
||||
"| spec.dependency '${pod.name}'$versionSuffix"
|
||||
}.joinToString(separator = "\n")
|
||||
@@ -69,10 +107,8 @@ open class PodspecTask : DefaultTask() {
|
||||
val syncTask = "${project.path}:$SYNC_TASK_NAME"
|
||||
|
||||
val deploymentTargets = run {
|
||||
with(cocoapodsExtension) {
|
||||
listOf(ios, osx, tvos, watchos).filter { it.deploymentTarget != null }.joinToString("\n") {
|
||||
"| spec.${it.name}.deployment_target = '${it.deploymentTarget}'"
|
||||
}
|
||||
listOf(ios, osx, tvos, watchos).map { it.get() }.filter { it.deploymentTarget != null }.joinToString("\n") {
|
||||
"| spec.${it.name}.deployment_target = '${it.deploymentTarget}'"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,15 +117,15 @@ open class PodspecTask : DefaultTask() {
|
||||
"""
|
||||
|Pod::Spec.new do |spec|
|
||||
| spec.name = '$specName'
|
||||
| spec.version = '${cocoapodsExtension.version}'
|
||||
| spec.homepage = '${cocoapodsExtension.homepage.orEmpty()}'
|
||||
| spec.version = '${version.get()}'
|
||||
| spec.homepage = '${homepage.getOrEmpty()}'
|
||||
| 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.authors = '${authors.getOrEmpty()}'
|
||||
| spec.license = '${license.getOrEmpty()}'
|
||||
| spec.summary = '${summary.getOrEmpty()}'
|
||||
|
|
||||
| spec.static_framework = true
|
||||
| spec.vendored_frameworks = "$frameworkDir/${cocoapodsExtension.frameworkName}.framework"
|
||||
| spec.vendored_frameworks = "$frameworkDir/${frameworkName.get()}.framework"
|
||||
| spec.libraries = "c++"
|
||||
| spec.module_name = "#{spec.name}_umbrella"
|
||||
|
|
||||
@@ -143,6 +179,8 @@ open class PodspecTask : DefaultTask() {
|
||||
}
|
||||
}
|
||||
|
||||
fun Provider<String>.getOrEmpty() = getOrElse("")
|
||||
|
||||
companion object {
|
||||
private val KotlinMultiplatformExtension?.cocoapodsExtensionOrNull: CocoapodsExtension?
|
||||
get() = (this as? ExtensionAware)?.extensions?.findByName(COCOAPODS_EXTENSION_NAME) as? CocoapodsExtension
|
||||
@@ -167,17 +205,15 @@ open class PodspecTask : DefaultTask() {
|
||||
* and then replace it with the real one during a real build process.
|
||||
*/
|
||||
open class DummyFrameworkTask : DefaultTask() {
|
||||
|
||||
@OutputDirectory
|
||||
val destinationDir = project.cocoapodsBuildDirs.framework
|
||||
|
||||
@Input
|
||||
val frameworkNameProvider: Provider<String> = project.provider { cocoapodsExtension.frameworkName }
|
||||
|
||||
@get:Nested
|
||||
internal lateinit var cocoapodsExtension: CocoapodsExtension
|
||||
lateinit var frameworkName: Provider<String>
|
||||
|
||||
private val frameworkDir: File
|
||||
get() = destinationDir.resolve("${frameworkNameProvider.get()}.framework")
|
||||
get() = destinationDir.resolve("${frameworkName.get()}.framework")
|
||||
|
||||
private fun copyResource(from: String, to: File) {
|
||||
to.parentFile.mkdirs()
|
||||
@@ -225,11 +261,11 @@ open class DummyFrameworkTask : DefaultTask() {
|
||||
|
||||
// Copy files for the dummy framework.
|
||||
copyFrameworkFile("Info.plist")
|
||||
copyFrameworkFile("dummy", frameworkNameProvider.get())
|
||||
copyFrameworkFile("dummy", frameworkName.get())
|
||||
copyFrameworkFile("Headers/placeholder.h")
|
||||
copyFrameworkTextFile("Modules/module.modulemap") {
|
||||
if (it == "framework module dummy {") {
|
||||
it.replace("dummy", frameworkNameProvider.get())
|
||||
it.replace("dummy", frameworkName.get())
|
||||
} else {
|
||||
it
|
||||
}
|
||||
@@ -242,12 +278,12 @@ open class DummyFrameworkTask : DefaultTask() {
|
||||
*/
|
||||
open class DefFileTask : DefaultTask() {
|
||||
|
||||
@Nested
|
||||
lateinit var pod: CocoapodsExtension.CocoapodsDependency
|
||||
@get:Nested
|
||||
lateinit var pod: Provider<CocoapodsDependency>
|
||||
|
||||
@get:OutputFile
|
||||
val outputFile: File
|
||||
get() = project.cocoapodsBuildDirs.defs.resolve("${pod.moduleName}.def")
|
||||
get() = project.cocoapodsBuildDirs.defs.resolve("${pod.get().moduleName}.def")
|
||||
|
||||
@TaskAction
|
||||
fun generate() {
|
||||
@@ -255,7 +291,7 @@ open class DefFileTask : DefaultTask() {
|
||||
outputFile.writeText(
|
||||
"""
|
||||
language = Objective-C
|
||||
modules = ${pod.moduleName}
|
||||
modules = ${pod.get().moduleName}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user