mike-neckのブログ

Java or Groovy or Swift or Golang

Gradle2.8 rc1が出たようです。 #gradle

f:id:mike_neck:20150818084108g:plain

世間ではBazelが流行っていますが、Gradle 2.8 rc-1 が2015/10/1 2:15am頃に出たようですので、リリースノートの超意訳を書きます。

discuss.gradle.org

なお、sdkmanでも取得可能のようです。

~ $ sdk list gradle

================================================================================
Available Gradle Versions
================================================================================
   * 2.8-rc-1             1.5                                                      
   + 2.7-rc-2             1.4                                                      
 > * 2.7                  1.3                                                      
   * 2.6                  1.2                                                      
   * 2.5                  1.12                                                     
     2.4                  1.11                                                     

================================================================================
+ - local version
* - installed
> - currently in use
================================================================================

Faster incremental builds (もっと速くなったインクリメンタルビルド)

Gradleを特徴づけるインクリメンタルビルドによって、Gradleは前回ビルドの成果物を再利用することで冗長な作業を避けています。これはビルド対象のファイルのチェックサムを管理することによってなされているわけですが、今回のリリースではこの管理方法を改善して前のビルド成果を再利用できる場合にビルドが速くなるようになりました。

Gradle2.8では、14万ファイルくらいのプロジェクトでは35〜50%くらい時間が短縮されます。もっと大きなプロジェクト(40万ファイルを超えるようなもの)では相当速くなります。ただし、十分なメモリーがある場合ですけど。もちろんちっちゃなプロジェクトも今回の変更の恩恵に与れます。

Faster build script compilation (より速くなったスクリプトコンパイル)

ビルドスクリプトコンパイル時間が30%くらい短縮されます。初回ビルドとかビルドスクリプトを修正した時などにこの改善効果があらわれます。

なお、コンパイルの時間はビルドスクリプトのサイズや複雑さから影響を受けます。またビルドスクリプトの数によっても影響を受けます。

Faster compilation for continuous builds(より速くなったコンティニュアスビルド)

たいていGradleはパフォーマンス向上のためにデーモンプロセスを起動します。デーモンは初回起動時に立ち上がり、ビルド終了時に終わります。

Gradle2.8ではコンパイラーデーモンはコンティニュアスビルドセッションの最中に起動し続けます。コンティニュアスビルドがキャンセルされた場合にのみ終了します。コンパイラーデーモンの起動を避けられるようになるため、パフォーマンスが向上します。なお、コンティニュアスビルドを使ってない場合は何も変わりません。

次のコンパイラーはフォークされ、この改善効果を体感できます。

全体的なパフォーマンス向上

その他にも様々なパフォーマンス向上対策が行われており、たいていのビルドで効果があります。これはより効率的なデータ構造とキャッシュによるものです。なお、ビルドの短縮時間はビルドのサイズや特性によります。

TestKitAPIが便利になりました

これまでのGradleではプラグインの作成者にいちいちビルドスクリプトのクラスパスを読みこませるようなスクリプトを書かせていました。

今回のリリースで GradleRunner クラスに withPluginClasspath(Iterable<File>) というメソッドが追加されます。ここで渡されるクラスパスはテストで起動されるビルドの中に配置されます。テストは次のような感じになります。

class BuildLogicFunctionalTest extends Specification {
    @Rule final TemporaryFolder testProjectDir = new TemporaryFolder()
    File buildFile
    List<File> pluginClasspath

    def setup() {
        buildFile = testProjectDir.newFile('build.gradle')
        pluginClasspath = getClass().classLoader.findResource("plugin-classpath.txt")
          .readLines()
          .collect { new File(it) }
    }

    def "execute helloWorld task"() {
        given:
        buildFile << """
            plugins {
                id 'com.company.helloworld'
            }
        """

        when:
        def result = GradleRunner.create()
            .withProjectDir(testProjectDir.root)
            .withArguments('helloWorld')
            .withPluginClasspath(pluginClasspath)
            .build()

        then:
        result.standardOutput.contains('Hello world!')
        result.taskPaths(SUCCESS) == [':helloWorld']
    }
}

将来的には自動的にクラスパスがテスト中に起動するビルドの中に読み込まれるような仕組みを提供する予定です。

Zipファイルの名前のエンコーディング

GradleはZipファイルの名前のにデフォルト文字コードを利用していますがOSやツールによっては相性がよくなかったりします。

Zipタスクは明示的にファイル名とコメント用のエンコーディングを指定できるようになります(もちろん、中身のファイルには影響しません)。なお、デフォルトの動作は変わりませんので、現在のビルドに変更が必要はありません。

PMDのrule priorityスレッショルド設定

これまでのPMDプラグインは全てのルール違反を報告しており、また、何らかの違反を発見した場合はビルドが落ちるようになっていました。そのため、プライオリティの低い違反を無視するにはrulesetをカスタマイズする必要がありました。

今後はrule priorityスレッショルドの設定を提供するようになります。このスレッショルドを超える違反のみがPMDのレポートに含まれるようになり、その違反が検知された場合にのみビルドが落ちるようになります。

設定方法は次のとおりです。

pmd {
    rulePriority = 3
}

PMDの型解決

PMDのルールによっては型情報解決のために依存ライブラリーにアクセスする必要があります。PMDのauxclasspathに依存ライブラリーが渡されれば、さらなる問題を発見できます。

今後は自動的にコンパイルの依存ライブラリーをPMDのauxclasspathに渡すようになります。この変更には新たな設定を必要としません。

Managed modelの改善

Managed modelにいくつか改善がなされました。現在はネイティブビルドとPlayプラグインだけに利用されていますが、今後のGradleのビルドにも関係するものです。

SetListのサポート

Managed modelがスカラータイプのコレクション(SetList)をサポートするようになります。つまり、SetListを以下の型とともに使うことができます。

  • JDKNumber 型(IntegerとかDoubleとか)
  • String
  • Boolean
  • File
  • enum

コレクションは @Managedのついた型にプロパティとして付与できます。

@Managed
interface User {
    Set<String> getGroups();
}

なお、コレクションは読み取り専用のプロパティとして定義した場合はデフォルトは空のコレクションです。読み書き可能なプロパティとして定義した場合は、デフォルトはnullになります。読み取り専用のプロパティとして定義する場合はセッターのみを定義します。読み書き可能なプロパティとして定義する場合はセッター・ゲッターの両方を定義します。

FunctionalSourceSetのサポート

今回のリリースで、 language-base プラグインを適用し FunctionalSourceSet を利用することで、ソースセット(LanguageSourceSet)を model{} ブロック内で追加することが容易になります。 FunctionalSourceSet@Managed タイプのプロパティとして、あるいは ModelSetModelMap の要素として、あるいはトップレベルの要素として利用可能です。

FunctionalSourceSet を用いることで、プラグインの作者はソースのコレクションを languageSourceSet としてモデル化することが可能になります。

トップレベルの要素として FunctionalSourceSet を利用する例

model {
    sources(FunctionalSourceSet)
}

RuleSource を通じて利用する場合

class Rules extends RuleSource {
    @Model
    void functionalSources(FunctionalSourceSet sources) {}
}
apply plugin: Rules

@Managed タイプのプロパティとして利用する場合

@Managed
interface BuildType {
    FunctionalSourceSet getSources()
    FunctionalSourceSet getInputs()
    ModelMap<FunctionalSourceSet> getComponentSources()
}

componentsの内部view

manage modelではないComponentSpecに情報を付加してmanage modelとして利用することが可能になります。これによりプラグインはcomponentsをビルドスクリプトから参照することが可能にできる一方で、内部的な情報は隠蔽することが可能になります。定義したcomponentのデフォルト実装は内部viewを実装する必要があります。

interface LibSpec extends ComponentSpec {
    String getPublicData()
    void setPublicData(String publicData)
}

interface LibSpecInternal extends ComponentSpec {
    String getInternalData()
    void setInternalData(String internalData)
}

class DefaultLibSpec extends BaseComponentSpec implements LibSpec, LibSpecInternal {
    String internalData
    String publicData
}

Componentsは内部viewタイプからruleの対象として利用できます。

class Rules extends RuleSource {
    @Mutate
    void mutateInternal(ModelMap<LibSpecInternal> libSpec) {
        libSpec.each {lib ->
            lib.internalData = 'internal'
        }
    }
}

内部viewで ComponentSpec を継承していないタイプで、componentを対象とするには ComponentSpecContainer.withType から利用します。

@Defaults
void finalize(ModelMap<LibSpec> libSpec) {
    libSpec.withType(LibSpecInternal).all {
        // ...
    }
}

(訳注: LibSpecComponentSpec を継承してないのでは感あるので、もしかしたら、元のドキュメント間違えているっぽい)

Rule based model configuration

古い設定のDSL空間と新しいrule base model設定のDSL空間の互換性が改善されました。

rule basedアプローチで生成されるタスクに依存したい古いモデルで作成されたタスクは tasks.withType(...) から設定することが可能です。

model間の参照

managed modelは木構造のオブジェクトでのみ機能していました。今後はグラフモデルもサポートするようになります。


非推奨になるやつ

sonar プラグインsonar-runner プラグインサードパーティ製の SonarQube プラグインに置き換えてください

Gradle3.0では sonarsonar-runner プラグインは削除される予定です。

非推奨のクラス

たくさんあるので、こっち見て

Eclipseのプロジェクト名を beforeMergedwhenMerged フックで設定すること

このサポートもGradle3.0で削除される予定です。

ビルドが壊れる可能性のあるもの

Groovyを2.4.4にあげました

これまでのGroovy2.3.10からGroovy2.4.4にあげました。

PMDの改善による影響

PMD改善によって、既存のPMDプラグインの設定などに影響があるかもしれません。

CodeNarcを0.24.1にあげました

古いCodeNarcのままにしたい人は、次のように設定してください。

dependencies {
    codenarc 'org.codenarc:CodeNarc:0.17'
}

IDEのプロジェクト名

プロジェクト名をIDEでユニークにするために、IDEメタデータが変更されます。

以下の様なプロジェクト構成では

root/
├── bar
│   └── app
└── foo
    └── app

IDE上で次のようなサブプロジェクト構成になります。

root/
├── bar
│   └── bar-app
└── foo
    └── foo-app

とりま、ここまで。

なお、Javaプラグインでもrule base modelへの変更に伴う変更がありますが、後で訳します(お昼なのでお腹空いている)

amazon.co.jp