ビルドツールGradleの基本を見ておきたい

antは使った事があるが、結局mavenに乗り換えずにいた。
ビルドツール一応知識としては持っておく。
Gradle 7.3.2

# ビルドツール
antもmavenもJavaプログラムのビルドツール
antは指定したディレクトリのソースをコンパイルして、jar作って、というのをXMLで書いていた。
mavenはその後継のようなもので、pom.xmlで指定する。リポジトリ管理までが一体となっている。

Gradleという多言語に対応したビルドツールというのもあって、これは全く触った事がない。
Javaは個人的にこれからあまり使わなくなりそうなので、Gradleを見ておく。
[比較](https://qiita.com/MahoTakara/items/ff73338e218b656bedfa

# Gradle
[公式ドキュメントの翻訳版](http://gradle.monochromeroad.com/docs/)

## インストール
WindowsServer2012上でインストールする。
[Windows10の手順](https://qiita.com/j-work/items/3fcf191cc8779c31ce35)を公開している人がいたので参考。

[公式のインストール手順](https://gradle.org/install/)
Java8以上が必要。
macだと`brew install gradle`でいけるらしい。
今回はWindowsで手動なので[リリース](https://gradle.org/releases/)から最新のバイナリを落とす。
公式によると`C:\Gradle`を作成して解凍したものを配置。
`C:\Gradle\gradle-7.3.2\bin`を環境変数に追加しろとの事だが、これはフルパス指定で問題ないかもしれないのでスルー。
フルパスに`-v`でバージョンが出るのを確認してインストールは完了

## 利用
[ここ](https://dev.classmethod.jp/articles/gradle-step-by-step/)とか、バージョンがかなり違うが[ここ](https://tech-lab.sios.jp/archives/9500)を見ながら。

`C:\Gradle\test`フォルダを作って、ここで試してみる。
testフォルダに移動してから`C:\Gradle\gradle-7.3.2\bin\gradle init --type java-application`

手順はGroovyというスクリプト言語のようなもので記述するのが基本だが、以下の選択肢が出たのでKotlinでも書けそう。（Kotlinは知らない）

```
Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1
```

テストフレームワークの種類とかも選択で出てきたが、適当に選んで初期設定完了。
と、ここでテストフレームワークでtestという名前が付いていてややこしいのでフォルダ名をtargetに変更する事にした。
作り直した結果

`C:\Gradle\target\app\src\main\java\target`
にApp.javaというファイルが出来ている。中身は以下のようなハローワールド。

```
/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package target;

public class App {
    public String getGreeting() {
        return "Hello World!";
    }

    public static void main(String[] args) {
        System.out.println(new App().getGreeting());
    }
}
```

`app\build.gradle`がコンパイル設定のようだが、良く分からないのでとりあえずコンパイルで書いてあったコマンドを実行。
`C:\Gradle\gradle-7.3.2\bin\gradle compileJava`を実行。
するとエラーになってしまった。`Task :app:compileJava FAILED`

古いバージョンとは違うようなので
* build.gradleのテスト系はコメントアウト
* pluginにjavaを追加
* gradle tasksでタスク一覧を見る

で
`C:\Gradle\target>C:\Gradle\gradle-7.3.2\bin\gradle assemble`
を実行するとコンパイルが通った。
実行してみる。

```
C:\Gradle\target>jar tvf app/build/libs/app.jar
     0 Tue Dec 21 16:11:32 JST 2021 META-INF/
    25 Tue Dec 21 16:11:32 JST 2021 META-INF/MANIFEST.MF
     0 Tue Dec 21 16:11:32 JST 2021 target/
   646 Tue Dec 21 16:11:32 JST 2021 target/App.class

C:\Gradle\target>java -cp app/build/libs/app.jar App
エラー: メイン・クラスAppを検出およびロードできませんでした
原因: java.lang.ClassNotFoundException: App

C:\Gradle\target>java -cp app/build/libs/app.jar target/App
Hello World!
```

些細なミスで微妙に時間を使ったが、ハローワールドが出来た。


## ライブラリ利用

Javaソースには
`import org.apache.poi.hssf.util.HSSFColor;`
だけ追加して依存関係を作っただけ。コード内で利用はしていない。

POIが必要なので落とすように指定する。

```
repositories {
    mavenCentral()
}

dependencies {
    implementation group: 'org.apache.poi', name: 'poi', version: '5.1.0'
}
```

mavenリポジトリのアドレスは例えばPOIだと[このページ](https://mvnrepository.com/artifact/org.apache.poi/poi/5.1.0)とかでGradleのタブを押して取得する。
これで`assemble`するとエラーが出たが、[プロキシ設定](https://maku77.github.io/gradle/settings/proxy-settings.html)をしていなかったのが原因。
`C:\Gradle\target`に`gradle.properties`ファイルを作成して、プロキシ設定を書き込む。

```
systemProp.http.proxyHost=proxy.host
systemProp.http.proxyPort=8080
systemProp.https.proxyHost=proxy.host
systemProp.https.proxyPort=8080
```

コンパイルされた。
ライブラリそのものはローカルリポジトリに入っている。
今回はローカルAdminで動かしたので
`C:\Users\Administrator\.gradle\caches\modules-2\files-2.1`
に`org.apache.poi`があって、その中にpomと.jarが入っている。
（ログをリダイレクトして、そこから.jarファイルをコピーする方法がある）

ライブラリの依存があるが、それらを含めたFatJarを作成する。
shadowをプラグインに組み込んで

```
id 'com.github.johnrengelman.shadow' version '2.0.3'

```

shadowJar - Create a combined JAR of project and runtime dependencies
のコマンドを実行するとエラー

```
Reason: A property without annotation isn't considered during up-to-date checking.

    Possible solutions:
      1. Add an input or output annotation.
      2. Mark it as @Internal.
```

調べるとバージョンに起因する問題と思われる。
最新バージョンは見ていないが、とりあえず7にすると動いた。
（Shadowのサイトにも対応バージョンが書いてあった）

```
id 'com.github.johnrengelman.shadow' version '7.0.0'
```

app-all.jarが出来て、7MBくらいのファイルが出来ていた。
中身にはpoiやらcommonsやらが入っていたので問題なさそう。

## タスク
実際にはコマンドで自分で定義したタスクを実行させる。
カスタムタスクは[ここ](https://tech-lab.sios.jp/archives/9500#i-6)とか参照

```
task mytask{
	doLast{
		println('xxx')
	}
}
```

[色々ある](https://qiita.com/opengl-8080/items/0a192b62ee87d8ac7578)ようだが、とりあえず基本だけ。

複数のタスクをまとめた別のタスクを作りたい（例えばallタスク）と思うが、標準的な方法は用意されていないっぽい。
otherタスクがmytaskに依存しているという設定を以下のようにすると、other実行時にはmytaskが実行される。
`task other(dependsOn: 'mytask')`
のように指定。
複数タスクを配列で指定すると実行順が保証されないので注意。[mustRunAfter参照](https://maku77.github.io/gradle/task-dependency.html)。


## ファイルコピー
[ここ](https://maku77.github.io/gradle/gradle-copy-files.html)とかでタスク中でファイルコピーをしている。
`type:Copy`を使えば良い。

```
task tskcopy(type: Copy) {
    from 'from/dir'
    into 'to/dir'
    exclude '**/*.bk' // .bkファイルを除く
}
```

## ZIP化
一式をZIP化するような場合
[ここ](https://qiita.com/niwasawa/items/ce35a97a97d376d2587a)とか。

`task xxx(type:Zip)`を指定したタスクを定義する。

```
task zipApp(type: Zip) {
    // zip ファイル名の変更
    archiveFileName = "xxx.zip"

	// WEB-INFフォルダをZIPにコピー
    into('WEB-INF') {
        from 'WEB-INF'
    }
    
    // buildディレクトリや.から開始する隠しディレクトリは除外
	excludes = ['build', '.*']
}
```

上手い事タスクを作れば、jarファイルを作った後に必要な.jspファイルをコピーしてからzip圧縮、みたいな事が出来る、はず。
一応[maven入門](https://qiita.com/tarosa0001/items/e5667cfa857529900216)もちらっと読んではおいた。