Java

依存関係を含めた実行可能なjarファイルをGradle(Kotlin DSL)で作成

Gradle で jar ファイルを作成する際、特定のクラスの main 関数を実行させたいケースってありますよね。

しかし作成した jar ファイルを何気なく実行してみると以下のエラーが・・・。

マニフェスト属性がありません

通常、実行可能な jar ファイルを作成する場合は、マニフェストファイル(MANIFEST.MF)に実行クラスを定義して jar に含めるのが一般的です。

今回は Gradle で jar ファイルを作成する際に、どのように manifest を指定すればいいのか確認してみました。

jarのタスク定義

今回のケースでは、以下を jar ファイルに含めると想定します。

・main 関数を実行するクラス
・依存関係のライブラリ

必要最低限となりますが、これだけ揃っていれば「java -jar」コマンドで jar を実行することが可能となります。

java -jar hogefuga.jar

もちろん引数(args)の指定も可能です。

java -jar hogefuga.jar [引数1] [引数2]

main関数を実行するクラス

まずは main 関数の実行対象ですね。

Kotlin DSL の場合は build.gradle.kts に以下を定義します。

manifest のメソッドが用意されているので、Main-Class 属性にパッケージからのクラス名を指定するだけです。

依存関係のライブラリ

次に、別のモジュールや外部のライブラリなど、プログラムの実行に必要なファイルも一緒に jar に入れます。

せっかく jar が実行できても、参照先のモジュールがなければ以下のエラーが発生することになりますからね。

・NoClassDefFoundError
・ClassNotFoundException

Gradle のバージョンによって定義が異なりますが、Gradle7.1 では以下の指定で問題ありません。

ただし、Gradle のバージョンによっては下記のエラーが発生することが。
(バージョン 7.x 系がダメなのかな)

調べてみると、ファイル重複のエラーは以下の設定で回避できるとのこと。

duplicatesStrategy = DuplicatesStrategy.EXCLUDE

これを追記しておきましょう。

完成形の jar タスクの中身は以下のようなイメージとなります。

jarに含めたくないファイルの除外

jar ファイルに不要なファイルを含めたくない。

exclude メソッドを使えばこれも実現できちゃいます。

以下はテキストファイルと、META-INF 配下の *.MF ファイルを除外する例です。

exclude(*.txt”, “META-INF/*.MF”)

これで jar のタスクも最低限は完成ですね。

すべてまとめるとこんな感じ。

まとめ

Gradle(Kotlin DSL)による実行可能な jar ファイルの作成について紹介してきました。

やってることは単純なのですが、いざ定義しようと思うとドキュメントと格闘です・・・。

groovy 版や、古い Gradle バージョンのサンプルは多く見つかるのですけどね。

jar を直接実行する機会は滅多にないと思いますが、覚えておいて損はないでしょう。