Cygwin で java を動かす

Cygwin には java は付属してないみたい

setupで検索しても出てこない。

f:id:nodamotoki:20190120042957p:plain
cygwin の setup で java を検索している画

でもWindows でインストールしていれば使える

$ type java
java は /cygdrive/c/ProgramData/Oracle/Java/javapath/java です

でも実行すると動かない

java -Dfile.encoding=UTF-8 -jar /usr/share/emacs/26.1/lisp/contrib/scripts/ditaa.jar  /tmp/babel-cacHaR/ditaa-4QhER5 /home/someone/org/images/hello-world.png
Error: Unable to access jarfile /usr/share/emacs/26.1/lisp/contrib/scripts/ditaa.jar

なぜなら、PATH が Windows 形式じゃないから

java に限らないが、ふつうのWindowのプログラムは、引数で受け取る PATH が Windows の PATH 形式じゃないと、うまく動けない。

Cygwin から実行されることは想定していないので、コマンドラインに指定した /usr/... とか、いったいどこだ? と混乱する。

なので変換スクリプトを用意

#!/usr/bin/python3
# -*- python -*-
#
# Windows 向けの Java を実行する前に引数のファイル名を
# Windows 向けの java が理解できるPATHに直す。
#

import os
import sys
import re
import subprocess

JAVA_FOR_WINDOWS = "/cygdrive/c/ProgramData/Oracle/Java/javapath/java"

def main():
    argv = sys.argv[1:]
    #print(argv)
    option = []
    args = []
    for arg in argv:
        if arg.startswith("-"):
            option.append(arg)
        else:
            args.append(arg)
    #print(option)
    #print(args)
    args_win = []
    for arg in args:
        cmdline = "cygpath -m " + arg
        #print(cmdline)
        ret = subprocess.check_output(cmdline, shell=True)
        ret = ret.decode()
        ret = ret.strip();
        args_win.append(ret)
        #print("args_win=", args_win)
    argv = option + args_win

    #print("argv=", argv)
    cmdline = JAVA_FOR_WINDOWS + " " + " ".join(option) + " " + " ".join(argv)
    #print("cmdline=", cmdline)
    subprocess.check_call(cmdline, shell=True)

if __name__ == "__main__":
    main()

これを ~/bin/java として保存。実行権つけて本物の java より PATH 環境変数の前に置いといて先に実行されるようにしとく。

$ chmod 755 ~/bin/java
$ export PATH=~/bin:$PATH

これで、java を実行するとこのスクリプトが実行され、スクリプトの中でほんものの java を実行する前に PATH をうまいこと変換する。

以上。