自己最近又在用 JVM 系的语言开新坑。这次终于说服自己从 Jetbrains 的温床里脱离出来改用了大家都在用的 Gradle!感觉良好,在这里简单写一下大概咋用,给之后的自己留一个参考吧。

为什么自己要用 Gradle 呢?

  1. Gradle 作为一个开源的构建系统不与任何 IDE 绑定(比如说 IDEA),这相当于增加了代码的兼容性。
  2. Gradle 里面可以直接从 Maven Central 上下库下来,省了我手动下库导入的过程,库更新了也好维护。这对我来说非常地有诱惑力。实测也非常舒服。
  3. Gradle 从设计上来说非常灵活,Gradle 默认的构建脚本是用 Groovy 写的(当然也可以用 Kotlin 但是这似乎不是主流的样子),而不是只有标记功能的 XML,这使 Gradle 一下子非常强大。
  4. 大家都在用的样子。
  5. IDEA 对于 Gradle 的支持非常棒!(所以到头来自己还是没有逃脱 JB 的舒适圈……)

虽然说 Gradle 的功能很强大我目前的用法还是最初级的。我目前用的 Gradle 代码大致如下:

plugins {
    id 'java'
    id 'org.jetbrains.kotlin.jvm' version '1.3.61'
}

group 'chengyuan'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8
project.ext.lwjglVersion = "3.2.3"
project.ext.lwjglNatives = "natives-windows"

repositories {
    maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
    maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
    mavenCentral()
}

dependencies {
    implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion")
    
    implementation "org.lwjgl:lwjgl"
    implementation "org.lwjgl:lwjgl-assimp"
    implementation "org.lwjgl:lwjgl-bgfx"
    implementation "org.lwjgl:lwjgl-glfw"
    implementation "org.lwjgl:lwjgl-nanovg"
    implementation "org.lwjgl:lwjgl-nuklear"
    implementation "org.lwjgl:lwjgl-openal"
    implementation "org.lwjgl:lwjgl-opengl"
    implementation "org.lwjgl:lwjgl-par"
    implementation "org.lwjgl:lwjgl-stb"
    implementation "org.lwjgl:lwjgl-vulkan"
    runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-assimp::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-bgfx::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-nanovg::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-nuklear::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-openal::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-par::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives"
    
    testCompile group: "junit", name: "junit", version: "4.12"
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}

compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}

首先是 plugins 这段,这一段虽然重要但一般用不着特别操心,按照我的理解大概是语言支持的插件。

接下来是版本、JVM 版本之类的,看着也很明白。

然后可以申明一些接下来会用到的常量。

repository 告诉 Gradle 从哪里找库。常见的源有内置的函数,例如 mavenCentral()jcenter()。如果是其他的 Maven 源也可以指定 URL。比如说我这里用了阿里云的 Maven 镜像,在国内速度就会快上很多。

接下来是 dependencies,这个是重头戏。

最常见的是 implementation,这个后面一般跟库的 Maven id。如果想直接引用本地文件可以用 files(...),如果是一个平台一个版本的可以用 platform(...)。基本上这就覆盖了 99% 的用途。

此外还有 runtimeOnly,这个和 implementation 的区别就是 runtimeOnly 的库是不参与编译的,只在运行期有效。这一般都是用 JNI 的一众 native 库和一些二级库。

还有 testCompile,用这个修饰的库是只在跑单元测试的时候依赖的,因此基本上都是一些测试有关的库。我人懒,平时懒得写单元测试,因此这个我基本上不用。

这些就是我目前摸索出来的 Gradle 的基本用法,目前的感觉就是把 IDEA 里面的很多 GUI 的操作文字化,非常舒适,省了很多麻烦。更复杂的用法例如自定义 build task 等都可以在官网上找到(文档很丰富也是 Gradle 比较吸引人的点)。

最后有一点点想吐槽,就是 Groovy 似乎单引号和双引号都可以表示字符串。双引号的字符串支持插值,这似乎是唯一的予以区别。IDE 默认生成的是单引号,LWJGL 的打包器生成的是双引号,似乎最通用的是双引号,自己到底是用双引号还是单引号呢?这种东西真的是万恶之源。