ここ数年機械学習ばかりやっていて使用言語はほぼPythonだったのですが、久々に色々な言語を仕事で使う機会がありそうで、ついでにMacもM1プロセッサのものに新調したので開発環境を整えていました。
HomebrewのM1対応は落ち着いてきたので早速その辺りを検索していると、最近は何やらanyenvなるものが流行っているらしい。
Pythonで言えばpyenvやanacondaのような仮想環境を入れずとも、基本的には最新版で開発すればいいし、バージョンを切り替えたい場合はパスを変えるなりDockerを使うなりすればいいと個人的には思っていたのだが、多言語使いとしてはコマンド一発で各々の開発環境が見通せるというのは魅力的である。
しかも、Oracleとの著作権問題でごちゃごちゃしていてインストールの面倒だったJavaの開発環境をコマンドで管理できるjEnvまで存在するとは、流石Javaも8から16に進化しただけのことはある。
とは言えそこはやはりJava。Pythonやnpmはすんなり入るのにjEnvだけは少し手間取り、かつ情報も断片的でまとめる必要があったのでインストール方法を記録しておきます。
(M1に限らずMacでanyenv + jEnvを使う人の役に立つよう心がけましたが、再現性などは真面目に保証できないので悪しからず。過不足あればコメント頂けると幸いです)
前提
MacBook Air M1 2020, BigSur 11.2.1
Homebrew 3.0.2
anyenv 1.1.2
jenv 0.5.4
anyenvのインストール
anyenvやHomebrewに関しては他に最新情報を書いている人が沢山いるので割愛します。
若干ハマりどころもあったような気もしますがなんとかして下さい。
私は以下の記事を参考にしました。
https://zenn.dev/hinastory/articles/71983c4ac8aa2d
% anyenv install -l
で動作確認。
anyenvが入っていることを確認したらjEnvよりハードルの低い言語のインストールを検証してみるといいと思います。
比較的多くの人がお世話になるであろうnodenvなどがいいと思います。
Go言語などは最新版の1.16以降がM1対応の様なので、M1の場合念の為使い慣れた言語がいいと思います。
M1以外の人はなんでもいいと思います。
% anyenv install goenv
% exec $SHELL -l
% goenv install -l
% goenv install 1.16.0
% goenv global 1.16.0
% exec $SHELL -l
ここまでで既に環境変数の設定を行っていると思いますが、以降もちょくちょく入ります。
M1 Macに限った話ではないですが、Catalina以降のMacのデフォルトシェルはzshなので環境変数は基本的に.zshrcにあります。
古い記事を鵜呑みにしてbash_profileなどを作ってもいいのですが、混乱するので方針は統一したほうがいいでしょう。
本題
1. jEnvのインストール
ここからがややこしいところですが、jEnvにinstallコマンドはありません。
まずはanyenvからjEnvをインストールします。
% anyenv install jenv
% exec $SHELL -l
% jenv install -l
jenv: no such command `install'
ではどうやってjEnvにJavaを認識させるのかと言うと、まずJava本体をインストールしてその後jEnvにパスを通し、登録されたJavaの中から使用するバージョンを選択するということのようです。
2. Javaのインストール
古いJavaはGUIインストールなのでcaskを使用しますが、最近はそのままインストールできるようです。
% brew search java
% brew install java11 # 好きなものを入れる
Java16は記事執筆時点でApple Silicon beta versionとなっていたので11でやっていますが私は後で16に入れ直しました。
brew info javaコマンドのメッセージでベータ版かどうかわかるので、個人の好みで読み替えて下さい。
またこれはおまけで、あまり書いている人がいなくて戸惑いましたが、古い記事を参照してcaskを使用する場合はオプションで指定します。
brew caskコマンドは最近廃止されました。
homebrewのcaskコマンドはオプションになりました。
https://qiita.com/horit/items/03e6ae6599253afcd75c
3. $JAVA_HOMEの設定
以下の記事を見るとenable-plugin exportというのを打っておいた方が良さそうです。
% jenv enable-plugin export
% exec $SHELL -l
4. jEnvにJavaを登録
ここで
% jenv add `/usr/libexec/java_home -v "11"`
とすれば良いと書かれてある記事が多かったのですが私の場合うまくいきませんでした。
それもそのはずで、JVMがあるはずの
/Library/Java/JavaVirtualMachines/
が空だったからです。
どうやらkeg-only指定なので$JAVA_HOMEへのシンボリックリンクを貼る必要があるとのことです。
% brew info java11
~略~
openjdk@11 is keg-only, which means it was not symlinked into /opt/homebrew,
because this is an alternate version of another formula.
以下のような感じでシンボリックリンクを貼りました。
% sudo ln -sfn /opt/homebrew/opt/openjdk@11/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-11.jdk
% echo 'export PATH="/opt/homebrew/opt/openjdk@11/bin:$PATH"' >> ~/.zshrc
5. バージョンの指定
改めて、
% jenv add `/usr/libexec/java_home -v "11"`
% jenv versions
% jenv global 11.0.9
% exec $SHELL -l
% echo ${JAVA_HOME}
指定のバージョンのJavaで起動は確認できたでしょうか。
最後に
正直、仮想環境とはいえ言語のインストールにここまで手間がかかるとは思っていなかった(どこかに情報がまとまっていると思っていた)ので、コマンドの履歴は完全ではありません。
また、jEnvのメジャーバージョンが0番台であることから、現行の手順は一時凌ぎ的なものである可能性も高いのではないかと思います。
ユーザー数の多いJavaの中で私は最近の動向には全く不案内なのですが、誰かの役に立てば幸いです。
参考
公式ドキュメント
https://www.jenv.be/
keg-onlyなパッケージはシンボリックリンクが作られない
https://mosquito7.blogspot.com/2013/07/keg-only.html