1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

grx :「Gradleのタスク定義のあれこれ」のサンプルコードを実行するためのシェルスクリプト

Last updated at Posted at 2024-03-31

@opengl-8080 さんが5年前にQiitaに投稿したGraleに関する記事3本を読んだ。

わたしはGradleを何年も使っているけれど、とりあえず動いたで立ち止まっていた。実はbuild.gradleがよく分かっていなかった。今回、@opengl-8080 さんの記事を読んで目から鱗が三枚ぐらい落ちた。

解決したい問題

「Gradleのタスクの定義のあれこれ」 (これを以下で「あれこれ」と略記する)を読んでいて困ったことがありました。「あれこれ」にはGradleビルドスクリプトのサンプルが(なんとまあ)62個掲載されていた。わたしはサンプルコードを見ながらエディタでコードを書きGradleで実行してどのように動作するかを確かめた。「あれこれ」はそれらサンプルに build.gradle という同一のラベルを付けて掲載していた。しかし中身の違う62個のビルドスクリプトを同じ build.gradle という名でファイル保存することはできない。ひとつひとつに固有のファイル名を付けて保存するしかない。だからわたしはビルドスクリプトをこんなふうに作った。

ファイル名: 25_fileTree.gradle

task foo {
    doFirst {
        FileTree tree = fileTree("src")
        tree.each { println it }
    }
}

この調子でビルドスクリプトを作っていったら、最終的に以下のファイルができた。

01_task_foo.gradle
02_doFist_doLast.gradle
03_configure_task_with_closure.gradle  
04_build_lifecycle.gradle  
04_task_dependsOn_other.gradle  
05_reference_to_task.gradle  
06_task_dependsOn_other.gradle  
07_task_runs_only_once.gradle  
08_dependsOn_inside_configuration_block.gradle  
09_dependsOn_as_task_argument.gradle  
10_sequence_control_not_good.gradle  
11_sequence_control_by_dependsOn.gradle  
12_sequence_control_mustRunAfter.gradle  
13_finalizedBy.gradle  
14_onlyIf.gradle  
15_onlyIf_with_finalizedBy.gradle  
21_file.gradle  
22_files.gradle  
23_files_asPath.gradle  
24_files_filter.gradle  
25_fileTree.gradle  
26_fileTree_include_as_closure.gradle  
27_fileTree_include_as_Map.gradle  
31_task_without_inputs_outputs.gradle  
32_task_with_inputs_outputs.gradle  
33_task_inputs_declaration.gradle  
34_task_outputs_declaration.gradle  
41_tasks_addRule.gradle  
42_clean_rule.gradle  
51_custom_task_within_buildscript.gradle  
52_custom_task_input.gradle  
53_custom_task_input_as_Object.gradle  
54_annotations_for_Input_Output.gradle  
61_Copy_task.gradle  
62_Copy_from_Object.gradle  
63_Copy_from_Object_Closure.gradle  
64_Copy_into_Object.gradle  
65_Copy_include.gradle  
66_Copy_exclude.gradle  
67_Copy_rename_closure.gradle  
68_Copy_rename_String_String.gradle  
69_copy_method.gradle  
71_Delete_task.gradle  
72_Delete_fileTree.gradle  
73_delete_method_of_Project.gradle  
74_Sync_task.gradle  
75_Sync_preserve.gradle  
76_sync_method_of_Project.gradle  
77_Exec_task.gradle  
78_exec_method_of_Project.gradle  
79_Zip_task.gradle  
80_zipTree.gradle  
81_unzip.gradle  
85_buildSrc.gradle  
86_Plugin.gradle  
87_Plugin_with_Extension.gradle  
88_Plugin_with_Extension_configured_by_closure.gradle  
89_Plugin_with_Extension_inputFile=null_outputDir=null.gradle  
90_Plugin_with_Extension_using_Property.gradle  
91_CustomCopyTask.gradle  

さて、これらビルドスクリプトをgradleで実行したいが、コマンドラインでどのように入力するか?

ひとつのやり方は --build-file オプションでファイル名を指定すること。たとえばコマンドラインで次のようにキー入力すればいい。

$ ./gradlew -b 25_fileTree.gradle foo
Starting a Gradle Daemon (subsequent builds will be faster)

> Task :foo
/Users/.../src/main/resources/hoge/hoge.xml
/Users/.../src/main/resources/main.xml
/Users/.../src/main/resources/fuga/fuga.xml
/Users/.../src/main/java/hoge/Hoge.java
/Users/.../src/main/java/fuga/Fuga.java
/Users/.../src/main/java/Main.java

これでちゃんと動きました。でも、繰り返しgradleを起動するたびに長いファイル名をキー入力するのが面倒だった。なんとかしたい。

解決方法

シェルスクリプト grx を作りました。

ファイル名: grx

#!/bin/sh

#f='01_task_foo.gradle'
#f='02_doFist_doLast.gradle'
#f='03_configure_task_with_closure.gradle'
#f='04_build_lifecycle.gradle'
#f='05_reference_to_task.gradle'
#f='06_task_dependsOn_other.gradle'
#f='07_task_runs_only_once.gradle'
#f='08_dependsOn_inside_configuration_block.gradle'
#f='09_dependsOn_as_task_argument.gradle'
#f='10_sequence_control_not_good.gradle'
#f='11_sequence_control_by_dependsOn.gradle'
#f='12_sequence_control_mustRunAfter.gradle'
#f='13_finalizedBy.gradle'
#f='14_onlyIf.gradle'
#f='15_onlyIf_with_finalizedBy.gradle'
#f='21_file.gradle'
#f='22_files.gradle'
#f='23_files_asPath.gradle'
#f='24_files_filter.gradle'

f='25_fileTree.gradle'

#f='26_fileTree_include_as_closure.gradle'
#f='27_fileTree_include_as_Map.gradle'
#f='31_task_without_inputs_outputs.gradle'
#f='32_task_with_inputs_outputs.gradle'
#f='33_task_inputs_declaration.gradle'
#f='34_task_outputs_declaration.gradle'
#f='41_tasks_addRule.gradle'
#f='42_clean_rule.gradle'
#f='51_custom_task_within_buildscript.gradle'
#f='52_custom_task_input.gradle'
#f='53_custom_task_input_as_Object.gradle'
#f='54_annotations_for_Input_Output.gradle'
#f='61_Copy_task.gradle'
#f='62_Copy_from_Object.gradle'
#f='63_Copy_from_Object_Closure.gradle'
#f='64_Copy_into_Object.gradle'
#f='65_Copy_include.gradle'
#f='66_Copy_exclude.gradle'
#f='67_Copy_rename_closure.gradle'
#f='68_Copy_rename_String_String.gradle'
#f='69_copy_method.gradle'
#f='71_Delete_task.gradle'
#f='72_Delete_fileTree.gradle'
#f='73_delete_method_of_Project.gradle'
#f='74_Sync_task.gradle'
#f='75_Sync_preserve.gradle'
#f='76_sync_method_of_Project.gradle'
#f='77_Exec_task.gradle'
#f='78_exec_method_of_Project.gradle'
#f='79_Zip_task.gradle'
#f='80_zipTree.gradle'
#f='81_unzip.gradle'
#f='85_buildSrc.gradle'
#f='86_Plugin.gradle'
#f='87_Plugin_with_Extension.gradle'
#f='88_Plugin_with_Extension_configured_by_closure.gradle'
#f='89_Plugin_with_Extension_inputFile=null_outputDir=null.gradle'
#f='90_Plugin_with_Extension_using_Property.gradle'
#f='91_CustomCopyTask.gradle'

cp $f build.gradle
./gradlew -q $1 $2 $3 $4 $5 $6 $7 $8 $9

grx が何をしているかは一目瞭然です。変数fが示すファイルの中身を build.gradle に上書きしてから gradlew コマンドを起動する。それだけ。コマンドラインでこんなふうに grx を利用します。

$ grx foo
Starting a Gradle Daemon (subsequent builds will be faster)

> Task :foo
/Users/.../src/main/resources/hoge/hoge.xml
...

grx がどのビルドファイルを実行するか?それは grx のコードを都度修正して切り替えます。シェル変数 f にファイル名を代入する行を取り替える。grx のコードにビルドファイルの正しいファイル名をいちど列挙してしまえば、あとは行の先頭のコメント記号 # を付けたり外したりすればいい。

わたしの意見

grx を作って何が嬉しかったか。Gradleのビルド・スクリプトのファイル名を build.gradle ではない任意の名前にしても構わないという自由が得られたこと。

というのも、Gradleのビルド・ファイルの名前は build.gradle しかあり得ないという思い込みがわたしにはあったからだ。この思い込みのせいでビルド・ファイルを2つ以上作ることをためらった。1個の build.gradle ファイルの中に foo タスクを作った。次に foo2 タスクを作った。次に foo3 タスクを作り、 foo4 タスクを作った。さらに foo5 タスクを作った。タスク名が重複しないよう気配りしながら。そうこうするうちに build.gradle ファイルは膨らんでぐちゃぐちゃになり、とても読めたものでなくなった。こんなことしなきゃいけないGradleってどうなのよとムカついた。このやり方でGradleを学習するのはわたしにとって苦痛だった。

ふと、わたしは grx を思いついた。grxがあれば小分けにしたビルド・スクリプトをいくらでも書くことができる。小分けされた個々のスクリプトが同じタスク名(たとえばfoo)を繰り返し使っていても問題ない。grxが小分けされたスクリプトをひとつ拾ってbuild.gradleを生成するから実行時にタスク名の重複は起きない。また、ファイル名が 89_Plugin_with_Extension_inputFile=null_outputDir=null.gradle のように長くても問題ないという点もナイスだ。ファイル名をシェル・スクリプトの中に一度書いておけばよくて、コマンドラインで長いファイル名を繰り返しタイプする手間を無くすることができる。grxのおかげでGradleビルド・スクリプトをたくさん書くことが苦でなくなった。むしろ楽しくなった。

もっとも、Javaアプリケーションやライブラリを開発することを目的とするプロジェクトにおいてGradleビルド・スクリプトを沢山たくさん書く必要などない。build.gradleをひとつ書いておしまいだ。ところがGradleそのものを学ぼうと志してチュートリアルを読むことを想像してごらんなさい。たとえば

とか。この記事にはbuild.gradleのexampleが48本も掲載されている。チュートリアルを読むのに grx のようなシェル芸がきっと役に立つだろう。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?