如何跨多个Gradle项目共享样板Kotlin配置?

时间:2016-08-24 08:10:03

标签: gradle kotlin gradle-plugin

Gradle项目中的typical Kotlin configuration非常模板化,我正在寻找一种方法将其抽象为外部构建脚本,以便可以重复使用。

我有一个工作解决方案(下面),但感觉有点像黑客,因为kotlin-gradle-plugin不能以这种方式开箱即用。

can't apply the plugin by id开始应用外部脚本中的任何非标准插件很麻烦,即

apply plugin: 'kotlin'将导致Plugin with id 'kotlin' not found.

简单(通常)的解决方法是通过插件的完全限定类名来应用,即

apply plugin: org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper

在这种情况下抛出一个很好的小异常,表明该插件可能不是这样调用的:

Failed to determine source cofiguration of kotlin plugin. 
Can not download core. Please verify that this or any parent project
contains 'kotlin-gradle-plugin' in buildscript's classpath configuration.

所以我设法破解了一个插件(只是real plugin的修改版本),迫使它从当前的buildcript中找到插件。

kotlin.gradle

buildscript {
    ext.kotlin_version = "1.0.3"
    repositories {
        jcenter()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
}

apply plugin: CustomKotlinPlugin
import org.jetbrains.kotlin.gradle.plugin.CleanUpBuildListener
import org.jetbrains.kotlin.gradle.plugin.KotlinBasePluginWrapper
import org.jetbrains.kotlin.gradle.plugin.KotlinPlugin
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider

/**
 * Wrapper around the Kotlin plugin wrapper (this code is largely a refactoring of KotlinBasePluginWrapper).
 * This is required because the default behaviour expects the kotlin plugin to be applied from the project,
 * not from an external buildscript.
 */
class CustomKotlinPlugin extends KotlinBasePluginWrapper {

    @Override
    void apply(Project project) {
        // use String literal as KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY constant isn't available
        System.setProperty("kotlin.environment.keepalive", "true")

        // just use the kotlin version defined in this script
        project.extensions.extraProperties?.set("kotlin.gradle.plugin.version", project.property('kotlin_version'))

        // get the plugin using the current buildscript
        def plugin = getPlugin(this.class.classLoader, project.buildscript)
        plugin.apply(project)

        def cleanUpBuildListener = new CleanUpBuildListener(this.class.classLoader, project)
        cleanUpBuildListener.buildStarted()
        project.gradle.addBuildListener(cleanUpBuildListener)
    }

    @Override
    Plugin<Project> getPlugin(ClassLoader pluginClassLoader, ScriptHandler scriptHandler){
        return new KotlinPlugin(scriptHandler, new KotlinTasksProvider(pluginClassLoader));
    }
}

然后可以将其应用于任何项目(即apply from: "kotlin.gradle"),并且您已经开始运行Kotlin开发。

它有效,我还没有任何问题,但我想知道是否有更好的方法?每次有新版本的Kotlin时,我都不太热衷于合并插件的更改。

2 个答案:

答案 0 :(得分:6)

查看OSError: [Errno 8] Exec format error。它似乎非常接近你想要在那里实现的目标。

答案 1 :(得分:0)

这里的问题是,有known gradle bug关于无法通过init脚本通过id应用插件。这就是为什么您需要使用完全限定的类名作为解决方法的原因。

例如我的初始化脚本中包含以下内容,并且可以正常工作:

apply plugin: org.jetbrains.kotlin.gradle.plugin.KotlinPlatformJvmPlugin

顺便说一句,我创建了一个gradle插件,用于准备在初始化脚本-custom-gradle-dist中定义的通用设置的自定义gradle发行版。它非常适合我的项目,例如库项目的 build.gradle 看起来像这样(这是一个完整的文件,包含所有存储库 apply插件依赖项< / em>初始化脚本中定义了etc设置):

dependencies {
    compile 'org.springframework.kafka:spring-kafka'
}