miseでCocoaPodsを管理してみた
mise でrubyを導入するようにしてみた。その流れで、脱Bundlerというほどでもないが CocoaPods をmise経由で導入してみることにした。
miseはGemパッケージのインストールも使えるという。iOS向けの開発をしている自分にとって、最も身近なruby製のツールだ。
環境
- mise: 2025.7.10 macos-arm64 (2025-07-14)
- ruby: 3.4.4 が mise によってグローバルインストール済み
試行錯誤の記録
Gemパッケージをインストールしてみる
mise settings experimental=true
が必要だと言われた。
mise use -g gem:cocoapods
たったこれだけでインストールされた。
type -a pod
# pod is /{ホームディレクトリへのパス}/.local/share/mise/installs/gem-cocoapods/1.16.2/bin/pod
どうやら mise/installs
に gem-
のプレフィックスが付いて導入されるらしい。中身を確認してみた。
# インストール先まで移動
cd /{ホームディレクトリへのパス}/.local/share/mise/installs/gem-cocoapods/1.16.2
cat bin/pod
#!/usr/bin/env bash
GEM_HOME="/{ホームディレクトリへのパス}/.local/share/mise/installs/gem-cocoapods/1.16.2/libexec" exec /{ホームディレクトリへのパス}/.local/share/mise/installs/gem-cocoapods/1.16.2/libexec/bin/pod "$@"
GEM_HOME
を指定して libexec
配下の pod
を実行するように包んでいるらしい。libexec
配下のpod
を見てみる。
#!/{ホームディレクトリへのパス}/.local/share/mise/installs/ruby/3.4.4/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'cocoapods' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'rubygems'
# ...
基本的にRubyGemが作る内容らしい。pod以外のファイルも同じフォーマットの内容だった。ただし、冒頭の1行に着目する必要がある。
#!/{ホームディレクトリへのパス}/.local/share/mise/installs/ruby/3.4.4/bin/ruby
shebang がmiseで導入したrubyを指し示している。
つまり「rubyの環境更新だ〜」、といって 3.4.4
をアンインストールしたら壊れるということだ。
一方で、このグローバルインストールした pod
については、たとえばruby2のみが有効となる環境においても影響を受けずに実行できそうだ。
また、libexec
の他の内容確認してみる。
どうやら cocoapods
に関連するものがまとめて隔離されているらしい。いわゆるバンドルされている、ってやつだ。
pwd
# /{ホームディレクトリへのパス}/.local/share/mise/installs/gem-cocoapods/1.16.2
ls libexec
# bin build_info cache doc
# extensions gems plugins specifications
ls libexec/bin
# fuzzy_match httpclient pod sandbox-pod xcodeproj
ls libexec/gems
# activesupport-7.2.2.2 bigdecimal-3.2.3
# cocoapods-downloader-2.1 concurrent-ruby-1.3.5
# ...
つまりmiseで導入したRubyの領域にgemが置かれることはない。
複数バージョンのgemを入れたらその分だけ依存パッケージが重複するとみられるが、クリーンな運用に対する代償だろう。
消してみる
ところで cocoapods は別にグローバルに必要ではない。特定のプロジェクトで見えれば十分だ。use
の反対は unuse
である。
mise unuse -g gem:cocoapods
加えてアンインストールするかというインタラクティブな確認が発生した。消した。
# remove gem:cocoapods@1.16.2 ? Yes
# mise gem:cocoapods@1.16.2 ✓ remove ~/Library/Caches/mise/gem-cocoapods/1.16.2
なんか知らんとこから消えた。
ls ~/.local/share/mise/installs
# node python ruby usage
とりあえず消えたらしい。
ローカルインストール→ローカルユース
最小限の場所で有効にしてみる。
cd /path/to/{cocoapodsが必要なプロジェクト}
mise use gem:cocoapods
type -a pod
# pod is /{ホームディレクトリへのパス}/.local/share/mise/installs/gem-cocoapods/1.16.2/bin/pod
なんか見たことあるパスが出てきた。
どうやらmiseによってインストールされるものは installs/
に詰め込まれ、コンテキストに応じてどれが有効になるかをコントロールすることで環境を制御しているらしい。
だから使うときには mise install pkg
ではなく mise use pkg
なのかと合点がいった。まぁ、「installとは使えるようにするまで含むだろ」という観点もないことはないが、CLIに生きるときってパス通すのは自分の仕事だしな。
PATH方式と呼ばれるらしい
pod
はどのように発見されているのかというと、PATHに直接挿入されているらしい。
echo $PATH | tr ':' '\n'
# /{ホームディレクトリへのパス}/.local/share/mise/installs/gem-cocoapods/1.16.2/bin
# ...
必要なバイナリへの到達方法をPATHに挿入することでランタイム管理を実現する場合、PATH方式と呼ばれるらしい。これはプロンプトを表示する度に対応したパスをPATHに挿入することで実行可能にするという。
Shim方式
その他にはShim方式と呼ばれるものがあり、miseは対応しているらしい。
PATH方式は対話型シェルに適しているが、IDEからの利用には適していない。たとえばRunで実行したい node
コマンドがPATHから見つけられない、などだ。
そこで、一旦コマンドすべてのシンボリックリンク相当になるものを詰め込んだディレクトリを用意し、それを参照させる。
ls -l /{ホームディレクトリへのパス}/.local/share/mise/shims
# bundle -> /{ホームディレクトリへのパス}/.local/bin/mise
# bundler -> /{ホームディレクトリへのパス}/.local/bin/mise
# ...
# pod -> /{ホームディレクトリへのパス}/.local/bin/mise
# ...
ここに mise
でインストールしたコマンドが全て列挙されるが、すべて同じバイナリを指し示す。叩いたコマンドと基点のパスに基づいてコマンドが有効かどうかを別途判定する、ということだろう。
miseのドキュメントShimsに詳しい。
感想
こいつぁ良さそうだ。
メンテナンスモードにも入って、いよいよ役目を終えつつあるCocoaPodsだが、これは依存関係が多い。グローバルに入れると環境が汚れるし、かといって必要なプロジェクト配下にだけbundlerで配置するとあちこちで同じようにゴチャ付いた vendor/bundle
が生成されてしまう。
パッケージ単位で、隔離された環境が状況に応じて管理されるため、ほどよく無駄がない。
Discussion