Gradleビルドスクリプトから一般的なメソッドを抽出します


85

Gradleビルドスクリプト(build.gradle)があり、そこでいくつかのタスクを作成しました。これらのタスクは、主にメソッド呼び出しで構成されています。呼び出されたメソッドもビルドスクリプトに含まれています。

さて、これが状況です:

さまざまなタスクを含むかなりの量のビルドスクリプトを作成していますが、元のスクリプトと同じメソッドを使用しています。したがって、これらの「一般的なメソッド」を何らかの方法で抽出して、作成する新しいスクリプトごとにコピーする代わりに、簡単に再利用できるようにしたいと思います。

GradleがPHPの場合、次のようなものが理想的です。

//script content
...
require("common-methods.gradle");
...
//more script content

しかしもちろん、それは不可能です。またはそれは?

とにかく、どうすればこの結果を達成できますか?これを行うための最良の方法は何ですか?Gradleのドキュメントをすでに読んだことがありますが、どの方法がこれに最も簡単で最適かを判断できないようです。

前もって感謝します!


更新:

別のファイルにメソッドを抽出することができました

(を使用してapply from: 'common-methods.gradle')、

したがって、構造は次のとおりです。

parent/
      /build.gradle              // The original build script
      /common-methods.gradle     // The extracted methods
      /gradle.properties         // Properties used by the build script

からタスクを実行した後build.gradle、私は新しい問題にぶつかりました。どうやら、メソッドがにあるときにメソッドが認識されないようですcommon-methods.gradle

それを修正する方法についてのアイデアはありますか?


メソッドを作成する必要がありますか?メソッドの観点からビルドスクリプトを作成すると、Gradleの優れた機能の一部を見逃してしまいます。最も重要なことは、インクリメンタルビルドを正しく機能させるために余分な作業が必要になることです。意図された抽象化は、タスクを使用および再利用することです。カスタムタスクを作成することもできます。おそらく、メソッドに現在ある実装をタスクに入れることを検討する必要があります。
アルパー2016年

@Alpar; timestamp()またはcurrentWorkingDirectory()メソッドをtask-sとして作成するためにどのような目的が提供されますか(たとえば)。ユーティリティ関数や同様のものは名目上スカラーです-Gradleとほとんどのビルドシステムに組み込まれているコードの再利用に制限があることを除いて、それらはタスクではありません。一度作って再利用できるDRYの世界が好きです。実際には、@Pieter VDEの例を拡張し、私はまた、「使用root.gradlebuild.gradleファイルは通常、ちょうどそのいくつかのプロジェクトの詳細を定義します-私の親プロジェクトのための」パターンapply ${ROOT}...
意志

あなたはプロパティで仕事に集中型の方法が必要な場合は、多分この質問はあなたを助けることができる:stackoverflow.com/questions/60251228/...
GarouDan

回答:


76

メソッドを共有することはできませんが、クロージャを含む追加のプロパティを共有することはできます。これは、要約すると同じことです。たとえば、で宣言ext.foo = { ... }common-methods.gradle、を使用apply from:してスクリプトを適用してから、を使用してクロージャを呼び出しますfoo()


1
それは確かにトリックを行います!しかし、私はこれについて質問があります:何かを返すメソッドはどうですか?FeFile foo(String f)はになりますext.foo = { f -> ... }、それから私は次のようなことをすることができFile f = foo(...)ますか?
Pieter VDE 2013

2
どうやら、私の前のコメントの質問は可能です。ピーター、この質問に答えてくれてありがとう!
Pieter VDE 2013

1
@PeterNiederwieserなぜそれが不可能なのですか?Gradle.orgはそう思う:docs.gradle.org/current/userguide/...
IgorGanapolsky

1
@IgorGanapolskyリンクをありがとう。gradle.buildの別のビルドファイルで生成された値をどのように使用できるのでしょうか-この方法で非常に便利です:)
kiedysktos 2017年

@IgorGanapolsky共有したリンクは、Peter VDEの質問のコンテキストでどのように役立ちますか?
t0r0X 2017年

157

Peterの答えに基づいて、これが私のメソッドをエクスポートする方法です。

内容helpers/common-methods.gradle

// Define methods as usual
def commonMethod1(param) {
    return true
}
def commonMethod2(param) {
    return true
}

// Export methods by turning them into closures
ext {
    commonMethod1 = this.&commonMethod1
    otherNameForMethod2 = this.&commonMethod2
}

そして、これは私が別のスクリプトでそれらのメソッドを使用する方法です:

// Use double-quotes, otherwise $ won't work
apply from: "$rootDir/helpers/common-methods.gradle"

// You can also use URLs
//apply from: "https://bitbucket.org/mb/build_scripts/raw/master/common-methods.gradle"

task myBuildTask {
    def myVar = commonMethod1("parameter1")
    otherNameForMethod2(myVar)
}

Groovyでメソッドをクロージャに変換する方法について詳しく説明します。


クロージャー名をextとして使用する特別な理由はありますか?
アヌープ

1
@AnoopSSGradleの追加プロパティに2つのクロージャーを追加します。これらの追加のプロパティは、と呼ばれるオブジェクトにバンドルされていますext
マティアスブラウン2016

どういうわけか、インクルードされたファイルで定義されているクラスとして値をキャストできますか?
GarouDan

これに関するサンプルコード@GarouDanを含む別の質問を投稿することをお勧めします。
マティアスブラウン

7

Kotlin dslを使用すると、次のように機能します。

build.gradle.kts

apply {
  from("external.gradle.kts")
}

val foo = extra["foo"] as () -> Unit
foo()

external.gradle.kts

extra["foo"] = fun() {
  println("Hello world!")
}

実際のタイプを共有する方法はありますか?あなたは基本的に型安全性を失い、コンパイラの助けを借りています...あなたのメソッドを含むクラスを共有できれば、コンパイラを利用することができます。
VACH

0

KotlinDSLの別のアプローチは次のとおりです。

my-plugin.gradle.kts

extra["sum"] = { x: Int, y: Int -> x + y }

settings.gradle.kts

@Suppress("unchecked_cast", "nothing_to_inline")
inline fun <T> uncheckedCast(target: Any?): T = target as T

apply("my-plugin.gradle.kts")

val sum = uncheckedCast<(Int, Int) -> Int>(extra["sum"])

println(sum(1, 2))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.