search
LoginSignup
2

More than 1 year has passed since last update.

posted at

updated at

FreeBSD Ports Collection における OPTIONS 機能の紹介 - OPTIONS_SET/OPTIONS_UNSET/NO_DIALOG の活用と実践 -

はじめに

2020年にもなって、まだコンパイルしてるの?

と言われるくらい、現在のFreeBSDでは、ベースシステムはもちろんのこと、サードパーティ製アプリのバイナリパッケージの使用(インストール)が進んできました。
実際、軽くセットアップして使う分には十分過ぎるほどバイナリパッケージが用意されていると思います。
ただまぁ自分の場合、ガッチガチにカスタマイズして使ってる関係で、バイナリパッケージに満足することができず…と言う事情もあり、ポーツコレクションのカスタマイズ方法についてまとめてみました。

なおポート(FreeBSD ports)とは何?については参考文献をご覧ください。すみません。

動作対象環境

2020年現在、導入から5年以上経過していることもあり、現在サポート対象となっている全てのFreeBSD環境で使用できます。まぁおおよそバージョン10以降で考えてもらえばいいかと。

OPTIONSという仕組み

OPTIONS(/usr/ports/Mk/bsd.options.mk)という仕組みの導入1により、ポートを使用してサードパーティ製アプリをコンパイルする時の、カスタマイズする方法が統一されました。

これが導入される前後でMakefileの書き方が変わっており、OPTIONS導入以前の仕組みは(ほぼ)残っていません2

いや厳密に調べてみると残っているというか、使われてたりすることもありますが、あまりに特殊な、ハッキング的カスタマイズ用途で使われたりするので、今回はスルースキルを発動することにします。

OPTIONSとは

各ポートのカスタマイズ出来る項目のオン・オフを制御するための仕組みで、以下のコントロールを行うための仕組みを提供しています。

  • 何をカスタマイズできるのか(オプション名)
  • どのような機能であるか(解説)
  • 何をデフォルトで、オンにするかオフするか(デフォルト値)
  • 振る舞い(依存関係の明示やインストール方法等)についての補助

ポートメンテナーはこれらをMakefileに記載することにより、利用者はオンオフを選ぶだけでカスタマイズできるようになっています。

ダイアログでの選択

コンパイル時にダイアログが表示され、これらカスタマイズをどうするかインタラクティブに取捨選択ができます。
具体的には以下のコマンドにより設定できる項目となります34

コマンド実行例
make config
make config-recursive
make showconfig
make showconfig-recursive
make rmconfig
make rmconfig-recursive

特に、一度ダイアログで確定してしまった場合、make config を明示的に実行するか、あるいは、新しくオプションが追加されたときしか、ダイアログを表示することはありません。
またデフォルトに戻したい場合は make rmconfig とすることで、ダイアログで設定した内容が削除されます。

グローバルな設定

/etc/make.conf 中に記載することで、大域的にカスタマイズ内容(オン・オフ)を定義することができます。
X11が不要である場合や、圧縮アルゴリズムとしてLZ4を使用したいなど、全てのポートで統一的に設定を図りたい場合に設定します。

/etc/make.conf の設定例
OPTIONS_SET+=   LZ4 LZO LZO2 LZMA ZLIB ZSTD BROTLI
OPTIONS_UNSET+= X11 CUPS GDBM TEST DEBUG TESTS

グローバルなポート別設定

/etc/make.conf 中には更に、ポート別にカスタマイズを定義することができます。
たとえば、基本的にはドキュメント類はインストールしておきたいが、そのドキュメントをインストールするためにTeXまでインストールし始める、みたいなケースではドキュメントのインストールを諦めたいのが心情かと思います。
そのようなケースでは ${OPTIONS_NAME}_SET ないしは ${OPTIONS_NAME}_UNSET で定義してやります。

/etc/make.conf の設定例
emulators_open-vm-tools_UNSET= DOCS FUSE LIBNOTIFY

${OPTIONS_NAME} は各ポートで make -VOPTIONS_NAME を実行して得られる文字列となります。
上記の例のように、中には変数名に -+ を含むことがあるようですが、Makefile的には問題無いようで。

なおOPTIONS導入当時 OPTIONS_NAME ではなく UNIQUENAME を使う、とありましたが、他の機構と衝突するとのことで、OPTIONS_NAME に変更になっています。

bsd.options.mk でのデフォルト設定

bsd.options.mk の中で以下の設定についてはポート側のデフォルト設定に関係無く、有効化されています。

  • DOCS
  • NLS
  • EXAMPLES
  • IPV6

ダイアログの選択肢に DOCS があるのに、ポート側のデフォルト設定には DOCS が無いにもかかわらず、実際には DOCS がオンになっているのは、これの影響となります。

OPTIONSの優先順位

  1. /etc/make.conf${OPTIONS_NAME}_SET_FORCE${OPTIONS_NAME}_UNSET_FORCE
  2. /etc/make.confOPTIONS_SET_FORCEOPTIONS_UNSET_FORCE
  3. make config
  4. /etc/make.conf${OPTIONS_NAME}_SET${OPTIONS_NAME}_UNSET
  5. /etc/make.confOPTIONS_SETOPTIONS_UNSET
  6. make WITH="オプション1 オプション2..." WITHOUT="オプション1 オプション2..." と指定したケース5
  7. bsd.options.mk
  8. MakefileMakefile.local

なお、_SET が処理されてから _UNSET の処理が行われるので、優先順位は _UNSET_SET となり、_UNSET の効果の方が強くなります。

カスタマイズ不要!

つまりパッケージシステムはカスタマイズ無しでコンパイルされてるはずで、ダイアログの表示無く処理されているはずです! 6

実際にそのようなオプションはあります。/etc/make.conf に下記のように書いておけば、全てのポートのダイアログ表示無し(≒カスタマイズ無し)でコンパイル始めます。

/etc/make.conf の設定例
NO_DIALOG= yes

実際にはダイアログの表示がスキップされるだけで、以前に実行した make config の結果や先に説明した OPTIONS_SETOPTIONS_UNSET 等の設定が反映された上で処理されます。
そういう意味では完全にデフォルトではないですが、バイナリパッケージ互換の運用はこうすることで提供可能であることが分かるかと思います。

ports-mgmt/portconf

portconf/usr/local/etc/ports.conf という設定ファイルで各ポートのカスタマイズ設定を記述できるツールです。

インストール時に /etc/make.conf へのフックを入れ、/usr/local/etc/ports.conf/usr/local/libexec/portconf/etc/make.conf と連携することで、あたかも最初からそこに設定が書いてあったがごとく振る舞います。よってこのフックを /etc/make.conf から削除してはいけません。

やってることは設定ファイル中のポートディレクトリ名とカレントディレクトリを比較(グロブでマッチング)して、該当すればその内容を取り込む、という動きになります。

例えば下記の例では、/usr/ports/databases/sqlite3 のディレクトリで /usr/local/libexec/portconf を実行してやれば、|NO_DIALOG=yes と表示されることが確認できると思います。

/usr/local/etc/ports.conf の設定例
databases/sqlite3: NO_DIALOG=yes
lang/perl5.*:      NO_DIALOG=yes

本例でのSQLite3のように、かなり細かくカスタマイズできるのですが、バイナリ互換性を失うようなカスタムが後から入ることもあり(その場合デフォルトオフで入る)、下手にカスタマイズしない方がいい類いのポートとなっています。

OPTIONSとの使い分け

OPTIONSの場合 ${OPTIONS_NAME}_SET${OPTIONS_NAME}_UNSET のように、ポート毎(${OPTIONS_NAME})に OPTIONS_SETOPTIONS_UNSET が明示できます。しかし NO_DIALOG のようなグローバルな名前だと、ポート個別に設定することはできません。よってそういうところでportconfを使用します。

もちろん ${OPTIONS_NAME}_SET${OPTIONS_NAME}_UNSET を使用せず OPTIONS_SETOPTIONS_UNSET を使用するために、ports.conf に記述してもいいのですが、portconfがインストールされてない環境で構築した場合の影響が多大なので、あまり影響ないところで使いこなすのが粋な使い方となります。

上記理解が済めば、それ以外の指定方法についても pkg info -D portconf を実行して、内容を読めば書けると思います。

よくある質問とその答え

Q.ポートからコンパイルしたものとバイナリパッケージは共用運用できないの?

全てのポートを NO_DIALOG 付でかつカスタマイズ無しの時に可能です。
パッケージの反映が遅いな、ポートからコンパイルしちゃえ、という運用をしたいなら、カスタムしないようにしてください。

Q.カスタムしたポートとバイナリパッケージは共用運用できないの?

基本できないと思ってください。限定して運用すればできることがあるかもしれませんが、試行錯誤が必要です。またその試行錯誤の結果が今後も保証される保証はありません。
カスタマイズした場合に、その機能の有効または無効によって、あるべき機能が無かったり、欲しい機能が無いことがあえります。ポートの依存関係では分からず、インストール後(ランタイム)に判明する場合があります(バイナリ互換性が無い)。
この種の変更(カスタマイズ)はバージョンアップによる影響よりも大きいことがあります。

まあちょっと脅しになってしまいましたが、ミドルウェア(特にライブラリ)と言われるポートで「なければ」、アプリケーションと言われるポートで「あれば」、問題無く動くと思います。

Q.オンとオフ、SETUNSET 何か飛躍があるような気がします!

A.大丈夫だ。問題無い。その認識は正しい。ちゃんと説明するべきであるが疲れたので寝る。

参考文献


  1. 2012年05月以降。もちろん仕組みが導入されてすぐ、全てのポートが対応したわけではないが、既に8年以上経過…。 

  2. WITHOUT_X11 等のメジャーなカスタマイズ設定は…残って…いませ…ん(正確には間違った使い方です)。 f( --; 

  3. config は設定、showconfig は現在の設定の閲覧、rmconfig は設定の削除。 

  4. -recursive はそれぞれ依存関係を追って処理します。 

  5. WITH で指定されたオプションは SET され、WITHOUT で指定されたオプションは UNSET されます。 

  6. パッケージビルドシステムの運用について軽く調べたのですが、どう運用してるという情報は無く、使用しているツールと、カスタマイズなんてしてられないだろう?という予測からの,、個人的かつ無責任な断定。 

  7. 日本語版の記述が古いため英語版を読むときの参考にしてください。特にpkgngについての記述は完全に無視してください(pkgngになってからずいぶん時間が経過しているため)。 

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
What you can do with signing up
2