へんてこのブログ

日々気づいたことや、最近やっていることを書いています

Gradleプラグインで入れ子構造の引数を受け取る方法

課題

とあるGradleプラグインのアップデートを実装してて、設定の記述をこんな風にしたかった

sample {
  configKey = "test config key"

  books {
    quickStart {
      title = "quick start book"
      body = "quick start book body"
    }
    userGuide {
      title = "user guide book"
      body = "user guide book body"
    }
    ...
    ...
    ...
  }
}

sampleって中にconfigKeyってパラメータを保持したまま、その中のbooksパラメータの中に任意の数のパラメータを入れ子構造で入れていきたいってのが今回の課題

こういうのをいい感じに解析するのにGradleではproject.containerってのを使うらしい
参照: 第58章 カスタムプラグインの作成

この参照先のサイトの例を見ると、booksの中にいい感じに入れ子構造での値受け渡しが出来てるみたいだけど、このさらに上の構造(configKeyの所)が今回は必要なので少し工夫する

方法

サンプルプラグインを書いてみた
henteko/gradle-samplebooks-plugin · GitHub

2013/11/29 7:00頃追記

サンプルのプラグインをアップデートしました
Gradleプラグインでの入れ子構造引数による動的タスク生成 - hentekoのdev日記

ちょっと解説

Pluginのapplyメソッド内で以下を記述する

def sample = new SampleExtension(project.container(BookTarget))
project.convention.plugins.sample = sample
project.extensions.sample = sample

SampleExtensionクラスを作成し、そのコンストラクタとしてproject.container(BookTarget)を渡す
SampleExtensionはこんな感じ

public class SampleExtension {
    final private NamedDomainObjectContainer<BookTarget> sampleBooks
    String configKey

    public SampleExtension(NamedDomainObjectContainer<BookTarget> books) {
        sampleBooks = books
    }

    public books(Closure closure) {
        sampleBooks.configure(closure)
    }
}

ここで重要なのが、booksメソッド*1でsampleBooks.configure(closure)を実行すること
これで解析していい感じに値が取得出きる

値の取得

値の取得はそれぞれ、
configKey : project.sample.configKey
books : project.sampleBooks*2
で取得が出来る
全て取得したい場合はこんな感じ

for(book in project.sampleBooks) {
    println book.name
}

まとめ

結構苦労した
他の既に動いてるプラグインを参考にしてやっと出来た感じだった
参考: catalysts-gradle-plugins/src/main/groovy/cc/catalysts/gradle/plugins/deploy at 155df09fd1754c6aa9df84d41632a495c0ca1faa · Catalysts/catalysts-gradle-plugins · GitHub
参考2: jvoegele/gradle-android-plugin · GitHub

*1:このメソッド名で設定記述欄の名前が決まる

*2:SampleExtension内のNamedDomainObjectContainerの変数名で決定されるよう