mike-neckのブログ

Java or Groovy or Swift or Golang

Gradle-2.9-rc1が11月4日に利用可能になってました #gradle

f:id:mike_neck:20151108133321p:plain

10月1日にGradle2.8-rc1が出たという記事を書いてから、1ヶ月、Gradle2.9-rc1が2015/11/4に出ています。

mike-neck.hatenadiary.com

というわけで、いつもどおりリリースノートの意訳


Gradle TestKitがもっと便利になった

Gradle TestKitがGradle2.6で出てからプラグインのテストが簡単になったわけですが、今回のリリースでもっと便利になりました。TestKitはデバッグクロスバージョンテスト、ビルド成果物を取得することができるようになりました。

より簡単になった機能テスト

Gradle TestKitはプログラム的にGradleビルドを走らせて、プラグインの検証を行うわけですが、テスト対象のクラスなどに対してデバッガーを割り当てることを容易にしました。

Gradleビルドの正確なシミュレーションを提供するために、TestKitは異なるプロセスで実行していました。その結果、デバッガーを割り当てることが非常に困難だったわけです。

今回のリリースによって、テストをテストプロセスと同じプロセスで走らせることが可能になるように改善しました。org.gradle.testkit.debugというシステムプロパティをtrueに設定するか、GradleRunnerwithDebug(true)を呼び出すことでデバック可能になります。

詳しくはTestKitのユーザーガイドを参照してください。

複数のGradleバージョンに対するプラグインのテスト

GradleRunnerを、任意のバージョンのビルドが実行できるようにしました。これで複数のGradleバージョンに対してプラグインが対応できるかテストできます。

GradleRunner#withGradleVersion(String version)を呼び出すことでバージョンの指定を行うことができます。

より詳しくはTestKitの該当箇所をご覧ください。

ビルド成果物の取得

GradleRunnerをプログラムから実行することで、テスト対象のプラグインの成果物を取得できるようになりました。

デフォルトでは、成果物は取得できませんが、forwardOutput()メソッドを実行することで、テスト対象の成果物をGradleRunnerが保持するアウトプットストリームに割り当てることができます。これで成果物の妥当性を目視で検証なんてことをしなくてすみます。

ファイルに書き出すなどの操作が必要であれば、forwardStdOutput(Writer)およびforwardStdError(Writer)メソッドを利用してください。

インクリメンタルビルドのパフォーマンス改善

インクリメンタルビルドのパフォーマンスについて、たぶんGradle2.9はGradle2.8に比べて改善されています。

(数千ファイル)を超えるような大きなビルドにおいては、2.7に比べて70%、2.8に比べて40%改善されています。

インクリメンタルビルドでのup-to-dateチェックをより速くした

Gradleはよりファイルシステムを効率的に扱うことでup-to-dateチェックを高速化しています。ただし、これはGradleをJava7以上で利用した場合に限られます。

includeexcludeパターンのマッチングを改善することでチェックを高速化しました。これはすべてのJavaのバージョンで利用可能です。

ただし、ビルドスクリプトが変更されると、これらのメリットは利用できませんのでご注意ください。

インクリメンタルビルドにてメモリの利用量を減らしました

インクリメンタルビルドで利用するメモリの量を減らしました。内部キャッシュで利用されるファイルパス文字列の重複を削除して、Javaプロジェクトのテストクラスを列挙する際のオーバーヘッド時間を減らすことにより、Gradle2.8に比べて30〜70%のメモリ消費量の削減につながりました。

メモリ利用量の削減はそのまま少ないメモリでのパフォーマンス改善という形で現れます。

これも先ほどと同様、ビルドスクリプトの変更が行われた場合、このメリットは利用できません。

モデルDSLの改善

ビルドスクリプト中で定義した他のルールを入力値として利用可能になりました

ビルドスクリプト中で定義した他のモデル要素の値を入力値として利用することが可能になりました。

model {
  components {
    all {
      targetPlatform = $.platforms.java6
    }
  }
}

上記の例では全てのコンポーネントのターゲットをJava 6に設定しています。すでに構築されたモデル要素S.platforms.java6は次のモデル要素の入力として参照されます。参照される値はすでに不可変な値として確定されているものと、ルール実行機能によって解釈されます。

くわしくはモデルDSLの入力としての利用方法を参照ください。

モデルタイプに対する徹底した検証

管理対象外モデルへのエラーメッセージを改良しました。特にサポートされる型を明確に記述するようにしています。下記の例ではMyModelはビーンにFileInputStreamを用いている不適切な管理対象モデルです。

@Managed
interface MyModel {
  FileInputStream getStream()
  void setStream(FileInputStream stream)
}

エラーメッセージ

A model element of type: 'MyModel' can not be constructed.
Its property 'java.io.FileInputStream stream' can not be constructed
It must be one of:
  - A managed type (annotated with @Managed)
  - A managed collection. A valid managed collection takes the form of ModelSet<T> or ModelMap<T> where 'T' is:
      - A managed type (annotated with @Managed)
  - A scalar collection. A valid scalar collection takes the form of List<T> or Set<T> where 'T' is one of (String, Boolean, Character, Byte, Short, Integer, Float, Long, Double, BigInteger, BigDecimal, File)
  - An unmanaged property (i.e. annotated with @Unmanaged)

LanguageSourceSetFunctionalSourceSetに直接加える事ができるようになりました

LanguageType型のインスタンスである何かしらのLanguageSourceSetをモデルスペース内にあるFunctionalSourceSetに追加することが可能になりました。

これはRuleSourceプラグインから実行できます。

class MyRule extends RuleSource {
  @Model
  void functionalSources(FunctionalSourceSet fss) {
    fss.create(`myJavaSourceSet`, JavaSourceSet) {LanguageSourceSet lss ->
      lss.source.srcDir 'src/main/myJavaSrcSet'
    }
  }
}

apply plugin: MyRule

またはモデルDSLからは

model {
  functionalSources(FunctionalSourceSet) {
    myJavaSourceSet(JavaSourceSet) {
      source {
        srcDir 'src/main/myJavaSrcSet'
      }
    }
  }
}

登録されたLanguageSourceSetの実装はオブジェクト生成時に特定できます。LanguageSourceSetを登録するにはルールアノテーション@LanguageTypeを付与します。

public class JavaLanguageRuleSource extends RuleSource {
  @LanguageType
  public void registerLanguage(LanguageTypeBuilder<JavaSourceSet> builder) {
    builder.setLanguageName("java");
    builder.defaultImplementation(DefaultJavaLanguageSourceSet.class);
  }
}
apply plugin: JavaLanguageRuleSource

注意 : LanguageSourceSetインスタンスFunctionalSourceSetに上記の方法で追加されたとしても、トップレベルソースコンテナの中には追加されません。これについては今後のリリースの中で対応することが決定しています。

Tooling APIがeclispse buildersとnaturesの詳細を提供するようになりました(eclipse関連よくわからんのでなんのこっちゃかわかってない)

Tooling APIのクライアントはEclipseProjectモデルよりEclipseのbuildersとnaturesに対してクエリーをかけることができるようになりました。

EclipseProject#getProjectNatures()およびEclipseProject#getBuildCommands()メソッドによってターゲットプロジェクトのbuildersとnaturesが取得できます。おれらの値にはGradleによって設定されたnaturesやbuildersが含まれる他、eclipseプラグインによってカスタマイズされた情報も含まれます。


修正されたバグ


壊れる可能性のある変更

nativeソフトウェアモデル

  • NativeExecutableBinarySpec.executableFileNativeExecutableBinarySpec.executable.fileによってアクセスするようになります。
  • NativeTestSuiteBinarySpec.executableFileNativeTestSuiteBinarySpec.executable.fileによってアクセスするようになります。

ツールの設定、例えばcppCompiler.argsはGradleの拡張メカニズムに吸収されています。ProcessingToolアクセッサーはNativeBinarySpecに直接実装されており、ExtensionAwareの機能はもう利用できません。これについてはビルドスクリプトの変更が必要ないと思われます。

JavaソフトウェアモデルとJavaプラグインの混合プロジェクト

binariesコンテナはもう通常のプラグインスペースと切り離されており、モデルルール内でのみ参照することが可能になっています。binariesプロジェクト拡張はもうありません。

モデル・ルールDSLの変更

Gradle2.9にて、モデルDSLはより厳密になりました。model{}ブロックのトップレベルに記述することが許されるのはルールの定義だけです。その他の要素(つまり、ifステートメントや何らかの変数など)は利用することができません。

例えば下記のmodel{}ブロックの記述は不可能となります。

model {
  if (someCondition) {
    tasks {
      create("myTask")
    }
  }
}

ただし、ルール内でや任意のステートメントの内部での利用は現在のところ可能です。(訳注:いやな言い方だ、今後使えなくするよみたいで)

up-to-dateチェックの変更

インクリメンタルビルドのパフォーマンス改善の結果、タスクのup-to-dateチェックの方法に変更が入っています。

  • zipTreetarTreeTask.inputsに用いた場合、Gradleはアーカイブを一時的に取り出すことはありません。単純にアーカイブファイルの変更を比較するだけになっています。
  • TaskzipTreetarTreefilterなどとともに利用した場合は、アーカイブが変更されただけでもout-of-date判定されます。
  • Gradleはこれまで、ディレクトリーの中身にかんしてはup-to-dateのチェック対象として考慮しませんでしたが、今後は考慮されます。

外部からの貢献

既知の不具合

今のところない