vlambda博客
学习文章列表

读书笔记《gradle-effective-implementations-guide-second-edition》混合语言

Chapter 8. Mixed Languages

我们已经了解了如何将 Gradle 用于带有 Java 代码的项目。 Gradle 也支持其他语言。在过去的几年里,出现了其他用于 JVM 的语言。在本章中,我们将了解 Gradle 对 Groovy 和 Scala 语言的支持。 JVM 支持这两种语言。

我们将看到如何将正确的插件和配置应用到我们的 Gradle 构建文件以使用不同的语言。

Gradle 也支持 C。C 插件增加了对编译源文件的支持。 JavaScript 和 Closure 插件作为第三方插件提供,增加了对这些语言的支持。我们不会在本书中介绍这种支持。我们将专注于 JVM 语言——Groovy 和 Scala。

Using the Groovy plugin


要在我们的项目中使用 Groovy 源,我们可以应用 Groovy 插件。 Groovy 插件可以将 Groovy 源文件编译为类文件。该项目可以包含 Java 和 Groovy 源文件。 Gradle 使用的编译器是一个联合编译器,可以编译 Java 和 Groovy 源文件。

该插件还为我们的构建添加了新任务。要编译 Groovy 源文件,我们可以调用 compileGroovy 任务。可以使用  compileTestGroovy 任务编译用 Groovy 编写的测试源。此外,为我们的构建定义中的每个额外源集添加了一个 compile<SourceSet>Groovy 任务。因此,如果我们创建一个名为 api 的新源集,就会有一个 compileApiGroovy 任务。

在以下示例构建文件中,我们应用了 Groovy 插件:

apply plugin: 'groovy' 

如果我们调用 tasks 任务来查看可用的内容,我们会得到以下输出:

$ gradle tasks
:tasks
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles test classes.
Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]
Documentation tasks
-------------------
groovydoc - Generates Groovydoc API documentation for the main source code.
javadoc - Generates Javadoc API documentation for the main source code.
Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'groovy'.
components - Displays the components produced by root project 'groovy'. [incubating]
dependencies - Displays all dependencies declared in root project 'groovy'.
dependencyInsight - Displays the insight into a specific dependency in root project 'groovy'.
help - Displays a help message.
model - Displays the configuration model of root project 'groovy'. [incubating]
projects - Displays the sub-projects of root project 'groovy'.
properties - Displays the properties of root project 'groovy'.
tasks - Displays the tasks runnable from root project 'groovy'.
Verification tasks
------------------
check - Runs all checks.
test - Runs the unit tests.
Rules
-----
Pattern: clean<TaskName>: Cleans the output files of a task.
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.
Pattern: upload<ConfigurationName>: Assembles and uploads the artifacts belonging to a configuration.
To see all tasks and more detail, run gradle tasks --all
To see more detail about a task, run gradle help --task <task>
BUILD SUCCESSFUL
Total time: 1.378 secs

请注意,我们还从 Java 插件中获得了所有任务。这是因为 Groovy 插件自动包含 Java 插件。因此,即使我们只在构建文件中定义了 Groovy 插件,Java 插件也会被应用。

额外的 compileGroovy 和  compileTestGroovy 任务在命令输出中可见。新任务是 classes 和 testClasses 任务的依赖任务。如果我们调用 classes 任务,则 compileGroovy 任务也会被执行。

该插件添加了 groovy 配置。 Groovy 编译器使用此配置。因此,要在我们的项目中编译 Groovy 源文件,我们必须设置对 compile 配置的依赖。

要编译 Groovy 源文件,我们必须将要使用的 Groovy 库的依赖项添加到 compile 配置中。我们可能期望 Gradle 将使用 Gradle 使用的 Groovy 版本,但编译任务独立于 Gradle 使用的 Groovy 版本。我们必须自己定义 Groovy 库。

独立于 Gradle 附带的 Groovy 库是很好的,因为这样我们就可以使用我们真正需要的 Groovy 版本。当我们想使用 Gradle 附带的 Groovy 库时,我们可以使用 localGroovy() 特殊依赖项。对于普通的 Groovy 项目,不建议这样做;但对于插件开发,它很有用。

首先,我们创建一个 Groovy 源文件,以便我们可以使用 Gradle 编译它。 Groovy 源文件的默认源目录是 src/main/groovy。让我们在 src/main/groovy/gradle/sample目录下新建一个文件,名称为 Sample.groovy .以下代码显示了该文件的内容:

// File: src/main/groovy/gradle/sample/Sample.groovy 
package gradle.sample 
 
import groovy.transform.ToString 
 
@ToString 
class Sample { 
    String name 
} 

接下来,我们创建一个 Gradle 构建文件并应用 Groovy 插件。我们将 Bintray JCenter 存储库和 Groovy 依赖项添加到 compile 配置中,如下所示:

apply plugin: 'groovy' 
 
repositories { 
    jcenter() 
} 
 
dependencies { 
    // Define dependency for Groovy libraries. 
    compile group: 'org.codehaus.groovy', 
      name: 'groovy', 
      version: '2.4.5' 
} 

当我们运行 build 任务时,我们得到以下输出:

$ gradle build
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:compileTestGroovy UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build
BUILD SUCCESSFUL
Total time: 6.081 secs

当我们的缓存中没有指定的 Groovy 库时,Gradle 从 Bintray JCenter 存储库下载它。源代码文件编译完成,查看build/classes目录可以看到编译后的class文件。

Groovy 插件还添加了新的源集属性。下表显示了额外的属性:

属性名称

类型

说明

时髦

org.gradle.api.file.SourceDirectorySet

这些是该项目的 Groovy 源文件。这包含 .java 和 .groovy 源文件,如果它们在 groovy 目录。

groovy.srcDirs

java.util.Set

这些是带有 Groovy 源文件的目录。它们还可以包含用于联合编译的 Java 源文件。

allGroovy

org.gradle.api.file.FileTree

这些仅包含 Groovy 源文件。所有带有 .groovy 扩展名的文件都是这个集合的一部分。

我们扩展了之前的构建文件并添加了 groovySourceSetsProperties 任务。我们使用此任务打印额外的属性及其值。构建现在看起来类似于以下代码:

apply plugin: 'groovy' 
 
repositories { 
    jcenter() 
} 
 
dependencies { 
    // Use String notation to define dependency. 
    compile 'org.codehaus.groovy:groovy:2.4.5' 
} 
 
// New task to print out source set properties 
// added by the Groovy plugin. 
task groovySourceSetProperties << { 
    sourceSets.main.with { sourceSet -> 
      println "groovy.srcDirs = ${sourceSet.groovy.srcDirs}" 
      println "groovy.files = ${sourceSet.groovy.files.name}" 
      println "allGroovy.files = ${sourceSet.allGroovy.files.name}" 
    } 
} 

当我们在命令行上运行 groovySourceSetProperties 任务时,我们会看到以下输出:

$ gradle groovySourceSetProperties
:groovySourceSetProperties
groovy.srcDirs = [/gradle-book/samples/Chapter8/Code_Files/groovy/src/main/groovy]
groovy.files = [Sample.groovy]
allGroovy.files = [Sample.groovy]
BUILD SUCCESSFUL
Total time: 0.729 secs

当我们的 Java 代码使用 Groovy 类时,反之亦然,我们可以使用联合编译功能。我们必须确保 Java 和 Groovy 源文件都在 src/main/groovy 目录中。

Creating documentation with the Groovy plugin

Groovy 插件还添加了 groovydoc 任务。  groovydoc 任务类似于 Java 插件中的 javadoc 任务。 Gradle 使用 GroovyDoc 工具,该工具可从我们定义为  compile 配置的依赖项的 Groovy 版本中获得.

该任务有几个我们可以更改的属性。例如,我们可以设置要在生成的文档中使用的页眉和页脚。

在以下构建文件中,我们将配置 groovydoc 任务:

apply plugin: 'groovy' 
 
// Set version for project, we use 
// it in the configuration for groovydoc. 
version = 1.0 
 
repositories { 
    jcenter() 
} 
 
dependencies { 
    compile 'org.codehaus.groovy:groovy:2.4.5' 
} 
 
// Configure groovydoc task. 
groovydoc { 
    header = 'GroovyDoc for sample project' 
    footer = "Generated documentation - $version" 
    docTitle = 'GroovyDoc Title' 
    windowTitle = docTitle 
    use = true // Create class and package usage pages 
 
    // Exclude files, use include to include files 
    exclude '**/*Doc.groovy' 
} 

当我们运行 groovydoc 任务时,我们可以在 build/docs/groovydoc 目录中看到生成的文档。我们必须在 Web 浏览器中打开 index.html 文件才能看到结果。

Using the Scala plugin


我们还可以使用 Gradle 来处理 Scala 源文件。我们可以在我们的项目中有一个纯 Scala 项目或 Java 和 Scala 源文件。我们必须应用 Scala 插件来为我们的构建启用 Scala 支持。该插件添加了新任务来编译 Scala 源文件。通过 compileScala 任务,我们编译我们的主要 Scala 源文件。源文件必须在 src/main/scala 目录中。  compileTestScala 任务编译 src/test/scala 目录中的所有 Scala 源代码文件。该插件还为我们的构建中的自定义源集添加了一个 compile<SourceSet>Scala 任务。

编译任务通过联合编译支持 Java 和 Scala 源文件。我们可以将 Java 源文件放在项目的  src/main/java 目录中,将 Scala 源文件放在  src /main/scala 目录。编译器将编译这两种类型的文件。为了能够编译这些文件,我们必须在我们的构建文件中添加对 Scala 库的依赖。我们必须将来自 Maven 存储库的正确依赖项分配给 compile 配置,以便 Gradle 可以调用编译器来编译源文件。

我们在 src/main/scala/gradle/ 目录下创建一个简单的 Scala 源文件 sample 并保存为 Sample.scala:

package gradle.sample 
 
class Sample(val name: String) { 
    def getName() = name 
} 

在以下示例构建文件中,我们应用了 Scala 插件。此外,在 dependencies 部分中,我们为编译器设置了正确的依赖项,如下所示:

apply plugin: 'scala' 
 
repositories { 
    jcenter() 
} 
 
dependencies { 
    // Define dependency on Scala library 
    // for compilation and Scala tools. 
    compile group: 'org.scala-lang', 
      name: 'scala-library', 
      version: '2.11.4' 
} 

为了构建项目,我们调用 build 任务并获得以下输出:

$ gradle build
:compileJava UP-TO-DATE
:compileScala
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:compileTestScala UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build
BUILD SUCCESSFUL
Total time: 2.656 secs

注意 compileScala 和 compileTestScala 任务是 类 和testClasses 任务。因此,新添加的任务自动成为我们从 Java 项目中知道的正常构建任务的一部分。如果我们自己不应用 Java 插件,Scala 插件会自动包含 Java 插件。

我们可以在我们的项目中定义一个自定义源集。 Scala 插件为我们项目的每个源集添加了一个 compile 任务。在下面的 Gradle 构建文件中,我们添加了一个名为 actors 的新源集,如下所示:

apply plugin: 'scala' 
 
repositories { 
    jcenter() 
} 
 
dependencies { 
    compile "org.scala-lang:scala-library:2.11.4" 
} 
 
sourceSets { 
    // Extra source set actors. 
    actors 
} 

当我们调用 tasks 命令时,我们看到 Gradle 将 compileActorsScala 添加到了可用任务列表中:

$ gradle tasks --all
:tasks
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
Build tasks
-----------
actorsClasses - Assembles actors classes.
compileActorsJava - Compiles actors Java source.
compileActorsScala - Compiles the actors Scala source.
processActorsResources - Processes actors resources.
assemble - Assembles the outputs of this project. [jar]
build - Assembles and tests this project. [assemble, check]
buildDependents - Assembles and tests this project and all projects that depend on it. [build]
buildNeeded - Assembles and tests this project and all projects it depends on. [build]
classes - Assembles main classes.
compileJava - Compiles main Java source.
compileScala - Compiles the main Scala source.
processResources - Processes main resources.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes. [classes]
testClasses - Assembles test classes. [classes]
compileTestJava - Compiles test Java source.
compileTestScala - Compiles the test Scala source.
processTestResources - Processes test resources.
...
BUILD SUCCESSFUL
Total time: 0.76 secs

actorsClasses 任务已添加,并具有 actors 源集的所有编译任务。当我们希望 actorsClasses 任务成为构建任务的一部分时,我们可以将其作为任务依赖项分配给jar任务。在下面的示例构建文件中,我们使用 jar任务的 from()方法来分配 的输出;actors 源集作为 JAR 文件内容的一部分。

当我们执行 build 任务时,我们在 actors 源集中的源文件被编译并添加到 JAR 文件中。

Scala 插件还向源集添加了几个新属性。下表显示了额外的属性:

属性名称

类型

说明

scala

org.gradle.api.file.SourceDirectorySet

这是这个项目的 Scala 源文件;它包含 .java.scala 源文件(如果它们位于 Scala 目录中)。

scala.srcDirs

java.util.Set

这些是 Scala 源文件的目录;它们还可以包含用于联合编译的 Java 源文件。

allScala

org.gradle.api.file.FileTree

这些只是 Scala 源文件。所有带有 .scala 扩展名的文件都是这个集合的一部分。

让我们创建一个新任务 scalaSourceSetsProperties,来查看每个属性的内容:

apply plugin: 'scala' 
 
repositories { 
    jcenter() 
} 
 
dependencies { 
    compile "org.scala-lang:scala-library:2.11.4" 
} 
 
// New task to show properties on the 
// main source set added by the Scala plugin. 
task scalaSourceSetsProperties << { 
    sourceSets.main.with { sourceSet -> 
        println "scala.srcDirs = ${sourceSet.scala.srcDirs}" 
        println "scala.files = ${sourceSet.scala.files.name}" 
        println "allScala.files = ${sourceSet.allScala.files.name}" 
    } 
} 

当我们从命令行调用 scalaSourceSetsProperties 任务时,我们得到以下输出:

$ gradle scalaSourceSetsProperties
:scalaSourceSetsProperties
scala.srcDirs = [/gradle-book/samples/Chapter8/Code_Files/scala/src/main/scala]
scala.files = [Sample.scala]
allScala.files = [Sample.scala]
BUILD SUCCESSFUL
Total time: 0.627 secs

Creating documentation with the Scala plugin

Scala 插件还在我们的构建中添加了一个 scaladoc 任务。我们可以使用此任务从源文件生成文档。这类似于 Java 插件中的 javadoc 任务。我们可以配置 scaladoc 任务来提供额外的选项。

在以下示例构建文件中,我们通过配置 scaladoc 任务为生成的文档添加标题:

import org.gradle.api.tasks.scala.* 
 
apply plugin: 'scala' 
 
version = 2.1 
 
repositories { 
    jcenter() 
} 
 
dependencies { 
    compile "org.scala-lang:scala-library:2.11.4" 
} 
 
// Configure ScalaDoc task. 
scaladoc { 
    title = 'Scala documentation' 
} 

当我们调用 scaladoc 任务时,Gradle 会生成文档,结果在 build/docs/scaladoc 中。我们可以在 Web 浏览器中打开 index.html 文件来查看生成的文档。

Summary


在本章中,我们讨论了如何在 Gradle 项目中使用 Groovy 和 Scala 源代码。我们将 Groovy 或 Scala 插件应用到我们的项目中,并看到 Gradle 添加了将源文件编译到项目中的任务。我们还讨论了必须将依赖项添加到插件添加的依赖项配置的正确 Groovy 或 Scala 版本。这两个插件也将包含 Java 插件。

我们还讨论了插件还为源集提供了一些新属性,例如,我们可以在源集中查找所有 Groovy 或 Scala 源文件。

在下一章中,我们将了解如何将代码质量工具添加到我们的 Gradle 构建中。