Eclipse、Gradle:モジュールシステムに対応させるまとめ

Eclipse 2019-06上でgradle 5.5を使って以下を行いたい。

  • モジュール開発を行いたい。
  • GradleのEclipseプラグインを使用して、Eclipseのクラスパス等を自動で設定させたい。
  • JUnit等のユニットテストを作成して実行したい。
  • モジュールとしてコンパイルし、モジュール化jarファイルを作成したい。

この課題について、既に一部は以下に書いた。

これらをまとめ、モジュールとしてのコンパイル方法を見ていく。

GradleのEclipseプラグインの動作変更

GradleのEclipseプラグインは、起動すればEclipseの環境を作成してくれる便利なものだ。自動的に.project, .classpathファイル等を生成してくれる。しかし、Gradle 5.5に付属のものでも未だにモジュールには対応していない。

ライブラリjarをモジュールパスに入れる

デフォルトではdependenciesに指定されたライブラリjarをクラスパスに入れてしまうため、この動作を変更しなければならない。これは既に GradleのEclipseプラグインにモジュール対応させるに記述した。

Gradleでコンパイラフラグを指定する

次にGradleでのコンパイル時にも特別な操作が必要になる。Eclipse上ではモジュールパスに格納されていても、Gradle側の解釈はまた別で、そのままだと「クラスパスにある」と解釈されてしまうからだ。

を見てみると、

compileJava {
  doFirst {
    options.compilerArgs = [
      "--module-path", classpath.asPath
    ]
    classpath = files()
  }
}

という指定が必要のようだ。この意味としては以下だろう。

  • 現在のclasspathを展開して、–module-path引数として指定する。
    「–module-path A;B;C」といった具合だ。
  • classpathを空にする。
    classpathがそのままだと、これは「クラスパス」として指定されてしまうので、0個にしておく。

まとめ

以上をまとめるとbuild.gradleは以下のようになる。

apply plugin: 'java'
apply plugin: 'eclipse'

sourceSets {
  main {
    java {
      srcDir 'src'
    }
  }
  test {
    java {
      srcDir 'srcTest'
    }
  }  
}


repositories {
  jcenter()
}

compileJava {
  doFirst {
    options.compilerArgs = [
      "--module-path", classpath.asPath
    ]
    classpath = files()
  }
}


dependencies {
  compile group: 'com.google.inject', name: 'guice', version: '4.0'
  testCompile group: 'junit', name: 'junit', version: '4.12'
}

eclipse {
  classpath {
    file {
      whenMerged {
        entries.findAll { isModule(it) }.each { //(1)
          it.entryAttributes['module'] = 'true'
        }
        entries.findAll { isSource(it) && isTestScope(it) }.each {
          it.entryAttributes['test'] = 'true'
        }
        entries.findAll { isLibrary(it) && isTestScope(it) }.each {
          it.entryAttributes['test'] = 'true'
        }
      }
    }
    defaultOutputDir = file('build')
    downloadSources = true
    downloadJavadoc = true
  }
}

boolean isLibrary(entry) { return entry.properties.kind.equals('lib') }
boolean isTestScope(entry) { return entry.entryAttributes.get('gradle_used_by_scope').equals('test'); }
boolean isModule(entry) { isLibrary(entry) && !isTestScope(entry); }
boolean isSource(entry) { return entry.properties.kind.equals('src'); }

これを「gradle cleanEclipse eclipse」で動作させる。

ビルドパスのソースは次のように設定される。

ライブラリはテスト用のものだけクラスパスに登録される。

そして、compileJavaを行うと、適切にmodule-pathが使われてコンパイルされる。