Homebrew完全に理解した
macOSで開発をする人の999割が使っているであろうHomebrewですが, Homebrewで入れているopensslのバージョンをごちゃごちゃにしてしまったことがちょっと前にあったので,仕組みをちゃんと知ろうと思い調べてみました.
基本的にはHomebrewの公式ページとman brew
, man brew-cask
を読んでまとめました.
Homebrewの基本的な使い方などはここでは説明しないので,公式ページのドキュメントを見てください.
各用語の意味
Homebrewはその名の通り,自家醸造をモチーフにした用語を使っています. これらについて調べてみました.
全体の関係図
formula
formulaとは「調理法,調合方法」という意味で,パッケージ定義を表します.これには,
- ソースのURL
- bottle(後述)
- 依存パッケージ
- インストールスクリプト
- テストスクリプト
などの情報が書いてあり,実体はパッケージ定義が書いてあるrubyファイルです. 具体的には次のようなものです.(gradleの例)
$ brew cat gradle
class Gradle < Formula
desc "Open-source build automation tool based on the Groovy and Kotlin DSL"
homepage "https://www.gradle.org/"
url "https://services.gradle.org/distributions/gradle-6.4.1-all.zip"
sha256 "3fd824892df8ad5847be6e4fb7d3600068437de172939fd657cc280a1a629f63"
bottle :unneeded
depends_on "openjdk"
def install
rm_f Dir["bin/*.bat"]
libexec.install %w[bin docs lib src]
(bin/"gradle").write_env_script libexec/"bin/gradle",
:JAVA_HOME => "${JAVA_HOME:-#{Formula["openjdk"].opt_prefix}}"
end
test do
assert_match version.to_s, shell_output("#{bin}/gradle --version")
(testpath/"build.gradle").write <<~EOS
println "gradle works!"
EOS
gradle_output = shell_output("#{bin}/gradle build --no-daemon")
assert_includes gradle_output, "gradle works!"
end
end
ちなみに複数形はformulae(フォーミュリ)です.
bottle
bottleとはそのまま「ボトル」で,ビルド済みのバイナリを表します. keg(後述)と同じファイル構成をtar.gzにしたもので,環境に合うbottleがformulaに含まれていれば,ビルドせずにインストール可能です. (合うものがなければ,formulaの定義に従いビルドされてインストールされます.)
bottleを作るときは,一旦開発環境でbottle用にビルドしてから作成します.
$ brew install --build-bottle <formula> && brew bottle <formula>
これを行うと,bottleが作られると同時にformula定義ファイル用のDSLも生成してくれます.
keg
kegとは「小樽」という意味で,インストールされたformulaもしくはbottleを表します. 実行可能ファイルやライブラリの実体がここに置かれ,/usr/local/bin などからシンボリックリンクが貼られます.
# wgetの実体とシンボリックリンクの例
$ ls -l $(which wget)
lrwxr-xr-x 1 otti admin 30 Nov 14 2018 /usr/local/bin/wget@ -> ../Cellar/wget/1.19.5/bin/wget
この場合 /usr/local/Cellar/wget/1.19.5 がkegです.
cellar
cellarとは「貯蔵室」という意味(ワインセラーとかのセラー)で,kegが置かれる場所を表します.
# Cellarの場所
$ brew --cellar
/usr/local/Cellar
# kegのリスト
$ find $(brew --cellar) -depth 2 | head -5
/usr/local/Cellar/pstoedit/3.74
/usr/local/Cellar/rubberband/1.8.2_1
/usr/local/Cellar/avrdude/6.3_1
/usr/local/Cellar/mosquitto/1.5.4
/usr/local/Cellar/libpsl/0.20.2
tap
tapとは「蛇口」という意味で,formulaを提供するリポジトリへの接続口を表します.
GitHubにtapする場合は省略形で書けます.
例えば,brew tap https://github.com/user/homebrew-repo
はbrew tap user/repo
と書くこともできます.
gitが解釈できるURLなら,フルのURLを指定することで他の場所からもtapできます.
Homebrew/coreはデフォルトでtapされているので,公式リポジトリに取り込まれているパッケージは,Homebrewをインストールした時点でtapすることなくインストールできます. Homebrew/coreへ自分のformulaを取り込んでほしい場合は,PRを送って取り込んでもらう必要がありますが,PRを作ったりするためのコマンドもbrewに用意されているので,brewのエコシステムの中だけでできるようになってます. ただし,取り込んでもらうためには,Acceptable Formulaeを満たす必要があります.
cask
caskとは「大樽」という意味で,バイナリのみ提供されるパッケージを意味します.例えば次のようなものです.
- macOSアプリケーション
- フォント
- プラグイン
- その他のOSSではないソフトウェア
caskはHomebrew(自家醸造)できないもので,Homebrewとしては推奨しておらず,拡張扱いです. Homebrew/coreにもマージしてもらえません.
コマンドも拡張形式(brew cask hoge
)ですし,
インストール先はcellarとは異なる場所(/usr/local/CaskRoom)になります.
Homebrewのパッケージ情報のupdate
Homebrewの本体はここに入っています.
$ brew --repository
/usr/local/Homebrew
これはHomebrewのGitHubリポジトリをcloneしたもので,brew update
した時にpullされてパッケージ情報などが更新されます.
$ cd $(brew --repository) && git remote get-url origin
https://github.com/Homebrew/brew
では,パッケージをインストールする前に毎回brew update
をしないといけないかというと,その必要はありません.
以下のHomebrewの設定によって,インストール時に自動でupdateしてくれます.(デフォルトでは,前回のupdateから300秒経っていたら自動でやってくれます.)
- HOMEBREW_AUTO_UPDATE_SECS (Default: 300)
- HOMEBREW_NO_AUTO_UPDATE (Default: 0)
逆に勝手にやってほしくない場合は,これらの設定を変えることで制御できます.
cf. Is it possible to `brew install` without updating? · Issue #1670 · Homebrew/brew
また,brew upgrade
をすると,全部のパッケージがupgradeされてしまいますが,
upgradeさせたくないパッケージがある場合は,次のコマンドで固定することができます.
$ brew pin <formula>
$ brew unpin <formula>