​ ​
launch4j_1.PNG

Gradle から Launch4j を使って jar を exe 化する

東京で働くファームノートのエンジニア狩谷です。そろそろ新しいMacBook Proが発表されそうでワクワクしております。弊社はエンジニア系な職務の人だけでなく全員がMacで仕事してます(多分)。最近はそういう会社が多いのでしょうか。

ところで、Javaのランタイムを同梱でWindowsにアプリケーションを配置したい時ってありますよね。一生に1回あるかどうかくらいの頻度ではあると思います。

そんな時に頼りになるのがLaunch4jです。Launch4jを使うとjarをラップしたexeファイルを作成することができます。また、実行時に使用するJREを指定することも可能です。Launch4jを使って作ったexeファイルとJREをzipファイルに同梱してWindows PCに持っていけば、Windows PC上でのセットアップが楽になりますね。

Launch4jのついての情報はググるといろいろ出てきます。

基本的にはLaunch4jを公式サイトからダウンロードしてきて、GUIもしくはXML形式の設定ファイルを読み込ませる形でCUIから利用します。

ただ、Javaのアプリケーション自体はGradleでビルドしているので、その延長でGradleからLaunch4jを使いたくなってきます。探してみるとありました、gradle-launch4j-pluginです。

では、使ってみましょう!

fatJarを作る

まずは、fatJarを作ります。gradle-capsule-pluginを使用しました。

plugins {
    id 'us.kirchmeier.capsule' version '1.0.2'
}

apply plugin: 'java'

sourceCompatibility = 1.8
targetCompatibility = 1.8
[compileJava, compileTestJava].each {
    it.options.encoding = 'UTF-8'
}

repositories {
    mavenCentral()
}

task fatJar(type: FatCapsule) {
    applicationClass 'sample.Main'
}

task wrapper(type: Wrapper) {
    gradleVersion = '3.1'
}

カレントディレクトリにファイルを作成する処理をする main メソッドを用意します。

package sample;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;

public class Main {
    public static void main(String[] args) throws IOException {
        Path path = FileSystems.getDefault().getPath("./sample_output.txt");
        Files.write(path, "Hello World!".getBytes());
    }
}

以下のコマンドでfarJarを生成できます。

$ ./gradlew fatJar

実行するとファイルが生成されてます。

$ java -jar ./build/libs/launch4j_sample-capsule.jar
$ ls ./sample_output.txt
./sample_output.txt

exeを作る

では、gradle-launch4j-pluginを使ってexeファイルを作成してみましょう。

build.gradleのpluginsにgradle-launch4j-pluginを追加します。

plugins {
    id 'us.kirchmeier.capsule' version '1.0.2'
    id 'edu.sc.seis.launch4j' version '1.6.2'
}

以下のようにgradle-launch4j-pluginの設定を行います。

copyL4jLib.dependsOn fatJar
launch4j {
    icon = "${project.rootDir}/cow.ico"
    headerType = 'console'

    copyConfigurable = project.tasks.fatJar.outputs.files
    jar = "lib/${project.tasks.fatJar.archiveName}"

    bundledJrePath = 'jre_win'
    bundledJre64Bit= true
}

icon でexeファイルのアイコンを指定できます。GUIアプリケーションではないので headerType'console' にします。jar には生成したfatJarを指定します。生成したfatJarは launch4j タスクによってコピーされるのですが、それについては後述します。bundledJrePath にはJREのパスを指定します。これはアプリケーション実行時に利用される設定で、exeファイルからの相対パスになります。

launch4j タスクを実行すると、build/launch4jディレクトリ配下にいろいろできてます。

$ ./gradlew clean launch4j
$ tree -F -L 2 build/launch4j
build/launch4j
├── bin-launch4j/
│   ├── bin/
│   ├── head/
│   ├── head_jni_BETA/
│   ├── launch4j.jar
│   ├── lib/
│   ├── w32api/
│   └── w32api_jni/
├── launch4j.xml
├── launch4j_sample.exe*
└── lib/
    └── launch4j_sample-capsule.jar

launch4j タスクは以下のタスクを順に実行してくれています。

  • copyL4jLib
    • build/launch4j/lib ディレクトリに、 copyConfigurable プロパティで指定したファイルをコピーする
  • generateXmlConfig
    • Launch4jの設定ファイル(build/launch4j/launch4j.xml)を生成する
  • unzipL4jBin
  • copyL4jBinLib
    • build/launch4j ディレクトリに、Launch4jを配置する(build/launch4j/bin-launch4j)
  • createExeWithJar
  • createExe
    • exeファイルを生成する

Launch4を使って、jarをexeにできました。

JREといっしょにzip化する

Windows用のJREとexeファイルをzipにします。まず、 prePack タスクでJREとexeファイルを適当な一時ディレクトリにコピーします。最後にpackタスクでzip化しています。

ext {
    archiveTmpDir = "${buildDir}/${project.name}_tmp"
}

task prePack(dependsOn: 'launch4j') << {
    copy {
        from 'jre_win'
        into "${archiveTmpDir}/jre_win"
    }
    copy {
        from "${launch4j.outputDir}/${project.name}.exe"
        into archiveTmpDir
    }
}

task pack(type: Zip, dependsOn: prePack) {
    from archiveTmpDir
    archiveName "launch4j_sample.zip"
}

実行するとzipファイルができます。

$ ./gradlew clean pack
$ ls build/distributions
launch4j_sample.zip

このzipファイルをWindows PCに持って行って展開します。

launch4j_2.PNG

exeファイルをダブルクリックします。実行できてファイルが作成されました!

launch4j_3.PNG

おわりに

無事、GradleからLaunch4jを使うことができました。ビルド環境の構築が楽になり、CIツールからも使ったりもできます。

ファームノートでは、このようなアプリケーションを開発するだけでなく、Webアプリケーションエンジニア大規模データ基盤エンジニアネイティブアプリエンジニアも募集中です!今回紹介したようないろいろをやるエンジニアも募集中です!弊社HPWantedlyからのご応募お待ちしております。

このエントリーをはてなブックマークに追加