
私は Java コードを書くのに Eclipse を使っています。以前はプロジェクト形式として標準の Java Project を選択していましたが、 現在は Gradle プロジェクト形式を選択するようにしています。
Gradle の素晴らしさを知ったのは Android アプリケーションの開発で Android Studio に触れた折でした (Android Studio のプロジェクト形式は Gradle プロジェクト形式だったのです)。以来、 Android 以外の Java アプリケーション開発 (Web サーバーアプリや JavaFX アプリ) でも Gradle プロジェクト形式を採用するようになりました。
今回は Gradle プロジェクトの雛形をカスタマイズする方法を紹介します。
それでも私はEclipseを続けるよ!
ちなみに、 Android Studio は IntelliJ IDEA がベースになっています。Android 以外の Java アプリケーション開発環境も Eclipse から IntelliJ IDEA に変えてしまったほうが楽かな?と考えたりもしたのですが、 悩んだ末に、 長年愛用している Eclipse を使い続けることにしました。
IntelliJ IDEA に乗り換えなかった理由は製品が有償だったことです。IntelliJ IDEA には無償で使えるオープンソースの Community 版もあります。Community 版は個人利用だけでなく商用利用も認められています。それでも、 私は、 有償の Ultimate 版と無償の Community 版の 2 つが存在していることが気になりました。IntelliJ IDEA Community 版では一部の機能が使えないという差別化が図られています。それがどうしても好きになれなかったのです。
Buildship
話を戻しましょう。
2015 年にリリースされた Eclipse 4.5 MARS から Buildship という Gradle プラグインが標準で含まれるようになりました。すぐに Gradle プロジェクトを使い始めることができます。
Eclipse の標準プロジェクト形式 (Java Project) を作成する場合は New → Java Project を選択しますよね。

Gradle プロジェクト形式を作成する場合は Java Project ではなく Project... を選択します。

ウィザードが表示されるので、 Gradle Project を選択して Next > を押します。

ウィザードを最後まで進めていくと、 プロジェクトの雛形が自動的に作成されます。

この自動的に作成される Gradle プロジェクトは私の好みではないです。
build.gradleで指定されているプラグインがjava-libraryになっている。ライブラリよりアプリケーションを開発することのほうが多いのでjavaになっていて欲しい。build.gradleの依存ライブラリにguavaが入っている。Google 推しやめてください。サンプルとして初期配置されている
Library.javaクラス、 すぐに消してしまうだけなので、 最初からないほうがいいです。testフォルダーも要らないです。(こんなこと言ったらテストコード書いてないのか!と怒られそうですが…。)
もっと自分好みの雛形を出力して欲しい! そう思いますよね?
Gradleプロジェクトの雛形をカスタマイズする
というわけで、 自動作成される Gradle プロジェクトの雛形をカスタマイズすることにしました。
Gradle プロジェクトの雛形は Eclipse の Buildship プラグインが出力しているわけではなく、 Gradle 自身が出力しています。Buildship を使わずにコマンドラインで gradle init を実行した場合も同じ雛形が出力されます。Buildship が特別なことをしているわけではないので、 Gradle 自体の機能でプロジェクトの雛形をカスタマイズする方法を考えます。
init.gradle
Gradle にはビルドプロセスをカスタマイズするための init.gradle という仕組みが用意されています。ユーザーフォルダー直下の .gradle フォルダーに init.gradle というファイル名で Gradle ファイルを置いておくと、 ビルドプロセスの前に init.gradle が実行されるようになります。
- Windows の場合、 配置パスは
%USERPROFILE%\.gradle\init.gradleになります。
この仕組みを使って、 あらかじめ用意しておいた雛形ファイル群がプロジェクトにコピーされるようにします。
init.gradlebuildFinished {
Task init = rootProject.tasks.findByName('init')
if(init && init.state.executed && !init.state.skipped) {
if(init.type.contains('java')) {
//delete files
["src/test", "src/main/java/${rootProject.name}"]
.each {
println "delete ${it}"
delete rootProject.file(it)
}
}
//copy files
copy {
from "templates/${init.type}"
into rootProject.file('.')
}
}
if(rootProject.tasks.findByName('nothing')) {
copy {
from "templates/.gitignore"
into rootProject.file('.')
}
}
}
私は、 このような init.gradle スクリプトを用意しました。
init.gradle はビルドプロセスで常に実行されることに注意してください。新規プロジェクトの作成時 (init タスク実行時) だけ雛形のコピーがおこなわれるように if 文の条件を init.state.executed と !init.state.skipped としています。
この init.gradle スクリプトでは以下の 3 つの処理をおこなっています。
javaプロジェクトだったらtestフォルダーを削除します。(怒らないで!)init.gradleと同じ場所にあるtemplates/${init.type}フォルダー内のファイルをプロジェクトにコピーします。${init.type}の部分はgradle initの--type引数で指定された値 (プロジェクトのタイプ名) に置き換えられます。Buildship からプロジェクトを作成した場合はjava-libraryが指定されるので、templates/java-library配下のファイルがプロジェクトにコピーされます。nothingタスクが実行された場合にtemplates/.gitignoreをプロジェクトにコピーします。この処理の詳細については後述します。
templates/java-library フォルダーには build.gradle、 javadoc.css、 lib を置きました。
- %USERPROFILE%
- .gradle
- init.gradle
- templates
- .gitignore
- java-library
- build.gradle
- javadoc.css
- lib
- .gradle
私が雛形として使っている build.gradle がこれです。
build.gradleapply plugin: 'java'
def defaultEncoding = 'UTF-8'
tasks.withType(AbstractCompile).each { it.options.encoding = defaultEncoding }
tasks.withType(GroovyCompile).each { it.groovyOptions.encoding = defaultEncoding }
javadoc {
options.charSet = defaultEncoding
options.encoding = defaultEncoding
options.stylesheetFile = new File(rootDir, 'javadoc.css')
}
repositories {
jcenter()
}
dependencies {
compile fileTree(dir: 'lib',
includes: ['**/*.jar'],
excludes: ['**/*-sources.jar', '**/*-javadoc.jar'])
}
文字コードの指定、 Javadoc スタイルシートの指定、 lib フォルダー内の JAR ファイルを参照ライブラリとして追加するようにしています。
init.gradle と雛形ファイル一式は以下のリンクからダウンロードできます。
BuildshipからGradleプロジェクトを作成してみる
ユーザーフォルダー直下の .gradle フォルダーに init.gradle と templates をコピーした状態で、 Eclipse で Gradle プロジェクトを新規作成してみます。

今度は以下のような構成でプロジェクトが作成されました。

testフォルダーやLibrary.javaが存在していない。javadoc.cssが配置されている。build.gradleの中身がカスタマイズ版に置き換わっている。.gitignoreがカスタマイズ版に置き換わっている。(Eclipse のエクスプローラービューには表示されていません。)
これで、 Gradle プロジェクト新規作成後の定型的なカスタマイズ作業を減らすことができますね。ぜひ、 自分好みのプロジェクトの雛形にカスタマイズしてみてください!
.gitignore
- Git を使っていない人は読み飛ばして構いません。
.gitigonore は Git リポジトリーへの登録を除外するファイルやフォルダーを記述するリストです。このファイルに Eclipse 固有の管理ファイル .classpath、 .project、 .settings を追加しておけば、 Git リポジトリーに Eclipse 固有の管理ファイルが格納されることはなくなり、 純粋な Gradle プロジェクトのみを Git リポジトリーに格納することができます。
Eclipse の Buildship プラグインはとても賢く build.gradle の dependencies 設定から自動的に Eclipse のライブラリ参照を構成してくれるので、 Eclipse のプロジェクト管理ファイルを大事に守る必要はありません。Buildship プラグインなら、 いつでも Gradle プロジェクトから Eclipse のプロジェクトを再構成できます。
とても便利な .gitignore ファイルですが、 このファイルは Gradle でも特別扱いされており、 templates/java-library に .gitignore を配置しておいても新規プロジェクトにコピーされません。
なぜかというと、 init.gradle の buildFinished リスナーで .gitignore をコピーしても、 その後で Gradle によって .gitignore が勝手に上書きされてしまうからです。この強制上書きは GitIgnoreGenerator というクラスでおこなわれています。
GitIgnoreGenerator.java のソースコード、 結構ひどいコードだと思います。
GitIgnoreGenerator.javapublic class GitIgnoreGenerator implements BuildContentGenerator {
@Override
public void generate(InitSettings settings) {
File file = fileResolver.resolve(".gitignore");
try {
PrintWriter writer = new PrintWriter(new FileWriter(file));
try {
writer.println("# Ignore Gradle project-specific cache directory");
writer.println(".gradle");
writer.println();
writer.println("# Ignore Gradle build output directory");
writer.println("build");
} finally {
writer.close();
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
外部リソースを元に .gitignore を作るのではなく、 ソースコードに .gitignore に書き込む中身がハードコーディングされているという…。さらに、 この BuildContentGenerator インターフェースの呼び出し工程も追いかけてみましたが、 ファクトリーパターンになっているわけでもなく、 GitIgnoreGenerator の振る舞いを抑制したり差し替えたりするのは困難に見えました。
Gradle のエンジニアさんでも、 こんなテキトーなコード書くんですね…。
というわけで、 gradle init でプロジェクトを新規作成したときに、 独自の .gitignore に置き換えることは (通常の方法では) できませんでした。
しかし、 幸運なことに Eclipse から Buildship で Gradle プロジェクトを作成した場合は gradle init だけでなく、 そのあとで gradle nothing というビルドプロセスも呼び出されるようなのです。
そこで init.gradle に以下のコードを追加しました。
if(rootProject.tasks.findByName('nothing')) {
copy {
from "templates/.gitignore"
into rootProject.file('.')
}
}
このコードは前述した GitIgnoreGenerator よりも後で呼び出されるため、 Gradle によって強制上書きされた .gitignore をさらに上書きできます。上書き返し大成功です。
この templates/.gitignore のコピーは Buildship から Gradle プロジェクトを作成した場合のみ有効です。コマンドラインから gradle init を実行した場合は、 デフォルトの .gitignore のままになってしまうのでご注意ください。
gradle init で自動作成されるプロジェクトの雛形をカスタマイズする方法の紹介は以上です。