経緯
Leiningenから起動されるJVMに環境変数を渡す方法で、leinコマンドに直接環境変数を設定して起動するんではなく、project.cljから設定を読み込むような方法ってないんだろうか…。
— えいとす(a.k.a. あちょす) (@athos0220) March 20, 2016
(lein-)environが似たことをやってるけど、あれはあくまで環境変数*も*設定情報のソースにしてくれるだけで、環境変数を設定してJVMを起動してくれるわけではないからやりたいことと微妙にズレてる。
— えいとす(a.k.a. あちょす) (@athos0220) March 20, 2016
やりたいのは単に、特定の環境変数を必要とするJavaライブラリをClojureから使うために開発時にLeiningenを起動する場合も含めて環境変数を設定しておくということなんだけど。シェルでexportしておく手もあるけど、環境が汚れるし設定のし忘れも起こりそう。
— えいとす(a.k.a. あちょす) (@athos0220) March 20, 2016
要件をまとめると次のようになります。
- lein コマンドに直接環境変数を渡したくない
- システムプロパティーではなくて 環境変数 を設定したい
- export するのは避けたい
こんな感じですね。これに対して幾つかの解法があることが分かったのでまとめたいと思います。
大人しく shell のプラグインを使う
次のようなプラグインを使えばわりと綺麗にやりたいことを実現できます。
https://github.com/Tarrasch/zsh-autoenv
https://github.com/jamesob/desk
とはいえ、他の人と同じプロジェクトを進めているときは注意が必要だと思いますが。
Emacs のローカルディレクトリ変数を使う
.dir-locals.el
を次のように設定すれば良いです。
;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")
((clojure-mode
(eval . (setenv "answer" "42"))))
最初だめだと思ったんですけど、やっぱりいけるぽいので書いておきます。
(System/getenv "answer")
;; => "42"
順序としてはファイルを開いて初めて環境変数が設定できるので、その後 cider-jack-in
します。 ただ、この方法だと Emacs からしかその環境変数を参照できないのであまり良い方法ではないかもしれないです。
lein-shell を使う
(defproject demo "0.1.0-SNAPSHOT"
...
:plugins [[lein-shell "0.5.0"]]
:shell {:env {"answer" "42"}})
こうすれば lein shell lein repl
という風に起動できて、 REPL 環境の中で環境変数を参照することができます。 しかし、これは lein-shell
で立ち上がった環境のうえで lein repl
を実行しているので最初はいいかもしれませんが何処かでおかしなことが起りそうな気がしています。
ちなみに最初、 :prep-tasks
で export
するとかしたらいいのではと思ったのですが、ダメみたいです。
まとめ
開発時であれば Emacs を使ったり、 shell のプラグインを使うのが自分の環境を汚さずに済みそうです。
本番環境への環境変数設定忘れについては別途スクリプトを書くなどして防ぐのが良さそう(それしかなさそう)。