专栏首页BennyhuoGradle Kotlin DSL 的 accessors 生成问题

Gradle Kotlin DSL 的 accessors 生成问题

概要

如果你想用 gradle kotlin DSL,那么请注意,accessors 的支持从 0.8.0 开始(gradle 3.5),后续也做了一些完善和更新,目前已经默认开启了这一项功能。使用时由于 accessors 是动态生成的,因此要注意使用 plugins{...} 可以直接触发 accessors 的动态生成,其他情况下就比较麻烦了。

正文

昨天也是手欠,非要用 Gradle Kotlin DSL 构建工程,还看到现在连 settings.gradle 也支持用 kts 了,于是乎:

不过这个需要 Gradle 的版本在 4.4 以上,gradle-wrapper.properties 的版本修改为:

...
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

看上去也没啥毛病啊,我的 build.gradle.kts 是这个样子:

buildscript {
    var kotlin_version: String by extra
    kotlin_version = "1.2.10"

    repositories {
        mavenCentral()
    }

    dependencies {
        classpath(kotlin("gradle-plugin", kotlin_version))
    }
}

apply {
    plugin("java")
    plugin("kotlin")
}

val kotlin_version: String by extra

repositories {
    mavenCentral()
}

dependencies {
    compile(kotlin("stdlib"))
}

然而一运行,出事儿了,compile 不识别。。

e: .../kotlinspecificsJvm/app/build.gradle.kts:42:5: Unresolved reference: compile

额,这就尴尬了,哪儿说理去。。由于 Kotlin 是静态语言,能够在这个地方写出来 compile 那么一定是定义了这个方法,就像:

dependencies {
        classpath(kotlin("gradle-plugin", kotlin_version))
    }

这里的 classpath 就是一个方法:

class ScriptHandlerScope(scriptHandler: ScriptHandler) : ScriptHandler by scriptHandler {
    ...
    fun DependencyHandler.classpath(dependencyNotation: Any): Dependency =
        add(CLASSPATH_CONFIGURATION, dependencyNotation)
}

那么 compile 的定义哪儿去了?其实,compile 和 classpath 不一样,前者是构建插件的 configuration,而 classpath 则是 gradle 本身的一个方法。

那么 compile 到底是什么,gradle 自己没有定义就不能用了吗?那倒也不是,gradle kotlin DSL 会帮我们根据插件的 configuration 定义生成这样的代码。这在 gradle kotlin dsl 0.8.0 中就做了支持,官方把他们称作:Type-safe accessors,这个版本也跟随 gradle 3.5 发版。

我本来用 4.0 用得好好的,非要因为 settings.gradle.kts 改用了 4.4 的版本,导致出现了这个问题,我就想难道新版本做了调整?于是我又换了 4.5、4.5.1,果然问题还是有。

后来查了一下官方 demo "hello-kotlin":

plugins {
    application
    kotlin("jvm") version "1.2.0"
}

application {
    mainClassName = "samples.HelloWorldKt"
}

dependencies {
    compile(kotlin("stdlib"))
}

repositories {
    jcenter()
}

对比了一下才发现,原来人家用的 是 plugins{} 这种写法,而我的工程仍然用的是 apply plugin 的写法,就这么点儿区别。。难道真的是因为这个?

果然,我把我的配置修改了一下:

- apply {
-    plugin("java")
-    plugin("kotlin")
- }

+ plugins {
+    java
+    kotlin("jvm") version "1.2.10"
+ }

这时候果然没问题了:

而且我们也能找到 compile 的定义:

fun DependencyHandler.`compile`(dependencyNotation: Any): Dependency =
    add("compile", dependencyNotation)

原来,这些 gradle 帮我们动态生成的 accessors,生成的时机就是 plugins{} 调用之后。也就是说我们需要使用这种方式来应用插件才会生成上述的方法。

详细说明在 gradle kotlin DSL 0.8.0 的更新说明当中:https://github.com/gradle/kotlin-dsl/releases/tag/v0.8.0 ,不过其中提到的 gskGenerateAccessors 我在 gradle 4.5 当中已经找不到了。

小结

kotlin 和 groovy 也算是各有所长,如果我们对于 gradle 的语法非常熟悉,那么我个人认为用 groovy 写 DSL 倒也灵活,kotlin 的约束毕竟多一些——而这也正是 Kotlin DSL 的优点,静态类型安全有保障。。


本文分享自微信公众号 - Kotlin(KotlinX),作者:bennyhuo

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-02-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Gradle下载慢?我就没办法治你了么?

    话说故事是这样的,我第一次用 Maven 的时候还在学校,用了一次就想死的心都有了。后来用上了 Gradle,虽然配置简单了,他喵的还是慢好伐,可是我家的百兆宽...

    bennyhuo
  • 基于 Node.js 环境的 KotlinJs 工程的完美搭建

    我们知道 Kotlin 对 Jvm 的支持实在是太好了,以至于我们创建一个 Java 工程,配置一下 Kotlin 的编译插件和标准库就可以很轻松愉快的开始玩耍...

    bennyhuo
  • Kotlin Native 详细体验,你想要的都在这儿

    本文通过 gradle 以及 makefile 两种方式对 Kotlin Native 项目进行构建,提供了详细的从 C 源码编译、到 Kotlin Nativ...

    bennyhuo
  • Android开发:Kotlin下配置DataBinding

    近日,随着Google召开了Google I/O 2017,Kotlin大火一把。因为Google宣布Kotlin为First-class开发语言作 为一名Ko...

    JarvanMo
  • 如何用kotlin开发同时支持iOS和Android的库

    虽说kotlin-native可以支持链接到c,java,objective-c等语言,甚至可以进行原生开发,但是在使用的过程中并不友好,配置繁琐且api相对生...

    Leacode
  • 《Springboot极简教程》Springboot使用Kotlin和Java混合编程配置工程目录结构让kotlin代码的归kotlin目录,java代码归java目录Java代码Kotlin代码互相

    要想实现Springboot使用Kotlin和Java混合编程,需要使用kotlin插件:

    一个会写诗的程序员
  • 使用Spring Boot和Kotlin创建RESTfull API

    使用 Kotlin 结合 SpringBoot 开发一个 RESTFul版本的 HelloWorld。

    全科
  • 【Rust日报】2020-02-08 wasm-pack 0.9.1发布了!

    wasm-pack,该工具旨在成为一站式平台,用于构建Rust生成的WebAssembly,希望使用它与JavaScript,浏览器或Node.js进行互操作。...

    MikeLoveRust
  • Travis CI Could not find or load main class org.gradle.wrapper.GradleWrapperMain 错误

    (adsbygoogle = window.adsbygoogle || []).push({});

    HoneyMoose
  • 一个基于.NET平台的自动化/压力测试系统设计简述

    AutoTest是一个基于.NET平台实现的自动化/压力测试的系统,可独立运行于windows平台下,支持分布式部署,不需要其他配置或编译器的支持。(本质是一个...

    lulianqi

扫码关注云+社区

领取腾讯云代金券