(M1/Apple Silicon)Macな人たちに贈る環境構築Tips集(Dotfiles付き)

# 🙇🏻‍♂️はじめに🙇🏻‍♂️
この記事は弊社の2021年度Advent Calendarに向けて執筆したものです。どういう記事にするか少し悩んだのですが、やはりAdvent Calendarでは実用的な記事の方がプレゼント感があっていいかなー、と思いこの記事を書くことにしました。

# 💪モチベーション💪
Macを利用しているエンジニアの方はかなり多いと思いますが、私の観測範囲では、環境をカスタマイズしまくる勢とほぼデフォルトのまま使ってる勢に二分されているように思います。「こういう設定入れとくと便利っすよ」みたいなことをいろんな人にお伝えしたことがあったので、今後はこの記事みるといいよ、って言えればいいかもなー、と思っている感じです。って言っても大したことやってないので凄腕エンジニアの方々は「なんだよ、これ、知ってることばっかなんだけどw」ってなるかもしれないのでブラウザバックでお願いします笑。

# 🔥TL;DR🔥
dotfiles置いておきましたw。
https://github.com/kuzukawa/dotfiles

### dotfiles？は？何それ？
「dotfiles?は、何それ？美味しいの？！」っていう方は[「ようこそdotfilesの世界へ」](https://qiita.com/yutkat/items/c6c7584d9795799ee164)をご覧ください。最高によくまとまっています。簡単にいうと、各種設定をGitで管理して、どこにいても自分の環境を瞬時に再現するぜ！という考え方のものですね。dotfilesの考え方は、いわゆる`~/.bashrc`に書いてある設定を云々、、ってなりがちなので、Windowsな方々が置いてきぼりになりそうな気もしますが、安心してください！[「Windows向けにdotfilesセットアップスクリプトを作る」](https://qiita.com/kentac55/items/733bdc21e66b44904332)なんて記事もありました！私は現時点ではWindowsは利用していないため、試せていませんが、、


## 🥸考え方🥸
私がやっているのは主に以下です。大したことはやってないです。

1. インストールするアプリケーションの管理
1. CLI環境の設定のカスタマイズ(私はデフォルトのTerminal.appユーザですw) 
1. M1な環境とX86な環境を分けて管理する

### 1. インストールするアプリケーションの管理
Macユーザの方はほぼ確実に[Homebrew](https://brew.sh/)を使っているかと思います。普段はCLIで`brew install wget`とかやってると思いますが、これを管理していきましょう、というものです。管理しておくと、何をインストールしたか、ちゃんと記録されるので精神衛生上も気持ちいいです。CLIなアプリだけでなく、デスクトップアプリも、Mac App Store上のアプリも全て管理できます。これはかなり便利ですぜ、、、

管理は「`Brewfile`」というものに書いていきます。私のを晒してしまうとこんな感じ。2ヶ月前に１から作り直したのでかなり簡素な感じです笑。

```shell
# アプリケーションインストール先の指定
cask_args appdir: "/Applications"

# アプリケーションをインストールする元リポジトリの指定
tap "homebrew/cask"
tap "homebrew/cask-fonts"
tap "homebrew/core"
tap "heroku/brew"

# caskで入れるのはデスクトップアプリケーション。MS-Officeとかも入れてるのがわかりますね
cask "google-chrome"
cask "box-drive"
cask "emacs"
cask "visual-studio-code"
cask "microsoft-office"
cask "microsoft-teams"
cask "zoom"
cask "alfred"
cask "typora"
cask "postman"
cask "drawio"
cask "font-jetbrains-mono"
cask "choosy"
cask "firefox"
cask "docker"

# brewで入れるのはCLIアプリケーション
brew "docker"
brew "asdf"
brew "tmux"
brew "jq"
brew "jump"
brew "pure"
brew "mas"
brew "fzf"
brew "tree"
brew "bat"
brew "gpg"
brew "zplug"
brew "heroku"
brew "git"
brew "git-lfs"
brew "mysql-connector-c"
brew "shared-mime-info"
brew "yarn"
brew "hstr"

# masで入れるのはMac App Store上のアプリケーション
mas "CyberDuck", id: 409222199
mas "Xcode ", id: 497799835
mas "feedly. Read more, know more.", id: 865500966
```

Mac App Storeのアプリをインストールする場合、idというものが必要になりますが、これは以下のように`mas`コマンドで取得できます。例えば、Evernoteの`id`は`406056744`ってことですね。

```shell
mas search evernote
   406056744  Evernote                                    (10.27.5)
  1481669779  Evernote Web Clipper                        (7.18.0)
  1444383602  GoodNotes 5                                 (5.7.56)
   360593530  Notability                                  (11.0.9)
   545988675  Bubble Browser for Evernote                 (2.1.2)
   505487553  Memory Lane - Moving Wallpaper for Evernote (2.0)
  1018564235  Quicky Menubar for Evernote                 (1.5)
  1396383432  EverTool-toolbox for Evernote               (1.0.0)
  1212409035  Memo • Sticky Notes                         (1.6.5)
  1249901692  ScanScan(白描)-OCR Text Scanner               (3.3.3)
  1488905707  Noteshelf                                   (8.5)
```


インストールしたいアプリケーションを`Brewfile`に書いたら、あとはコマンド実行するだけです。以下のコマンド一発でアプリケーションがインストールされます。

```shell
brew bundle --file ${Brewfileへのパス}
```

楽でしょ？本当はセットアップするShellの中で以下のようなコマンドを都度叩くようにしています。これで常に最新の状態が保持される、という感じです。brewのコマンドの説明はここでは省略させていただきます。

```shell
brew doctor
brew update
brew upgrade
brew bundle --file ${Brewfileへのパス}
brew cleanup
```

###  2. CLI環境の設定のカスタマイズ
#### 見た目のカスタマイズ
見た目のカスタマイズに関しては「[お前らのターミナルはダサい](https://qiita.com/kinchiki/items/57e9391128d07819c321)」を読んでいただければ十分です笑。この記事は本当によくできてます、ありがとうございます！私も参考にさせていただいており、色々試しましたが、今でも[Prezto](https://github.com/sorin-ionescu/prezto)、[pure](https://github.com/sindresorhus/pure)を使っています。2行プロンプトはいい感じすぎて使い始めたら元に戻れないですよっ！私のTerminalの見た目は今はこんな感じです。フォントは今は[JetBrains Mono](https://www.jetbrains.com/lp/mono/)を使ってます。いい感じです。
![Screen Shot 2021-12-25 at 8.42.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271670/a418839d-3a5b-ff77-dbb2-49dfbe088216.png)

#### エイリアスを使おう
長いコマンド打つのめんどくさすぎますよね。凄腕の人たちは死ぬほどエイリアス作ってらっしゃるかと思いますが私は少しだけ使っている感じで、以下くらいは今でも切ってます。私はzshを使っているので、`.zshrc`にエイリアスの定義を書いています。

```shell
alias emacs="emacs -nw"
alias la="ls -aFG"
alias ls="ls -FG"
alias ll="ls -alFG"
alias dc="docker-compose"
alias brewx="arch -x86_64 /usr/local/bin/brew"
```

#### アプリケーションもCLIドリブンに起動しよう
みなさん、CLIからデスクトップアプリにファイルを渡すとき、どうやってるんですか？Finderでそこまで行って、マウスで、、みたいな感じでしょうか。ちょっと手間ですよね。エイリアス同様に、`.zshrc`に関数を登録してこのペインを解消していきましょう。例えば、以下は`md`コマンドでMarkdownをエディタで一発で起動するコマンドです。

```shell
function md (){
  open -a Typora $1
}
```

これで、`md ${マークダウンファイル}`ってコマンド実行すると、[Typora](https://typora.io/)が起動します。こんな感じです。
![Screen Shot 2021-12-25 at 8.58.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271670/019c0198-ae4b-c02b-d820-41cd89a9a893.png)
Finderを経由せずにCLIからデスクトップアプリケーションを起動するのは割と生産性が上がった気がするHackなのでみなさん、ぜひ導入していただければと思います笑。

##### 2022/1/3追記
コメントいただきましたので、加筆です。`open`コマンドを使うと、デフォルトアプリケーションが起動するようです。なので、上記例の場合、.mdファイルのデフォルトアプリケーションがTyporaであれば、わざわざfunction自作しなくても以下のコマンドでアプリケーション起動できます！コメントありがとうございました！

```shell
# openコマンドを使うとその種類のファイルを開くデフォルトアプリが起動します
open ./README.md
```

### 3.M1(Apple Silicon)な環境とX86な環境を分けて管理する

M1 Macだと開発やる場合、まだまだ訳のわからないトラブルが発生してしんどい時がありますよね。完璧に解消できるものではありませんが、ここではM1環境とIntel環境に分けてTerminalを使っていくTIPSをご紹介します。

#### そもそもこれなんやねん？
昔々、MacがMacintoshって呼ばれていた頃、PowerPCからIntelアーキテクチャにお引越しするプロジェクトがありました。バイナリの互換性を維持するために開発された技術が[Rosetta](https://ja.wikipedia.org/wiki/Rosetta)というものなんですね。時は流れ2020年、、今度はIntelアーキテクチャからApple Siliconへとまたアーキテクチャをお引越しすることになりました。このバイナリ互換を維持するための技術がRosetta2と呼ばれるものです。Rosetta2さんのおかげでIntel上で動くようにコンパイルされたバイナリも、Apple Silicon上でそれなりに動くんですね。ありがとうございます！Rosettaさん！

普通にMacを使う分にはこれで全く問題ないのですが、エンジニアとして開発で使う場合、今のプロセスがM1で動いてるのか、Intelで動いてるのか、意識していないと困る場合があります。少しでも意識できるように、また、少しでも安全にM1とIntelを分離できるようにこれからご説明する設定を入れておくとちょっと安心するかも？的な感じです。

#### Terminal.appを分離しよう
Macのデスクトップアプリケーションは場合によりますが、Rosetta経由で実行するか、Rosettaを経由せずに実行するかを指定することができます。アプリケーションの「情報」欄から指定することができます。`Terminal.app`の場合、指定できます。
![Screen Shot 2021-12-25 at 9.20.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271670/7cbf4ff5-d9c5-5a77-8f56-6932e019e953.png)
ここで、チェックがついていると、Rosetta経由でTerminalが起動することになります。Rosetta経由ってことは、Terminal上はIntelアーキテクチャでプログラムが動作する、ってことです。私はこんな感じでTerminal.appをコピペして2つ用意して利用しています。これで、Shellを使う際に、あらかじめどちらのアーキテクチャで動いているかを意識しながらTerminalを起動できます。
![Screen Shot 2021-12-25 at 9.29.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271670/55ead70b-0d15-2c91-7ca6-c3dfbc3380ae.png)


#### Terminal側もより安全にしよう！

起動されたTerminal側では`uname -m`コマンドで実行中のアーキテクチャを把握できます。これを利用して、私は起動されたShellがどのアーキテクチャで実行されているかを都度表示させるようにしています。これ、地味ですけどかなりいいです。毎回表示されるのですごく楽に意識できますし、慎重な作業をする際に毎回`uname -m`って打つストレスから解放されます。

ログイン時に実行したいので、今回は`~/.zprofile`に以下の設定を入れます。

```shell
[ `uname -m` = 'x86_64' ] && echo "😀 Be careful, this is x86_64 Shell 😀" 
[ `uname -m` = 'arm64' ] && echo "💪 You are on arm64 Shell 💪" 
```

これで、Terminal.appを起動した場合、都度、以下のようにアーキテクチャが表示されます。
![Screen Shot 2021-12-25 at 9.38.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271670/70809962-9b16-0105-0748-bf9c73e1a89e.png)

#### Homebrewをそれぞれに導入する
従来のHomebrewは`/usr/local/bin`にインストールされていましたが、Apple Silicon向けのHomebrewは`/opt/homebrew`を使うようになりました。これを利用して、arm64向け、x86_64向けにそれぞれHomebrewをインストールします。私は`setup.sh`に以下のように書いています。

```shell
#------------------------------------------
# homebrew(arm64)
#------------------------------------------
echo "Installing homebrew..."
which /opt/homebrew/bin/brew >/dev/null 2>&1 || /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
・
・
・
#------------------------------------------
# homebrew(x86_64)
#------------------------------------------
echo "Installing homebrew(x86_64)..."
which /usr/local/bin/brew >/dev/null 2>&1 || arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
・
・
・
```
見たまんまなので特に説明は不要だと思いますが、コマンドがいなければインストールしているだけです。`arch`コマンドを利用すればコマンド実行時にアーキテクチャを指定できるため、それも活用しています。（今見返すと、arm64の実行時に`arch`指定していないの、これ、バグですね。まぁ私個人ようなので直さないですけど笑）

で、最後に`~/.zprofile`でアーキテクチャに応じてパスや起動Shell等を切り分けて実行すれば準備完了！です。

```shell-session
[ `uname -m` = 'x86_64' ] && eval $(/usr/local/bin/brew shellenv)
[ `uname -m` = 'arm64' ] && eval $(/opt/homebrew/bin/brew shellenv)
```

これで、Terminal.appを起動した時のアーキテクチャに応じてそれぞれのHomebrewが利用されることになります。ちなみに、先ほどは省略しましたが、Homebrewが2つ入ることになるので、Brewfileもそれぞれのアーキテクチャ用に２つ必要です。私は以下の2つのファイルを用意しています。

```shell
# arm64向け。cask, mas(デスクトップアプリケーション)も入れる。
Brewfile
# x86_64向け。CLIコマンドのみ入れる。
Brewfile_x86_64
```

#### anyenvとasdfの共存
ここまでの設定でShellのアーキテクチャは別々に管理・起動できるようになりましたが、開発する時のコンパイラとか実行環境とかも分けて管理したいですよね。ちょっと苦肉の策感がありますが、私は以下のようにして運用しています。

* arm64環境の場合[asdf](https://asdf-vm.com/)を利用
* x86_64環境の場合[anyenv](https://github.com/anyenv/anyenv)を利用

anyenvもいい奴なんですけど、起動が遅いんですよね。ストレス溜まるので、起動頻度の高いarm64環境の方でasdfを利用しています。こうすることにより、各種プログラミング言語の実行環境等もApple Silicon環境とIntel環境でそれぞれ別管理できるようになり、かなりスッキリした気持ちになれます。いつものように`~/.zshrc`に以下のよう初期処理を定義しておきます。

```shell
#--------------------------------------------------------
# asdf(arm64) / anyenv(x86_64)
#--------------------------------------------------------
[ `uname -m` = 'arm64' ] && . /opt/homebrew/opt/asdf/libexec/asdf.sh
[ `uname -m` = 'x86_64' ] && eval "$(anyenv init -)"
```

## ✅総括✅
これでTerminal周りの設定はほぼ完了です。ここまでやればある程度整頓されて使いかってのよい環境ができるのではないかな、と思います。あとは独自にdotfiles等を育てて行って、自分だけの高生産性開発環境を育てていくのが良いかと思います！冒頭にも書きましたが[Github](https://github.com/kuzukawa/dotfiles)にdotfiles一式置いてありますので、適宜参考になさってください。



## 🥁おまけ🎸
私が普段使いしていて、おすすめのアプリをご紹介しておきます。皆様ご存じのモノとは思いますが、新人さんや未経験の方々の参考になれば、、という思いで記載しておきます。これは本当に紹介、ってレベルの記載なので、興味を持たれた方はもっとちゃんと情報書いてある場所を探してくださいませ🙇🏻‍♂️

### [Alfred 4](https://www.alfredapp.com/)
泣く子も黙るMac界のド定番ランチャーソフト。これはほんとに便利なのでぜひ導入していただきたいです。ランチャー使うと「マウスやトラックパッドでアプリを起動」なんてめんどくさくてやってられなくなります。Spotlightでも代用はできると思いますが、例えば、以下のような機能がめっちゃ便利です。

#### 普通にGoogle検索
基本機能ですが、こんな感じでAlfredから直接Google検索できたりします。ローカルのファイル検索したり、普通に色々できるのでこれだけでも使う価値があると思います。
![Screen Shot 2021-12-25 at 10.33.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271670/a122a756-114b-d753-d489-334160e16880.png)


#### クリップボード履歴
こんな感じでクリップボードを保管しておけます。コピペプログラマーの私にはなくてはならない機能です笑。デフォルトだと1週間分のクリップボード履歴と24時間分の画像履歴が保管されます。私は`⌘+⌥+c`でクリップボード履歴を呼び出す設定にしています。書式も落ちるので、プレーンテキストとして文字をコピペしたい方々にはいい機能だと思います。
![Screen Shot 2021-12-25 at 10.24.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271670/b88ba83f-29df-0eab-faf3-4cb0c7aed898.png)

#### ワークフロー
有償版を購入するとワークフローを使えるようになります。エンジニアたるもの、できる限りキーボードだけで作業したいじゃないですか笑。例えば、私は2個くらいしか使ってませんが、以下のような処理をワークフローを使ってAlfredから呼び出せるようにしています。

* AirPodsの接続／切断
* GoogleDrive内の検索

![Screen Shot 2021-12-25 at 10.32.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271670/9c77ad38-7293-0d0b-fa4d-1692583fa0af.png)

ワークフローを自作するのは結構大変ですが、有志が色々なワークフローを公開してくれているので、探せばやりたいワークフローは大体見つかります笑。


### [Choosy](https://www.choosyosx.com/)
そこまでおすすめ、って感じでもないんですが使う人は使う感じです。Chromeとかでプライベートのアカウントと会社のアカウントを分けて使いたい、とか、場合によってブラウザを指定して実行したい、みたいな時に便利です。URLリンク踏んだ時のデフォルトブラウザだChoosyになって、そこからブラウザを指定して、、、みたいな感じです。ある程度ルールも書けるので、ルールに従って指定されたブラウザを起動することも可能です。
![Screen Shot 2021-12-25 at 10.38.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271670/57a23973-bf2f-7f85-6e42-9a2931b5a56b.png)

あんまり常駐アプリ増やしたくないので、定期的にアプリを見直していますが、この2つは今でも生き残って便利に使わせていただいていますね。[Magnet](https://apps.apple.com/jp/app/magnet-%E3%83%9E%E3%82%B0%E3%83%8D%E3%83%83%E3%83%88/id441258766?mt=12)とかも使っている人は便利！って言いますが私は使わなくなってしまいました。


# 😊さいごに😊
開発環境を整備して便利にしていくのは奥の深い道楽みたいなモノですが、やってみるとすごく作業が楽になったり思わぬ知識を吸収できたりします。私の大好きなラリーウォールが言っている「プログラマの3大美徳（怠惰・短気・傲慢）」っていう言葉がありますが、開発環境を洗練させていく作業っていうのはプログラマの3大美徳が体現される場所の一つなんじゃないかなー、って思ってたりしてまして、この辺を突っ込んでやってる人をみるとすごく魅力を感じたりしますね。私もまだまだ勉強頑張ります！


最後まで読んでいただきありがとうございました😊