anyenv + macOS環境構築

フルスタックで開発しているとphp、ruby、python、node.jsなど様々なプログラム言語を使用する機会が増えてきます。特に異なったプロジェクトを同一マシンで行おうとすると各プログラム言語のバージョンなどが競合して上手く開発が行えなくなります。

そこでanyenvの登場です。anyenvをインストールすることでメジャーどこの\*\*env系を一括して管理できるようになりとても開発が楽になります。

追記：anyenv製作者のRyosuke IWANAGAさんが新たにanyenvのgithubリポジトリを作成されたので、記事を修正しました。

- 旧リポジトリ：[https://github.com/riywo/anyenv](https://github.com/riywo/anyenv)
- 新リポジトリ：[https://github.com/anyenv/anyenv](https://github.com/anyenv/anyenv)

現時点でanyenvがサポートしている\*\*env系は以下。

新リポジトリanyenv/anyenvになってから以前からインストールできる\*\*env系の整理されたようです。

※以前はndenvを使用していたのですが、更新がnodenvの方が活発に開発されているので、これを機にndenvからnodenvに乗り換えようと思います。

■ 新anyenv(anyenv/anyenv)
- Renv: R
- crenv: Crystal ← 新規追加
- denv: D
- erlenv: Erlang
- exenv: Elixir
- goenv: GO
- hsenv: Haskell
- jenv: Java
- luaenv: Lua
- nodenv: Node.js ← ndenvがなくなっていますが、nodenvの方が開発が活発なためnodenvに統一されたのだと思われます。
- phpenv: PHP
- plenv: Perl
- pyenv: Python
- rbenv: Ruby
- sbtenv: Sbt
- scalaenv: Scala
- swiftenv: Swift

■ 旧anyenv（riywo/anyenv)
- rbenv: Ruby
- plenv: Perl
- phpenv: php
- ndenv: Node.js
- nodenv: Node.js
- denv: D
- jenv: java
- luaenv: Lua
- goenv: GO
- Renv: R
- erlenv: Erlang
- exenv: Elixir
- hsenv: Haskell
- nenv: Node.js/io.js
- sbtenv: sbt
- scalaenv: Scala
- swiftenv: Swift

かなりの\*\*env系をサポートされています。「こんなに使わないからanyenv使うまでもないな」と思ってしまいがちですが、今後異なった言語を使う可能性がある場合はanyenvを導入するのをお勧めします。

というのもanyenvを導入する利点として、bashやzshなどにanyenvのパスを通すのみでその他は基本的にanyenv下で行ってくれるので.bash_profileや.zshrcなどがとてもきれいに保たれます。更にrbenv系を直接入れていたりするとndenvなど他のenv系をインストールしてbashなどにパスを通したところで上手くパスが通らないということが起こったりします。※個人的には以前この現象でかなりハマったので、それからanyenvを利用するようにしています。

前置きが長くなりましたが早速anyenvのインストールについて書いていきます。

## anyenvのインストール

情報が古くなっている場合は本家の[anyenv](https://github.com/anyenv/anyenv)のインストールを参照してください。ここでは本家に習って記載したいと思います。

### インストール

~~シェルはbashを使用する前提のコードです。~~
シェルはzshを使用する前提です。

**2021年2月9日追記**
macOS Catalinaからデフォルトログインシェルが**`zsh`**になったため記事を**`bash`**から**`zsh`**用に変更いたしました。**`bash`**を使う人は、以下のコマンドの`.zshrc` を `.bash_profile` に読み替えて実行してください。

#### Homebrewでインストール

新たにmacOSユーザーはHomebrewからインストールできるようになっています。

```sh
$ brew install anyenv
$ echo 'eval "$(anyenv init -)"' >> ~/.zshrc
$ anyenv init
$ exec $SHELL -l # シェルを再起動
$ anyenv install --init
```

#### githubのソースからインストール

Homebrewを使わず、従来どおりgithubのソースをダウンロードしてインストールも可能です。

```sh
1:$ git clone https://github.com/anyenv/anyenv ~/.anyenv
2:$ echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.zshrc
3:$ echo 'eval "$(anyenv init -)"' >> ~/.zshrc
4:$ ~/.anyenv/bin/anyenv init
5:$ exec $SHELL -l
6:$ anyenv install --init 
```

たった5行でanyenvをインストールすることができました。
一応解説すると以下のようなことを行っています。

- 1: ユーザーディレクトリ以下に``.anyenv``という名前でanyenvをgithubからクローン（ダウンロード）  
- 2: クローンした.anyenvをzshにパスを通す。`.zshrc`に`export PATH="$HOME/.anyenv/bin:$PATH"`を追加記述するコマンド
- 3: `.zshrc`に`'eval "$(anyenv init -)"'`を追加記述するコマンド
- 4: anyenvのセットアップコマンド実行
- 5: .zshrcの変更を有効にするためにSHELLを再起動
- 6: anyenvの初期化コマンド実行

一応、`.zshrc`を確認してみましょう。

```sh
$ cd ~
$ cat .zshrc
```

以下のようにanyenvのパスが`.zshrc`の下の方に記述されています。

```
...
export PATH="$HOME/.anyenv/bin:$PATH"
eval "$(anyenv init -)"
...
```

## 旧 riywo/anyenv から anyenv/anyenv への以降

旧 riywo/anyenvから新たな anyenv/anyenvへの以降は以下のコードでmigrateできるようです。
※自分の使っていたndenvが``anyenv install -l``で外れていたので少々環境を変更する必要がある方もいると思われますので、慎重に行ってください。 新たにanyenvをanyenv/anyenvからインストールする方はここは飛ばして問題ありません。

```sh
$ cd ~/.anyenv
$ git pull
$ git remote set-url origin https://github.com/anyenv/anyenv.git
```

## インストールのマニフェストディレクトリ

``/User/[your_account]/.config/anyenv/anyenv-install``にインストールのマニフェストを格納？できるようになっているようです。公式サイトに習って実行してみます。

上記の``/User/[your_account]/.config/anyenv/anyenv-install``の「ディレクトリが存在しません、checkout しますか？」と聞かれるので「y」でcheckoutします。

```sh
$ anyenv install --init
Manifest directory doesn't exist: /Users/[your_account]/.config/anyenv/anyenv-install
Do you want to checkout ? [y/N]: y
Cloning https://github.com/anyenv/anyenv-install.git master to /Users/[your_account]/.config/anyenv/anyenv-install...
Cloning into '/Users/[your_account]/.config/anyenv/anyenv-install'...
remote: Enumerating objects: 44, done.
remote: Counting objects: 100% (44/44), done.
remote: Compressing objects: 100% (39/39), done.
remote: Total 44 (delta 1), reused 43 (delta 1), pack-reused 0
Unpacking objects: 100% (44/44), done.
```

※旧anyenvから移行した人は、この状態で``anyenv versions``とコマンドを打っても``/User/...: ndenv: command not found``と以前インストールした``**env``系のコマンドが見つかりませんと言われますが、シェルを再起動すれば問題ありません。

```sh
$ exec $SHELL -l
```

この後に``anyenv``でインストールした``**env``系のバージョンを確認してみます。

```sh
$ anyenv versions
ndenv:
  v10.10.0
  v6.10.0
  v6.14.4
  v6.2.2
  v7.10.0
  v7.2.0
  v7.9.0
  v8.10.0
* v8.11.1 (set by /Users/[your_account]/.anyenv/envs/ndenv/version)
  v8.11.3
  v8.12.0
  v9.9.0
```

新anyenvの``anyenv install -l``では出ていなかった``ndenv``ですが、旧anyenvでインストールしたものはどうやらインストールされた状態のようです。

※ただ、ndenvは開発があまり活発ではないため、新anyenvに切り替えた機にnodenvに乗り換えようと思います。



## anyenvのPluginのインストール

上記でanyenvを利用して\*\*env系のインストール準備はできていますが、anyenvで入れた\*\*env系のアップデートなどを一括でアップデートしてくれるなど、後々便利になってくるプラグインを初回からインストールしておきます。

追記：``znz/anyenv-update``と``znz/anyenv-git``のプラグインのgithubページをみると、anyenvのリンク先が一見、旧anyenv(riywo/anyenv)のリンクのようですが、新anyenv(anyenv/anyenv)のページにリダイレクトされているかつ、anyenvの公式ページのPluginsでリンクが貼られているので互換性があるようです。なので、Pluginをインストールしていきます。


### anyenvのプラグインをインストールする「plugins」ディレクトリの作成

今回は``anyenv-update``プラグインと``anyenv-git``プラグインの２つをインストールするので、先にそれらのプラグインをインストールする「``plugins``」ディレクトリを``.anyenv``以下に作成しておきます。

```sh
$ mkdir -p ~/.anyenv/plugins
```

### anyenv-updateプラグインのインストール

``anyenv update``コマンドでanyenvで入れた\*\*env系の全てをアップデートしてくれるプラグインです。

```sh
$ git clone https://github.com/znz/anyenv-update.git ~/.anyenv/plugins/anyenv-update
```

### anyenv-gitプラグインのインストール

``anyenv git``コマンドでanyenvで入れた\**env系の全てのgitコマンドを実行するプラグインです。

```sh
$ git clone https://github.com/znz/anyenv-git.git ~/.anyenv/plugins/anyenv-git
```

#### anyenv-gitの使い方

※情報が古い場合はanyenv-gitの[本家](https://github.com/znz/anyenv-git)を確認して見てください。

- ``$ anyenv git pull``: anyenvでインストールした全ての\**env系とインストールされているプラグインのアップデート
- ``$ anyenv git gc``: ガーベージコレクション（お掃除）
- ``$ anyenv git remote -v``: 全てのリモートリポジトリを表示
- ``$ anyenv git status``: gitのステータス表示


以上でanyenvのインストールおよびanyenvを快適に使用するプラグインのインストールは完了です。

## anyenvの使い方

### anyenvでインストールできる\**env系のリストを表示

anyenvでは\*\*env系のサポートが増えることが有るので以下のコマンドでインストールできる\*\*env系のリストを表示して確認することができます。

```sh
$ anyenv install -l
```

### \*\*env系のインストール

今回はnodeのバージョン管理を行うnodenvをインストールしてみます。
コマンドは以下

***~~以下``ndenv``で説明していますが、新anyenvでは``nodenv``をサポートしているので``nodenv``に読み替えてください。~~***
***↑以前は上記のように``ndenv``でこれより下の記事で説明を書いていましたが、``nodenv``に書き換え修正しました。***

***※記事の中でも数回触れていますが``ndenv``より``nodenv``の方が開発が活発なため、個人的には``nodenv``を使用することをお勧めします。***


```sh
$ anyenv install nodenv
```

anyenvでインストールしたnodenvを有効にするため、シェルの再起動をします。

```sh
$ exec $SHELL -l
```

### インストールした\*\*env系のバージョンの確認

以下のコマンドでanyenvでインストールした\*\*env系のバージョンを確認することができます。

```sh
$ anyenv versions
nodenv:
Warning: no Node detected on the system
```

anyenvでnodenv自体をインストールしましたが、nodenvで管理するnodeをインストールしていないので上記のようにエラーが出力されます。
なので次にnodenvを使ってnodeをインストールしていきます。

### \*\*env系にインストールできるバージョンの確認

anyenvで\*\*env系をインストールした時点では上記のようにsystemに準拠したバージョンが指定されているので\*\*env系に新たにインストールできるバージョンの確認を以下のコマンドで表示できます。

以下はnodenvの例です。
※ndenvの場合は``v8.10.0``でnodenvの場合は``8.10.0``で頭文字に``v``がつきません。ndenvからnodenvに移行された方で``ndenv local v8.10.0``などで``.node-version``を生成している場合は、このあたり要注意です。

```sh
$ nodenv install -l
..中略..
8.10.0
8.11.0
8.11.1
8.11.2
8.11.3
8.11.4
8.12.0
8.13.0
8.14.0
8.14.1
8.15.0
..中略..
```

### \*\*env系に異なるバージョンのインストール

上記でインストールできるバージョンを確認できたら、インストールしたいバージョンを以下のコマンドで指定してインストールすることができます。

※nodenvの例で``6.10.0``と``8.10.0``の２つをインストールしてみます。8系はlambda、firebase functionsなどで対応されたためasync/awaitが使えて便利です。

```sh
$ nodenv install 6.10.0
$ nodenv install 8.10.0
```

**新しい\*\*env系をインストールをした後はbash（shell）の再起動を忘れずに行っておきましょう**

```sh
$ exec $SHELL -l
```

ここで一旦\*\*env系がインストールされているか確認してみましょう。以下のように指定したバージョンが表示されていれば無事成功です。

```sh
$ anyenv versions
nodenv:
  6.10.0
  8.10.0
```

各バージョンのnodeがnodenvによってインストールできていますが、``nodenv global``を設定していないので``*``マークが付いていません。この状態で``node``コマンドを実行しても、どのバージョンのnodeを使用するのかシステム側は不明なのでエラーとなります。
では次に``global``を設定してシステムのデフォルトのバージョンを指定していきます。

### インストールされている\*\*env系のバージョンを変更

では実際に\*\*envのバージョンを変更してみます。グローバルに変更すればシステムの全てのバージョンが指定したものに切り替わります。またグローバルは変更せずに特定のプロジェクト（ディレクトリ以下）で指定のバージョンを使用したいときにはローカルでバージョンを変更することも可能です。

#### グローバルの設定・変更

```sh
$ nodenv global 8.10.0
```

くどいですが、変更されているか確認してみます。

```sh
$ anyenv versions
nodenv: 
  6.10.0
* 8.10.0 (set by /Users/xxxx/.anyenv/envs/nodenv/version)
```
``8.10.0``の先頭にアスタリスクがついて無事globalとして設定・変更されています。

#### ローカルで変更

ではローカルで異なるバージョンを使えるようにしてみましょう。ここでは仮に``testdir``を制作して、そこに上記で設定した``6.10.0``の環境を有効にしてみます。

```sh
$ mkdir testdir
$ cd testdir
$ nodenv local 6.10.0
```

ここでも確認してみます。

```sh
$ anyenv versions
nodenv:
* 6.10.0 (set by /Users/xxxx/Desktop/testdir/.node-version)
  8.10.0
```

無事設定されています。グローバルは変更されていませんので、指定のローカルディレクトリ下以外ではグローバルで設定した``8.10.0``が有効になっています。また``set by``の後のパスがローカルで指定したディレクトリに制作された``.node-version``になっています。

``vagrant + virtualbox``などの仮想サーバーを構築した際に``Vagrantfile``の``config.vm.synced_folder``でシンクロナイズするフォルダに``.node-version``を参照しておくと、仮想開発環境のサーバーを動かしつつ、ホスト側で``gulp``ないしは``webpack``などで``browserSync``を利用する時にnodeのバージョンが統一できて重宝します。


## まとめ

ざっくりとですがanyenvのインストールと使い方を記載させてもらいました。いろいろな\*\*env系が混在する開発環境ではかなり便利に使い分けることができるようになるので大変助かっております。anyenv製作者のRyosuke IWANAGAさんに感謝です。