公開日: 2023年7月28日

packages と ports を併用する前にやっておくこと

ソフトウェアのインストールやアップグレードにおいて、packages と ports をいいとこ取りして利用したいと考えるのは自然だと思います。ところが FreeBSD ハンドブック 第 4 章を読むと packages と ports の併用は推奨されないことがわかります。それはなぜなのか?じゃあどうすればいいのか?について考えてみました。

packages と ports についてはそれぞれ下記の記事も参考にしてください。

なぜ packages と ports の併用は駄目なのか?

FreeBSD ハンドブック 4.5 節には次のように書かれています。
Ports Collection をインストールして使用する前に、一般的には、 ソフトウェアのインストールに、pkg でダウンロードしたバイナリパッケージと Ports Collection を組み合わせて使うことはあまり良いことではないことを知っておいてください。pkg は、デフォルトでは ports ツリーの (HEAD ではなく) quarterly ブランチリリースを追いかけます。 HEAD の port と対応する quarterly ブランチの port の依存関係は異なる可能性があり、そのため pkg でインストールされた依存関係と Ports Collection の依存関係の間で競合が起きることがあります。

ports ツリーは Git で管理されており、主流である Latest ブランチと、そこから四半期ごとに枝別れする Quarterly ブランチがあります (図 1。筆者の調査に基づいて作成したので多少まちがいがあるかもしれませんが、だいたいのイメージで捉えてください)。Latest ブランチは Git 上では main というブランチ名が付いており、上の引用文中の「HEAD」というのは main ブランチの直近のコミットを指しています。Quarterly ブランチは毎年 1、4、7、10 月に main から分岐して、その年の西暦 4 桁と Q1 ~ Q4 をくっつけた名前が与えられます (例: 2023Q3)。その時点で、それまで使われていた古い Quarterly ブランチの更新はストップします。Quarterly ブランチには、(例外があるかもしれませんが基本的には) 新機能の追加は行われず、バグフィックスやセキュリティ対策などに限って Latest ブランチから取り込まれます (Git でいうところの「チェリーピック」というやり方で)。

図 1: ports ツリーのブランチ (2023 年 7 月現在の直近のみ)
図 1: ports リポジトリのブランチ (2023 年 7 月現在の直近のみ)

そして、デフォルトでは ports は Latest ブランチを、packages は Quarterly ブランチを追いかけます。ここで、とあるソフトウェア A に対して Latest ブランチに何らかの新機能が追加されたとします。A に依存する別のソフトウェア B も Latest ブランチで A の新機能に対応したとします。このような状況で、A を packages で、B を ports でインストールすると、A は (Quarterly ブランチでビルドされたバイナリファイルがインストールされたので) まだ新機能に対応しておらず、B からその機能を呼び出すことができなくなります。それによってどのような障害が発生するかはケース・バイ・ケースで予測困難と思われますが、とにかくこのようにして依存関係が壊れていきます。

packages と ports を併用したいときの対処方法

とはいえ packages と ports を併用したい場面はいろいろあると思います。どうすればいいんでしょうか?引き続き FreeBSD ハンドブック 4.5 節から引用します。

もし、Ports Collection と pkg を組み合わせて使用しなければならないのであれば、Ports Collection と pkg が同じ ports ツリーのブランチを使用していることを必ず確認してください。
つまり、
  1. packages が Latest ブランチを追いかけるようにする。
  2. ports が Quarterly ブランチを追いかけるようにする。
のどちらかを選んで、そのように設定を変えればよい、ということです。

ただし、ports ではオプションのカスタマイズを行わない (デフォルトオプションのままビルドする) ことが前提です。オプションのカスタマイズを行ってしまうと、ブランチを合わせたとしても依存関係の問題は残ります (もちろん、依存関係に実害のないオプションもあると思いますし、どのような影響があるかを把握したうえでカスタマイズするならかまわないと思いますが)。

また、細かいことを言えば、ports ツリーのリモートリポジトリにコミットされてから、それがビルドされ packages リポジトリに格納されるまでの間にタイムラグがあるはずなので、ブランチを合わせたとしても packages と ports を完全に同期させることはできないと思われますが、そこは気にしないことにします。

さて、どちらのブランチを追いかけるか?についてですが、個人でやりたい放題ができるスタンドアロンマシンなら好きなほうでよいと思います。サーバー用途のマシン等で安定性を重視するなら Quarterly ブランチがよいと思います。以降でそれぞれの場合の具体的な設定方法を説明します。

Latest ブランチを追いかける場合

ports は単にリモートリポジトリから clone してくれば Latest ブランチになっているので、設定変更の必要はありません。

packages はデフォルトで Quarterly ブランチになっているので、Latest ブランチへの切り替えが必要です。具体的には FreeBSD.conf というファイルを編集しますが、オリジナルの /etc/pkg/FreeBSD.conf ではなく、これを /usr/local/etc/pkg/repos/ にコピーして編集してください。

# mkdir -p /usr/local/etc/pkg/repos/
# cp /etc/pkg/FreeBSD.conf /usr/local/etc/pkg/repos/FreeBSD.conf

コピーしたファイルの 2 行目 ("url:" から始まる行) の "quarterly" を "latest" に書き換えます。

/usr/local/etc/pkg/repos/FreeBSD.conf
FreeBSD: {
  url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",
  mirror_type: "srv",
  signature_type: "fingerprints",
  fingerprints: "/usr/shared/keys/pkg",
  enabled: yes
}

これで Latest リポジトリに切り替わった packages を利用できるようになりましたが、その前に、ローカルに保存されている Quarterly なリポジトリカタログを Latest のものにアップデートしておきましょう。

# pkg update -f

ちなみに、リポジトリカタログのアップデートはpkg installpkg upgradeの際にも暗示的に実行されます。

Quarterly ブランチを追いかける場合

packages はデフォルトで Quarterly なリポジトリを見に行くので設定変更の必要はありません。

ports はデフォルトで Latest ブランチになっているので、Quarterly ブランチへの切り替えが必要です。具体的には、すでに Latest ブランチ (main ブランチ) を clone してあるなら、git switchで最新の Quarterly ブランチに切り替えます。この記事を書いている 2023 年 7 月現在では、2023Q3 が最新なので、次のようになります。

# cd /usr/ports
# git switch 2023Q3
# git branch
* 2023Q3
  main

または、新しくcloneするのであれば Quarterly ブランチを指定してcloneすることもできます。

# git clone -b 2023Q3 https://git.freebsd.org/ports.git /usr/ports
# cd /usr/ports
# git branch
* 2023Q3

ところで、上にも述べたように、Quarterly ブランチは四半期ごと (毎年 1、4、7、10 月) に main ブランチから枝分かれして 2023Q1、2023Q2、2023Q3、... というように名前が与えられます。新しい Quarterly ブランチが作成されると、それまで使われていた古い Quarterly ブランチはその時点で更新がストップします。というわけで四半期ごとに次のようにして新しいブランチに切り替える必要があり、ちょっと面倒ではあります。

# git switch 2023Q4

もしかしたら何かうまいやり方があるのかもしれませんが、よく知らないのでここまでにしておきます。