mike-neckのブログ

Java or Groovy or Swift or Golang

Gradle2.10のリリースノート意訳

久々にパソコンの前に座ったので、リハビリ代わりに先月にリリースされたGradle2.10のリリースノート意訳というか、中途半端に翻訳した。分量が多かったので訳してないところがありますが、引き続き入院してるので、翻訳の続きはありません。

オリジナル(英文)はこちら

新機能と変更

ネイティブコンパイルのパフォーマンス改善

Gradleはインクリメンタルビルドする場合に、すべての入力値、入力ファイル、出力ファイルを必要としている。それによってGradleは入出力ファイルの変更がない場合にタスクをスキップできる。

ネイティブコンパイル系のタスクの場合、ディレクトリー構造も考慮しているため、インクルードされるディレクトリーが多い場合や、ルートディレクトリーがインクルードされている場合にパフォーマンス上の問題が発生した。UP-TO-DATEチェックを速くするために、以下の変更をおこなった。

  • インクルードディレクトリーも入力値として扱う
  • 実際に参照されるヘッダーファイルだけを入力情報として扱う

我々のベンチマークでは非常に大きなプロジェクトのインクリメンタルビルドにおいて多大な改善がみられた。

C++および関連言語では、Gradleはソースファイルをパースしてインクルードされるヘッダーファイルを特定する。Gradleがヘッダーファイルの特定ができない場合は、古いメカニズムを採用する。つまり、マクロによって#include句を定義することは、新しい仕組みを利用できなくなるため、推奨されない。

テストキット依存性の改善

gradleTestKit()を使ってGradleテストキットをテスト時ランタイムクラスパスに組み込むことができる。以前のバージョンではテストキットがGradleのコアに依存しているため、コアクラスもテスト実行時のクラスパスに組み込んでしまっていた。そのため、テストキットにより追加される実行時ライブラリーとユーザーが利用する依存ライブラリーとの間でバージョンのコンフリクトが発生してしまっていた。

Gradleテストキットは実行時クラスパスの汚染を避けるために、テストキットが依存するGradleのコアクラスおよび依存ライブラリーをオールインワンjarの形で利用するように修正する。

buildScript 依存性を図示する新しいタスク

buildEnvironmentタスクによって、buildscriptブロックで宣言された依存性を表示できるようにした。これによって、ビルド時のビルドのデバッグなどがよりやりやすくなる。

チェックスタイルレポートのHTML出力

チェックスタイルタスクがXMLに加えてHTMLの形式でもレポートを出力するように変更した。このHTMLレポートはデフォルトで利用できる。

eclipseプロジェクトにてTooling APIがソースレベルで開示されるように修正

tooling APIJavaソースレベルでAPIを開示するようにして、eclipseプロジェクトでjavaSourceSettingsプロパティから参照できる。Buildshipなどで煩わしかった設定が簡素化される。

Javaソフトウェアモデルにおける依存性管理機能

今回のリリースでJavaソフトウェアモデルに依存性管理の機能が追加された。

コンポーネントレベルでの依存性管理

ソースで依存性を表現するよりもコンポーネントを用いた方がやりやすい。

plugins {
  id 'jvm-component'
}
model {
  components {
    main(JvmLibrarySpec) {
      dependencies {
        library "core"
      }
    }
    core(JvmLibrarySpec) {
    }
  }
}

外部依存性管理

ソフトウェアモデルでの外部依存性管理も利用可能になった。

apply plugin: 'jvm-component'
repositories {
  jcenter()
}
model {
  components {
    main (JvmLibrarySpec) {
      dependencies {
        // 外部依存性はmoduleでもgroupでも始められる
        group 'com.acme' module 'artifact' version '1.0'
        module 'artifact' group 'com.acme' version '1.0'
        // ショートハンドスタイルも利用可能
        module 'com.acme:artifact:1.42'
      }
    }
  }
}

ソフトウェアモデルにおけるDSLの改善

モデル空間のDSLを修正した。

ネストしたルール

ModelMapの生成や設定ではネストしたルールを利用できる。

model {
  components {
    myLib { … }
    test {
      // `myLib`を入力値として利用する。
      // このコードが実行されると`test`が完全に定義されて、model 以外からは変更できなくなる。
      targetPlatform = $.components.myLib.targetPlatform
    }
  }
}

tasksModelMapであるため、タスクは他のタスクを使って定義することができるようになった。

model {
  tasks {
    jar { … }
    dist(Zip) {
      // `jar`タスクを入力として利用する
      // この定義はモデル空間で定義されて、model 以外からは変更できない
      def jar = $.tasks.jar
      from jar.output
      into "someDir"
    }
  }
}

このようなModelMapメソッドを利用した定義も可能である。

model {
  components {
    all {
      // すべてのcomponentに適用される定義
    }
    withType(JvmLibrarySpec) {
      // JvmLibrarySpec型のコンポーネントに適用される定義
    }
  }
}
@Managedが付与された型のオブジェクトに対するプロパティの設定

@Managedが付与された型のオブジェクトが保持するプロパティはネストしたクロージャーで定義することができるようになった

model {
  components {
  myLib {
      sources {
        // `myLib.sources`に対する定義
      }
      binaries {
        // `myLib.binaries`に対する定義
      }
    }
  }
}

@Managedが付与された型のオブジェクト、あるいはModelMap<T>インスタンス、あるいはModelSet<T>インスタンス、これらのプロパティにてこの変更が利用できる。ネストされたクロージャーではネストしたルールを定義できないこと、および更にクロージャーがネストした場合にすぐに実行されてしまう(実行を遅らせることができない)ことの二点に注意が必要である。この点については次のGradleのリリースで改善される予定である。

より詳しくはモデルDSLを参考。

スカラー型のプロパティがより簡単になった

モデルDSLにて自動的にスカラー型の自動的な規約がサポートされた。具体的にはStringスカラー型の値として利用できるように。

enum FailType {
  FAIL_BUILD,
  WARNING
}

@Managed
interface CoverageConfiguration {
  double getMinClassCoverage()
  void setMinClassCoverage(double minCoverage)

  double getMinPackageCoverage()
  void setMinPackageCoverage(double minCoverage)

  FailType getFailType()
  void setFailType(FailType failType)

  File getReportTemplateDir()
  void setReportTemplateDir(File file)
}

model {
  coverage {
    minClassCoverage = '0.7' // `String`で`double`の値を設定可能
    minPackageCoverage = 1L // `long`で`double`の値を設定可能
    failType = 'WARNING' // `String`を`Enum`の代わりに利用可能
    templateReportDir = 'src/templates/coverage' // `File`オブジェクトをプロジェクトからの相対パスで作成可能
  }
}

ソフトウェアモデルでのプラグイン開発のサポート

今回のリリースにはプラグイン開発者がソフトウェアモデルを拡張することを可能としている。

LanguageSourceSetモデルへのサポート

今回のリリースでモデル空間の任意の箇所にソースセット(LanguageSourceSetのサブタイプ)を追加可能にしている。@Managedモデル型のプロパティとして、あるいはModelMap<T>ModelSet<T>の値(Tの型)として、あるいはモデル要素のトップレベル要素としてLanguageSourceSet型を追加可能になった。

バイナリーおよびコンポーネント

BinarySpec型もしくはComponentSpec型を継承した型を、メソッドの実装なしに、@Managedアノテーションを付与することで作成することができるようになった。同様にLibrarySpec型とApplicationSpec型も拡張できるようになっている。

@Managed
interface SampleLibrarySpec extends LibrarySpec {
  String getPublicData()
  void setPublicData(String publicData)
}

class RegisterComponentRules extends RuleSource {
  @ComponentType
  void register(ComponentTypeBuilder<SampleLibrarySpec> builder) {
  }
}
apply plugin: RegisterComponentRules

model {
  components {
    sampleLib(SampleLibrarySpec) {
      publicData = "public"
    }
  }
}
バイナリー型、コンポーネント型用内部モデル
@Managed
interface MyJarBinarySpecInternal extends JarBinarySpec {
    String getInternal()
    void setInternal(String internal)
}

class CustomPlugin extends RuleSource {
    @BinaryType
    public void register(BinaryTypeBuilder<JarBinarySpec> builder) {
        builder.internalView(MyJarBinarySpecInternal)
    }

    @Mutate
    void mutateInternal(ModelMap<MyJarBinarySpecInternal> binaries) {
        // ...
    }
}

apply plugin: "jvm-component"

model {
    components {
        myComponent(JvmLibrarySpec) {
            binaries.withType(MyJarBinarySpecInternal) { binary ->
                binary.internal = "..."
            }
        }
    }
}
// This won't work:
model {
    binaries.withType(MyJarBinarySpecInternal) {
        // ...
    }
}
管理対象外のバイナリー型およびコンポーネント型のデフォルト実装

デフォルト実装をバイナリー型およびコンポーネント型に与えることが可能になった。

interface MyBaseBinarySpec extends BinarySpec {}

class MyBaseBinarySpecImpl extends BaseBinarySpec implements MyBaseBinarySpec {}

class BasePlugin extends RuleSource {
    @ComponentType
    public void registerMyBaseBinarySpec(ComponentTypeBuilder<MyBaseBinarySpec> builder) {
        builder.defaultImplementation(MyBaseBinarySpecImpl.class);
    }
}

@Managed
interface MyCustomBinarySpec extends BaseBinarySpec {
    // Add some further managed properties
}

class CustomPlugin extends RuleSource {
    @ComponentType
    public void registerMyCustomBinarySpec(ComponentTypeBuilder<MyCustomBinarySpec> builder) {
        // No default implementation required
    }
}
管理対象外のバイナリー型、コンポーネント型用内部モデル
/**
 * Documented public type exposed by the plugin
 */
interface MyBinarySpec extends BinarySpec {
    // Functionality exposed to the public
}

// Undocumented internal type used by the plugin itself only
interface MyBinarySpecInternal extends MyBinarySpec {
    String getInternalData();
    void setInternalData(String internalData);
}

class MyBinarySpecImpl implements MyBinarySpecInternal {
    private String internalData;
    String getInternalData() { return internalData; }
    void setInternalData(String internalData) { this.internalData = internalData; }
}

class MyBinarySpecPlugin extends RuleSource {
    @BinaryType
    public void registerMyBinarySpec(BinaryTypeBuilder<MyBinarySpec> builder) {
        builder.defaultImplementation(MyBinarySpecImpl.class);
        builder.internalView(MyBinarySpecInternal.class);
    }
}

修正されたイシュー


問題が発生する可能性のある修正

テストキットの実行時クラスパス

コンパイルに用いるヘッダーファイル

DSLのモデル空間の変更

ソフトウェアモデルの修正

Javaソフトウェアモデルの修正

ネイティブモデルの修正

既知の問題