動機
Clojureで開発するときには、常々、boot-cljを使ってきて、Debianが提供しているclojureパッケージは使ったことはなかったが、ちょっとした小物をつくるときに、いちいちboot-cljでプロジェクトをつくったり、拾ってきたjarファイルや/usr/share/java内にあるライブラリを自分のmavenのリポジトリにインストールするのが面倒なので、Debianで提供のものを使ったやり方をまとめておく。
手順
インストール
$ sudo apt install clojure
適当にスクリプトっぽく書く。 (ここでいうスクリプトっぽくというのは 名前空間の設定をしないという意味)
test.clj
(println "Hello")
実行する。
コマンド
$ clojure test.clj
Hello
他のライブラリを使いたいときは、"-cp"でクラスパスを追加してあげる。
JVMにプロパティを渡したい時は、System/setPropertyでコードの中で設定する。
(clojureアプリのコマンドラインとして一度受けとってからsetPropertyで渡すことはできるので、最悪そうする。/usr/bin/clojureの実装上、JVMに直接-Dオプションで渡せない)
試しに何の得にもならないが、ClojureからJythonを使ってPythonコードが実行できるようにしてみる。 事前にjythonをaptでインストールしておく。
$ sudo apt install jython
コードを以下のように書き変える。
test.clj rev. 2
(import '[org.python.util jython])
(System/setProperty "python.home" "/usr/share/jython")
(System/setProperty "python.path" "/usr/share/jython/Lib")
(System/setProperty "python.executable" "/usr/bin/jython")
(System/setProperty "python.console" "org.python.util.JLineConsole")
(jython/main (into-array String *command-line-args*))
コマンド
$ clojure -cp /usr/share/java/jython.jar:$PWD test.clj
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by jnr.posix.JavaLibCHelper$ReflectiveAccess (file:/usr/share/java/jnr-posix.jar) to method sun.nio.ch.SelChImpl.getFD()
WARNING: Please consider reporting this to the maintainers of jnr.posix.JavaLibCHelper$ReflectiveAccess
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Jython 2.7.1 (, Oct 22 2017, 13:43:00)
[OpenJDK 64-Bit Server VM (Oracle Corporation)] on java11
Type "help", "copyright", "credits" or "license" for more information.
>>> print("Hello")
Hello
>>>
WARNINGはjython由来なものなので無視するとして、コマンドの引数にpythonのコードを渡してみる。
hello.py
print("Hello in a file")
コマンド
$ clojure -cp /usr/share/java/jython.jar:$PWD test.clj hello.py
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by jnr.posix.JavaLibCHelper$ReflectiveAccess (file:/usr/share/java/jnr-posix.jar) to method sun.nio.ch.SelChImpl.getFD()
WARNING: Please consider reporting this to the maintainers of jnr.posix.JavaLibCHelper$ReflectiveAccess
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Hello in a file
のちのち他のコードと混ぜて使いたい時があるかもしれない場合は、名前空間を付与しておく。
test.clj rev.3
(ns test
(:import [org.python.util jython]))
(defn launch-python [args]
(System/setProperty "python.home" "/usr/share/jython")
(System/setProperty "python.path" "/usr/share/jython/Lib")
(System/setProperty "python.executable" "/usr/bin/jython")
(System/setProperty "python.console" "org.python.util.JLineConsole")
(jython/main (into-array String args)))
(defn -main [& args]
(launch-python *command-line-args*))
コマンド
$ clojure -cp /usr/share/java/jython.jar:$PWD -m test hello.py
rev.2の時と違うのが、コマンドで "-m"オプションにて-main関数がある名前空間を渡しているところで、Javaのクラス探索規則に従ってクラスパスからtest.clj (もしくは該当の初期化クラス)を探索する。ここでは、カレントディレクトリをクラスパスに指定しているのでtest.cljが発見される。
最後に他の人に渡すときはcljファイルをjarでまとめる。
$ jar cf from-me.jar *.clj
作成したjarを渡してクラスパスに通して実行する。
$ clojure -cp /usr/share/java/jython.jar:from-me.jar -m test hello.py
おわりに
JVMの起動時間の遅さも、昔に比べれば、まだ待てる範囲になったので、ちょっとした小物作成の時はこのやり方でやってみる。