いつもお世話になっているHomebrewについて調べてみた

Macにライブラリやプログラミング言語をインストールする際にお世話になっているHomebrew。
ただHomebrewでのインストールに失敗することがたまにあり、そういうときって何かやりたいことがあってインストールをしているので、インストール時のエラーに構ってられず、
エラー文を検索窓でコピペして、見つけた記事にある良さそうなコマンドを打って解決してしまいます。
あまりそういうことをやっていると、Homebrewについての知見がたまらず、これからもたくさんのインストール時エラーをテキトウに解決してしまいそうだなー、と思ったので重い腰を上げて調べることにしました。

#Homebrewについて
私はHomebrewについて、macOSで使えるパッケージマネジャということしか知らないのでもっと詳しく調べてみます。
[Homebrew](https://brew.sh/index_ja)
↑公式のホームページをみていきます。

###Linuxでもつかえる！

>Homebrewではアップル(またはあなたのLinuxシステム)が提供していないあなたの必要なものをインストールできます。

macOSだけでなく、Linuxでも使えるんですね！

###/usr/local/Cellar

>Homebrewは自身のディレクトリにパッケージをインストールし、それらへのシンボリックリンクを/usr/localに作成します。
>\$ cd /usr/local
>\$ find Cellar
>Cellar/wget/1.16.1
>Cellar/wget/1.16.1/bin/wget
>Cellar/wget/1.16.1/share/man/man1/wget.1
>\$ ls -l bin
>bin/wget -> ../Cellar/wget/1.16.1/bin/wget

なるほど...
もうちょと深くみていきましょうか。

```bash
$ cd /usr/local
$ ls Cellar | head -10
arpack
autoconf
automake
bdw-gc
bison
cairo
cmake
epstool
fftw
fig2dev
```

"自身のディレクトリ"というのは、Cellarのことなんだと思います。
そして、シンボリックリンクが貼られている/usr/local/bin以下を参照すると、

```bash
$ ls -l /usr/local/bin head -10
total 3336
lrwxr-xr-x   1 mac   admin       31  4  5  2019 2to3 -> ../Cellar/python/3.7.3/bin/2to3
lrwxr-xr-x   1 mac   admin       35  4  5  2019 2to3-3.7 -> ../Cellar/python/3.7.3/bin/2to3-3.7
lrwxr-xr-x   1 mac   admin       38  5 19  2019 411toppm -> ../Cellar/netpbm/10.73.27/bin/411toppm
drwxr-xr-x   9 root  wheel      288  7  5  2019 Django-2.2.3.dist-info
lrwxr-xr-x   1 mac   admin       59  5 19  2019 GraphicsMagick++-config -> ../Cellar/graphicsmagick/1.3.31/bin/GraphicsMagick++-config
lrwxr-xr-x   1 mac   admin       57  5 19  2019 GraphicsMagick-config -> ../Cellar/graphicsmagick/1.3.31/bin/GraphicsMagick-config
lrwxr-xr-x   1 mac   admin       61  5 19  2019 GraphicsMagickWand-config -> ../Cellar/graphicsmagick/1.3.31/bin/GraphicsMagickWand-config
lrwxr-xr-x   1 mac   admin       50  5 19  2019 Magick++-config -> ../Cellar/imagemagick/7.0.8-44/bin/Magick++-config
lrwxr-xr-x   1 mac   admin       52  5 19  2019 MagickCore-config -> ../Cellar/imagemagick/7.0.8-44/bin/MagickCore-config
```

たしかに、Cellarへのシンボリックリンクが貼られています。

###Formula

>HomebrewのformulaはシンプルなRubyスクリプトです

いきなりformulaという未知の単語が出てきたのでdocumentの用語集から探してみます。
[Homebrewの用語集](https://docs.brew.sh/Formula-Cookbook#homebrew-terminology)

|用語|説明|例|
|:---|:---:|:--:|
|Formula|パッケージの定義|/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/foo.rb|

documentの例にならって以下のディレクトリを参照すると、拡張子がrbのファイルがたくさんあるのがわかります。

```bash
$ ls /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/
```

それらのうちgccのファイルを開いてみると、

```Bash
$ cat /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/gcc.rb | head -40
class Gcc < Formula
  desc "GNU compiler collection"
  homepage "https://gcc.gnu.org/"
  url "https://ftp.gnu.org/gnu/gcc/gcc-10.2.0/gcc-10.2.0.tar.xz"
  mirror "https://ftpmirror.gnu.org/gcc/gcc-10.2.0/gcc-10.2.0.tar.xz"
  sha256 "b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c"
  license "GPL-3.0"
  head "https://gcc.gnu.org/git/gcc.git"

  livecheck do
    url :stable
    regex(%r{href=.*?gcc[._-]v?(\d+(?:\.\d+)+)(?:/?["' >]|\.t)}i)
  end

  bottle do
    sha256 "8dbccea194c20b1037b7e8180986e98a8ee3e37eaac12c7d223c89be3deaac6a" => :catalina
    sha256 "79d2293ce912dc46af961f30927b31eb06844292927be497015496f79ac41557" => :mojave
    sha256 "5ed870a39571614dc5d83be26d73a4164911f4356b80d9345258a4c1dc3f1b70" => :high_sierra
  end

  # The bottles are built on systems with the CLT installed, and do not work
  # out of the box on Xcode-only systems due to an incorrect sysroot.
  pour_bottle? do
    reason "The bottle needs the Xcode CLT to be installed."
    satisfy { MacOS::CLT.installed? }
  end

  depends_on "gmp"
  depends_on "isl"
  depends_on "libmpc"
  depends_on "mpfr"

  uses_from_macos "zlib"

  # GCC bootstraps itself, so it is OK to have an incompatible C++ stdlib
  cxxstdlib_check :skip

  def version_suffix
    if build.head?
      "HEAD"

```

たしかに、パッケージの詳細がRubyで記されていて、ホームペジのリンクや依存関係などが書いてありますね。

###brew edit

>すべてGitとRubyで動作しているため、あなたがすでに持っている知識で簡単に変更を戻したりマージしたりできます。
\$ brew edit wget # $EDITORで開きます！

実際に一例として何かしらのライブラリをeditしてみましょうか。

```bash
$ brew edit gcc
class Gcc < Formula
  desc "GNU compiler collection"
  homepage "https://gcc.gnu.org/"
  url "https://ftp.gnu.org/gnu/gcc/gcc-10.2.0/gcc-10.2.0.tar.xz"
  mirror "https://ftpmirror.gnu.org/gcc/gcc-10.2.0/gcc-10.2.0.tar.xz"
  sha256 "b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c"
  license "GPL-3.0"
  head "https://gcc.gnu.org/git/gcc.git"

  livecheck do
    url :stable
    regex(%r{href=.*?gcc[._-]v?(\d+(?:\.\d+)+)(?:/?["' >]|\.t)}i)
  end

  bottle do
    sha256 "8dbccea194c20b1037b7e8180986e98a8ee3e37eaac12c7d223c89be3deaac6a" => :catalina
    sha256 "79d2293ce912dc46af961f30927b31eb06844292927be497015496f79ac41557" => :mojave
    sha256 "5ed870a39571614dc5d83be26d73a4164911f4356b80d9345258a4c1dc3f1b70" => :high_sierra
  end

  # The bottles are built on systems with the CLT installed, and do not work
  # out of the box on Xcode-only systems due to an incorrect sysroot.
  pour_bottle? do
    reason "The bottle needs the Xcode CLT to be installed."
    satisfy { MacOS::CLT.installed? }
  end

  depends_on "gmp"
  depends_on "isl"
  depends_on "libmpc"
  depends_on "mpfr"
```

なるほど！
Formulaを編集することで、色々な変更を加えることができるんですね。

### brew cask

>"アイコンをドラッグしてインストール…"のようなことをする必要はありません。brew caskではmacOSアプリケーション、フォント、プラグイン、そしてオープンソースではないソフトウェアもインストールできます。
$ brew cask install firefox

このcaskについても用語集をみてみます。

|用語|説明|例|
|:--|:--:|:---:|
|Cask|macOSのネイティブアプリをインストールするためのHomebrewの拡張|/Applications/MacDown.app/Contents/SharedSupport/bin/|

例は、MacDown.appというネイティブアプリをbrew caskでインストールできますよー、ということみたいです。

ホームページに書かれていることから概要は掴めた気がします。次は、用語集乗っている中から重要そうな概念をみていきたいと思います。


#重要な概念

###Keg
|用語|説明|例|
|:--|:--:|:---:|
|Keg|Formulaのインストールしたバージョン番号|/usr/local/Cellar/foo/0.1|

以下のコマンドで、gccのKegを参照してみると、

```Bash
$ ls /usr/local/Cellar/gcc
10.2.0  9.1.0
```

たしかにバージョンごとにディレクトリがあることがわかります。

###opt prefix

|用語|説明|例|
|:--|:--:|:---:|
|opt prefix|Kegのうち、アクティブなバージョンに対するシンボリックリンク|/usr/local/opt/foo|

以下のコマンドで、先ほどのgccのKegのうちアクティブなバーションを確認してみると、

```Bash
$ ls -l /usr/local/opt/gcc
lrwxr-xr-x  1 mac  admin  20  9 21 22:44 /usr/local/opt/gcc -> ../Cellar/gcc/10.2.0
```

10.2.0がアクティブになっていることと、シンボリックリンクが敷かれていることが確認できました。

###Cellar

|用語|説明|例|
|:--|:--:|:---:|
|Cellar|全てのインストール済みのKeg|/usr/local/Cellar|

では、gccのCellarを参照してみますね。

```Bash
$ ls /usr/local/Cellar/gcc
10.2.0  9.1.0
```

全てのKegのソースコートがここに格納されているわけですね。そして、先ほどのopt prefixはCellarに格納されているバージョンのうち、アクティブなバージョンへのシンボリックになっているわけですね。
だんだんと、わかってきた...

###Tap

|用語|説明|例|
|:--|:--:|:---:|
|Tap|FormulaのGitリポジトリ|/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core|

私の環境で確認してみますね。

```bash
$ ls /usr/local/Homebrew/Library/Taps
dpo             hashicorp       heroku          homebrew
$ ls /usr/local/Homebrew/Library/Taps/homebrew
homebrew-cask   homebrew-core
$ ls /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core
homebrew-cask   homebrew-core
$ ls /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula | head -10
a2ps.rb
a52dec.rb
aacgain.rb
aalib.rb
aamath.rb
aardvark_shell_utils.rb
abcde.rb
abcl.rb
abcm2ps.rb
abcmidi.rb
```

リポジトリが色々とあって、その中にFormulaが格納されていることがわかりますね。
documentのTapのページを参照してみます。

>Taps are external sources of Homebrew formulae, casks and/or external commands. They can be created by anyone to provide their own formulae, casks and/or external commands to any Homebrew user.

Tapはインターネット上(、主にGitのリポジトリ)にあるFormulaのリソース集になっているわけですね。
そして、誰でもFormulaを追加できるらしいです。

###Bottle

|用語|説明|例|
|:--|:--:|:---:|
|Bottole|ビルド前のKeg|qt-4.8.4.catalina.bottle.tar.gz|

なるほど。新しいKegをインストールしたい場合はまずBottleをインストールしてきて、それをローカルで展開することでKegにするわけですね。
さきほどのgccのFormulaを見返すと、urlという変数にmacOSのバージョンごとのBottleが格納されているのが確認できます。

```bash
$ cat /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/gcc.rb | grep bottle -5
  livecheck do
    url :stable
    regex(%r{href=.*?gcc[._-]v?(\d+(?:\.\d+)+)(?:/?["' >]|\.t)}i)
  end

  bottle do
    sha256 "8dbccea194c20b1037b7e8180986e98a8ee3e37eaac12c7d223c89be3deaac6a" => :catalina
    sha256 "79d2293ce912dc46af961f30927b31eb06844292927be497015496f79ac41557" => :mojave
    sha256 "5ed870a39571614dc5d83be26d73a4164911f4356b80d9345258a4c1dc3f1b70" => :high_sierra
  end

```

# まとめ
色々と明らかになりましたね！まだまだ深められる部分はありそうですが、これで大体のインストールエラーには対応できそうですので、今回はこれくらいにしときます〜。