6
2

Homebrewの内部動作を理解する

Posted at

これは「Happiness Chain Advent Calendar 2023」の23日目の記事です。
https://adventar.org/calendars/9414/

はじめに

みなさんお世話になっているHomebrewですが、内部動作の理解を後回しにして使っている方もいるのではないでしょうか。
もちろん私もそうでしたが、先日躓いた際に基本動作から調べる機会がありました。
基本動作を理解することでエラーも解決できましたし、何よりも前よりHomebrewを気持ちよく使うことができるようになりました。
これを読んだ方が同じ効果を得られるように記事にまとめてみました。
特にbrew installを実行してからインストールしたものを実行できるところに焦点を当てました。

内容

動作環境

  • Apple M1
  • macOS 14.1.2
  • Homebrew 4.1.25-42-gcd8a9c0

用語

まずHomebrewで出てくる用語について簡単に触れておきます。

用語 原訳 homebrew上での意味
Homebrew 自家製ビール ツール名そのもの
brew 醸造する コマンド
formula 製法 インストール手順を書いたRubyスクリプト
keg 小樽 インストールした実行ファイル置き場
cellar 貯蔵庫 kegをまとめて管理するディレクトリ

大まかな流れ

brew install実行時の大まかな流れは下記になります

  • formulaを取得
  • 取得したformulaを元にインストールした実行ファイルをkegに保存
  • kegへのエイリアスを作成
  • エイリアスにpathを通すことでシェルから呼び出せるようになる

以降で流れを追っていきます。

formulaを取得してインストール

以降は

$ brew install tree

の実行を例にします。
実行するとまず、インストール方法が書かれたformulaを取得しにいきます。
formulaはGitHub上に置かれており、treeの場合は下記のアドレスになります。
https://github.com/Homebrew/homebrew-core/blob/master/Formula/t/tree.rb
ちなみにインストール後はbrew cat treeでもformulaの中身を確認できます。

class Tree < Formula
  desc "Display directories as trees (with optional color/HTML output)"
  homepage "http://mama.indstate.edu/users/ice/tree/"
  url "http://mama.indstate.edu/users/ice/tree/src/tree-2.1.1.tgz"
  sha256 "d3c3d55f403af7c76556546325aa1eca90b918cbaaf6d3ab60a49d8367ab90d5"
  license "GPL-2.0-or-later"

  livecheck do
    url "http://mama.indstate.edu/users/ice/tree/src/"
    regex(/href=.*?tree[._-]v?(\d+(?:\.\d+)+)\.t/i)
  end

  def install
    ENV.append "CFLAGS", "-fomit-frame-pointer"
    objs = "tree.o list.o hash.o color.o file.o filter.o info.o unix.o xml.o json.o html.o strverscmp.o"

    system "make", "PREFIX=#{prefix}",
                   "MANDIR=#{man}",
                   "CC=#{ENV.cc}",
                   "CFLAGS=#{ENV.cflags}",
                   "LDFLAGS=#{ENV.ldflags}",
                   "OBJS=#{objs}",
                   "install"
  end

  test do
    system "#{bin}/tree", prefix
  end
end

実際のインストール方法はコンパイル、バイナリ取得、インストールスクリプトなどがありますが、これをスクリプトで実行してくれているのでユーザーはbrew installのコマンドを実行するだけで良いのです。
ちなみにインストール物がバイナリの場合はbottleと呼ばれます。
また、macOSのGUIアプリの場合はcask(大樽)と呼ばれます。以前はinstall時に--caskオプションが必要でしたが、今は不要になりました。

保存場所とパスの確認

先ほどのbrew install treeのコマンドでインストールが完了しました。
treeの実行可能ファイルやライブラリの実態はcellarの中のkegにインストールされます。
どこにあるか探してみましょう。
まずtreeがどこを示すかコマンドで確認してみます。

$ which tree
/opt/homebrew/bin/tree

ここがkegでしょうか?違います。詳細を見てみます。

$ ls -l $(which tree)
lrwxr-xr-x  1 takuzo  admin  29  9 22 04:13 /opt/homebrew/bin/tree -> ../Cellar/tree/2.1.1/bin/tree

/opt/homebrew/bin/treeはシンボリックリンクであることが分かります。
これはインストール時に作成されたものです。
そしてリンク先の/opt/homebrew/Cellar/tree/2.1.1/bin/treeがkegでここに実行ファイルが置かれます。(実はインストール実行時のログにも書かれています)

実際に使われる際は/opt/homebrew/binに置かれたシンボリックリンクへアクセスされます。
homebrewをインストールした際にここへのパスが通されており、echo $PATHで確認できます。

$ echo $PATH | grep '\/opt\/homebrew\/bin'
..前略..:/opt/homebrew/bin:..後略..

またcellarは下記のコマンドで所在を確認できます。

brew --cellar
/opt/homebrew/Cellar

以上をまとめると、brew install XXXXを実行した際はCellarの中に実行ファイルが置かれ、コンソールからコマンドを実行したときは下記の流れで実行ファイルが呼び出されます。

  1. $PATH
  2. /opt/homebrew/bin/XXXX
  3. /opt/homebrew/Cellar/XXXX/X.X.X/bin/XXXX

補足:CPUによる保存場所の違い

ちなみにMacのintelコア(x86_64)では/usr/local/binに置かれていましたが、M1チップ(arm64)以降は/opt/homebrew/binに置かれるようになりました。
その他のvarやetcもintelコアではrootに置かれますがM1以降は/opt/homebrew配下へ置かれるようになりました。
古い記事を読んだ際は置き場が異なるので注意してください。

補足:リンクについて

上記で説明したようにインストールされると自動でリンクが貼られますが、手動でリンクを貼る必要がある場合があります。
openssl, node, mysqlなど複数のバージョンのkegがcellarの中に存在する場合や、マニュアルでインストールした場合です。
その場合はbrew link --force openssl@1.1のようにするとリンクが貼られます。
(本来はコンテナやasdfなどで管理するべきですが。。。)
参考にbrew linkのコマンドヘルプも載せておきます。

brew link -h
Usage: brew link, ln [options] installed_formula [...]

Symlink all of formula's installed files into Homebrew's prefix.
This is done automatically when you install formulae but can be useful for manual installations.

おわりに

Homebrewでインストールしてから使えるようになるまでの流れを確認できました。
これで以前よりも気持ちよくbrew installコマンドを実行できるようになったのではないでしょうか。
また、もし環境構築などでトラブルがあった時はこのことを覚えていると早く解決できるようになると思います。

参考

記事作成にあたり、下記を参考にさせていただきました!

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2