Gradle:プロジェクト間の共通処理パターンを実現する
複数のプロジェクトがあり、それぞれにbuild.gradleを作成するわけだが、ほとんど同じことを毎度毎度書かなくてはいけないのは辛い。なんとか簡単に済ませる方法は無いものか。
処理の例
例えば、eclipseプラグインでecipseの.project、.classpathをgradleに作成させるものとする。さらにその制御を細かくしたいのだが、複数プロジェクトでほとんど同じだ。例えば、以下のように記述する。
apply plugin: 'eclipse'
....
eclipse {
project {
....
file {
whenMerged {
....
}
}
}
classpath {
defaultOutputDir = file('output')
downloadSources = true
file {
whenMerged { cp->
....
}
}
}
}
結論から言えば、以下のようにしたいのである。新たなメソッドeclipseExを導入し、そのクロージャの中でプロジェクトごとに異なる部分だけを記述したい。
さらにこれをcommon.gradleといった共通ファイルを通して行いたい。
apply from: 'common.gradle'
....
eclipseEx {
output = file('output2')
extraSources = [ 'src_test' ]
....
}
これをどうするか?
実際のコード
以下のようになる。
build.gradle
apply from: 'common.gradle'
apply plugin: 'java'
apply plugin: EclipseExPlugin
repositories {
mavenCentral()
}
sourceSets {
main {
java {
srcDir 'src'
}
resources {
srcDir 'src'
}
}
}
dependencies {
compile('javax.inject:javax.inject:1')
compile('com.google.inject:guice:4.0')
}
eclipseEx {
output = file('output')
extraProjects = ['/gwtcenter_bwidget']
extraSources = ['src_test'];
}
common.gradle
ext.EclipseExPlugin = EclipseExPlugin
class EclipseExPlugin implements Plugin<Project> {
def void apply(Project project) {
project.apply(plugin:'eclipse')
project.convention.plugins.eclipseExConvention = new EclipseExConvension(project)
}
}
/* EclipseExのコンベンション */
class EclipseExConvension {
/* プロジェクト */
Project project
/* 出力先 */
File output;
/* 追加プロジェクトリスト */
List extraProjects;
/* 追加ソースフォルダリスト */
List extraSources;
/* GWT用natureを追加 */
boolean gwtNature;
EclipseExConvension(project) {
this.project = project
}
def eclipseEx(Closure closure) {
closure.delegate = this
closure()
project.eclipse {
project {
gwtNatureBuildCommand(delegate)
file {
whenMerged {
addCommonGradle(delegate)
}
}
}
classpath {
defaultOutputDir = output
downloadSources = true
file {
whenMerged { cp->
removeOutputFoldersForSourceFolders(cp)
removeDuplicatedSources(cp)
removeAllExcludes(cp)
appendExtraSources(cp)
appendExtraProjects(cp)
sortProjectEntries(cp)
}
}
}
}
} // eclipseEx
/* GWT用のNature、ビルドコマンドを追加 */
def gwtNatureBuildCommand(p) {
if (!gwtNature) return;
p.natures 'org.eclipse.wst.common.project.facet.core.nature'
p.buildCommand 'org.eclipse.wst.common.project.facet.core.builder'
p.buildCommand 'com.gwtplugins.gdt.eclipse.core.webAppProjectValidator'
}
/* common.gradleへの参照を追加 */
def addCommonGradle(proj) {
proj.linkedResources.add(new org.gradle.plugins.ide.eclipse.model.Link(
'common.gradle', '1', 'J:/OwnCloud/CryptoFiles/gradle/common.gradle', null));
}
/* ソースフォルダの出力指定を削除する。こうしないと、フォースフォルダごとに別のフォルダに出力されてしまう */
def removeOutputFoldersForSourceFolders(cp) {
cp.entries.findAll{ it.kind == 'src' }.each{
it.output = null
}
}
/* ソースフォルダが重複してしまうことがあるので重複分を削除する */
def removeDuplicatedSources(cp) {
def newList = new ArrayList()
def duplicated = new HashSet()
cp.entries.each { e->
if (e.kind != 'src') {
newList.add(e);
return
}
if (duplicated.contains(e.path))
return;
newList.add(e);
duplicated.add(e.path);
}
cp.entries = newList;
}
/* 追加のソースフォルダ */
def appendExtraSources(cp) {
if (extraSources == null) return;
extraSources.each {
cp.entries.add(new org.gradle.plugins.ide.eclipse.model.SourceFolder(it, null))
}
}
/* 追加のプロジェクト */
def appendExtraProjects(cp) {
if (extraProjects == null) return;
extraProjects.each {
cp.entries.add(
new org.gradle.plugins.ide.eclipse.model.SourceFolder(it, null)
)
}
}
// srcDir 'src'; exclude '**/*Test.java';のexcludeを削除する。
// IDE上ではテストユニットが見えていて欲しい
def removeAllExcludes(cp) {
cp.entries.findAll{ it.kind == 'src' }.each{
it.setExcludes(new ArrayList())
}
}
/*
ライブラリ他をアルファベット順にソートする。アルファベット順でないと非常に見つけにくい
これは単純にEclipseの.projectファイルの内容をソートするもの。追加・削除等は行わない。
*/
def sortProjectEntries(cp) {
Map srcMap = new HashMap();
Map libMap = new HashMap();
List others = new ArrayList();
cp.entries.each {
if (it.kind == 'lib') {
String path = it.path;
int index = path.lastIndexOf('/')
libMap.put(path.substring(index + 1), it);
} else if (it.kind == 'src') {
srcMap.put(it.path, it);
} else {
others.add(it);
}
}
def newList = new ArrayList();
// ソースフォルダをソートして入れる
srcMap.keySet().sort({ a, b -> a.compareToIgnoreCase b }).each{
newList.add(srcMap.get(it))
}
// ライブラリ以外を入れる
newList.addAll(others);
// ライブラリをソートして入れる
libMap.keySet().sort({ a, b -> a.compareToIgnoreCase b }).each{
newList.add(libMap.get(it))
}
cp.entries = newList
}
}
ディスカッション
コメント一覧
まだ、コメントがありません