launch4jという、javaの実行可能なjar形式を実行可能Windows exe形式にラップしてくれるソフトウェアがある。まず基本的な使い方は、UIを起動して、javaの実行環境としてのjarファイル、実行可能Windows exeの出力ファイル名を指定し、出力実行すると、設定をxmlに保存すると同時にexe形式ファイルを出力する。設定の際にjvmのバージョン等いくらかのパラメータも指定できる。
HPの冒頭にCross-platform Java executable wrapperとあるが、Windows, macOS, Linuxのいずれからでも、jarをwrapしたwindows形式を出力するのをcrossと呼んでて、各OSの実行形式に(例えばLinuxに)出力してくれるわけではない。また、exeはあくまでjarを起動する手順を提供し、jar自体を内包するわけではない。*1
使い方のひとつとして、UIで出力した設定ファイルを引数として指定すると、UIを開くことなくラッパーexeを出力してくれる。設定xmlを用意しておけば、コマンドラインに閉じて.jar 作成=> .exeの流れを作れるので、古風に言えばmakeファイル、というかjavaなので、ant等なビルドツールに含めたbuild手順を作れることになる。
Windowのexeを出力する仕掛けは、launch4jにGNU binutils のldが3OS分(+linux64bit版)含まれていて、さらにWindowsのlibcにあたるいくらかのファイルまで含まれている。これに設定そのものと設定により制御されるjarを起動するコンパイルされた手順コードを、ldを使って実行形式をリンクしている。その手順は、net.sf.launcher4j.Buildの中にある。
起動しているコマンドラインはこんな感じ
windres --preprocessor=[type|cat] -J rc -O coff -F pe-i386 rcfile rcoutfile ld -mi386pe --oformat pei-i386 --dynamicbase --nxcompat --no-seh --subsystem [windows|console] -s headobjs rcoutfile libfiles -o outfile
実は、windresというコマンドがGNU binutilisに入ってるの知らなかった。Windowsの実行形式をエクスプローラで参照するとき出てくるバージョン番号とかをリソースファイル(.rc)で書いてsdkのrc.exeでコンパイルすると思うが、rc.exeがgnuでwindresというコマンドだったということ。当然windows専用なわけである。
libc相当の必要なファイルをそろえれば、linuxないし、macのwrapper実行形式も出力できそうな気がしたのだが、このlaunch4jを改変してそれをするのはすぐには無理っぽい。まずrcファイルに”リソース”要素としてjarファイル名などが入っているので、RC(リソースファイル)という仕組みを持たないlinuxないし、macではなにか別の手段が必要*2。さらにソースツリー上のhead_srcが、launch4jでのjar起動制御をやっていて、これがWinAPI依存で書かれている。
ひとつ勝手な憶測で、Windowsのために何かしらexe形式wrapperが必要で生まれたのかもで、Linux/macOs/その他ならば、sh/bashスクリプトでラップするのが適しているのだと思う。
追記)jpackageというjreバンドル作るコマンドがjdk16から登場しているので、もう市井のwrapper作成は不要なのかもです。