建立自己的 Gradle Scala 外掛

完成基本設定示例後,你可能會發現自己在每個 Scala Gradle 專案中都重複了大部分內容。聞起來像樣板程式碼……

如果不使用 Gradle 提供的 Scala 外掛 ,你可以應用自己的 Scala 外掛,該外掛將負責處理所有常見的構建邏輯,同時擴充套件已有的外掛。

這個例子將把以前的構建邏輯轉換為可重用的 Gradle 外掛。

幸運的是,在 Gradle 中,你可以在 Gradle API 的幫助下輕鬆編寫自定義外掛,如文件中所述。作為實現語言,你可以使用 Scala 本身甚至 Java。但是,你可以在整個文件中找到的大多數示例都是用 Groovy 編寫的。例如,如果你需要更多程式碼示例或想了解 Scala 外掛背後的內容,可以檢視 gradle github repo

編寫外掛

要求

自定義外掛在應用於專案時將新增以下功能:

  • scalaVersion 屬性物件,它將具有兩個可覆蓋的預設屬性
    • major =“2.12”
    • minor =0
  • 應用於依賴項名稱的 withScalaVersion 函式將新增 scala 主要版本以確保二進位制相容性(sbt %%運算子可能響鈴,否則在繼續之前轉到此處
  • 建立必要目錄樹的 createDirs 任務,與前面的示例完全相同

實施指南

  1. 建立一個新的 gradle 專案並將以下內容新增到 build.gradle

    apply plugin: ‘scala’ apply plugin: ‘maven’

    repositories { mavenLocal() mavenCentral() }

    dependencies { compile gradleApi() compile “org.scala-lang:scala-library:2.12.0” }

備註

  • 外掛實現是用 Scala 編寫的,因此我們需要 Gradle Scala 外掛
  • 為了使用其他專案的外掛,使用 Gradle Maven 外掛; 這增加了用於將專案 jar 儲存到 Maven Local Repository 的 install 任務
  • compile gradleApi()gradle-api-<gradle_version>.jar 新增到類路徑中
  1. 為外掛實現建立一個新的 Scala 類
 placeholderCopypackage com.btesila.gradle.plugins 
 
import org.gradle.api.{Plugin, Project}  
 
class ScalaCustomPlugin extends Plugin[Project] {
    override def apply(project: Project): Unit = {
        project.getPlugins.apply("scala")
    }
}

備註

  • 為了實現外掛,只需擴充套件 Project 型別的 Plugin 特性並覆蓋 apply 方法
  • 在 apply 方法中,你可以訪問外掛所應用的 Project 例項,你可以使用它來為其新增構建邏輯
  • 這個外掛什麼都不做,只是應用現有的 Gradle Scala 外掛
  1. 新增 scalaVersion 物件屬性

首先,我們建立一個 ScalaVersion 類,它將儲存兩個版本屬性

Copyclass ScalaVersion {
  var major: String = "2.12"
  var minor: String = "0"
}

Gradle 外掛的一個很酷的事實是,你始終可以新增或覆蓋特定屬性。外掛通過連線到 gradle Project 例項的 ExtensionContainer 接收這種使用者輸入。有關詳細資訊,請檢視資訊。
通過在 apply 方法中新增以下內容,我們基本上是這樣做的:

  • 如果專案中沒有定義 scalaVersion 屬性,我們新增一個預設值

  • 否則,我們將現有的一個作為 ScalaVersion 的例項,以進一步使用它

    var scalaVersion = new ScalaVersion if (!project.getExtensions.getExtraProperties.has(“scalaVersion”)) project.getExtensions.getExtraProperties.set(“scalaVersion”, scalaVersion) else scalaVersion = project.getExtensions.getExtraProperties.get(“scalaVersion”).asInstanceOf[ScalaVersion]

這相當於將以下內容寫入應用外掛的專案的構建檔案:

Copyext {
    scalaVersion.major = "2.12"
    scalaVersion.minor = "0"

}
  1. 使用 scalaVersion 將 t​​ihuan20 庫新增到專案依賴項中

    project.getDependencies.add(“compile”, s"org.scala-lang:scala-library:${scalaVersion.major}.${scalaVersion.minor}")

這相當於將以下內容寫入應用外掛的專案的構建檔案:

Copycompile "org.scala-lang:scala-library:2.12.0"
  1. 新增 withScalaVersion 功能

    val withScalaVersion = (lib: String) => { val libComp = lib.split(":") libComp.update(1, s"${libComp(1)}_${scalaVersion.major}") libComp.mkString(":") } project.getExtensions.getExtraProperties.set(“withScalaVersion”, withScalaVersion)

  2. 最後,建立 createDirs 任務並
    通過擴充套件 DefaultTask 將其新增到專案實現 Gradle 任務:

    class CreateDirs extends DefaultTask { @TaskAction def createDirs(): Unit = { val sourceSetContainer = this.getProject.getConvention.getPlugin(classOf[JavaPluginConvention]).getSourceSets

    CopysourceSetContainer forEach { sourceSet =>
      sourceSet.getAllSource.getSrcDirs.forEach(file => if (!file.getName.contains("java")) `file.mkdirs()`)
    }

    } }

注意SourceSetContainer 包含有關專案中存在的所有源目錄的資訊。Gradle Scala 外掛的作用是將額外的源集新增到 Java 庫中,如外掛文件中所示

通過將此附加到 apply 方法,將 createDir 任務新增到專案中:

Copyproject.getTasks.create("createDirs", classOf[CreateDirs])

最後,你的 ScalaCustomPlugin 類應該是這樣的:

Copyclass ScalaCustomPlugin extends Plugin[Project] {
  override def apply(project: Project): Unit = {
    project.getPlugins.apply("scala")

    var scalaVersion = new ScalaVersion
    if (!project.getExtensions.getExtraProperties.has("scalaVersion"))
      project.getExtensions.getExtraProperties.set("scalaVersion", scalaVersion)
    else
      scalaVersion = project.getExtensions.getExtraProperties.get("scalaVersion").asInstanceOf[ScalaVersion]

    project.getDependencies.add("compile", s"org.scala-lang:scala-library:${scalaVersion.major}.${scalaVersion.minor}")

    val withScalaVersion = (lib: String) => {
      val libComp = lib.split(":")
      libComp.update(1, s"${`libComp(1)`}_${scalaVersion.major}")
      libComp.mkString(":")
    }
    project.getExtensions.getExtraProperties.set("withScalaVersion", withScalaVersion)

    project.getTasks.create("createDirs", classOf[CreateDirs])
  }
}

將外掛專案安裝到本地 Maven 儲存庫

通過執行 tihuan 29
可以輕鬆完成此操作你可以通過訪問本地儲存庫目錄來檢查安裝,通常位於~/.m2/repository

Gradle 如何找到我們的新外掛?

每個 Gradle 外掛都有一個 id,用於 apply 語句。例如,通過將以下內容寫入構建檔案,它將轉換為 Gradle 的觸發器,以查詢並應用 id 為 scala 的外掛。

Copyapply plugin: 'scala'

以同樣的方式,我們希望以下列方式應用我們的新外掛,

Copyapply plugin: "com.btesila.scala.plugin"

這意味著我們的外掛將具有 com.btesila.scala.plugin id。

要設定此 ID,請新增以下檔案:

src / main / resources / META-INF / gradle-plugin / com.btesil.scala.plugin.properties

Copyimplementation-class=com.btesila.gradle.plugins.ScalaCustomPlugin

之後,再次執行 gradle install

使用外掛

  1. 建立一個新的空 Gradle 專案,並將以下內容新增到構建檔案中

    buildscript { repositories { mavenLocal() mavenCentral() }

    Copydependencies {
        //modify this path to match the installed plugin project in your local repository
        classpath 'com.btesila:working-with-gradle:1.0-SNAPSHOT'
    }

    }

    repositories { mavenLocal() mavenCentral() }

    apply plugin: “com.btesila.scala.plugin”

  2. 執行 gradle createDirs - 你現在應該生成所有源目錄

  3. 通過將其新增到構建檔案來覆蓋 scala 版本:

    ext { scalaVersion.major = “2.11” scalaVersion.minor = “8”

    } println(project.ext.scalaVersion.major) println(project.ext.scalaVersion.minor)

  4. 新增與 Scala 版本二進位制相容的依賴庫

    dependencies { compile withScalaVersion(“com.typesafe.scala-logging:scala-logging:3.5.0”) }

而已! 你現在可以在所有專案中使用此外掛,而無需重複相同的舊樣板。