FreeBSDをmipsなルータのFlashに焼くためにZRouterでカーネルとrootfsを作っているが、rootfsにバイナリを追加する方法を考えてみる。
現状
ZRouterではprofileという仕組みで追加のバイナリなどを管理している。これの実体はtargetかportsというディレクトリにあり、targetはFreeBSDのソースツリーの一般のプログラムと同じようにコンパイルしてコピーする仕組みで、portsはFreeBSDのportsを使った仕組みになっている。targetは同じディレクトリにファイルを置く事もできるが、ほとんどがcontribといディレクトリに実際のファイルを置いている。元々のZRouterのportsは/usr/local/binではなく、/usr/binにファイルを置いていた。ZRouterにはpackagesというディレクトリがあるが中身が空だ。
問題点
- targetは新たにFreeBSD風のMakefileを作る必要がある
- portsはFreeBSDのportsのMakefileがそのまま流用できない
- configureを使うportsの場合、hostの設定を使ってしまいうまく動かない事がある
- ZRouterは旧pkgの頃に作られていて、現在のpkgでインストールする方法が動かない
- ZRouterのportsのワークディレクトリはアーキテクチャを区別してない
- 本体のportsも同じだがgithubにあるファイルだけでリリースアーカイブを作らないプロジェクトのビルドができない
- 本来のportsはStageありとなし(古いもの)がありインストール方法が違う
- オブジェクトパスの変更が行われてtargetがZRouterのツリーでビルドされるようになってしまった。これにより誤って違うアーキテクチャのバイナリが入ってしまうことがある。(追加)
考察
新たに仕組みを作るのはあまり現実的ではない
FreeBSD/mipsはビッグとリトルのエンディアンがある
/usr/includeを使ってしまいクロスビルドしてもホストとターゲットに差がなければ問題にはならないかも
リソースの制限やなんらかの要因でamd64では動いてFreeBSD/mipsでは動かない事もある
qemuな環境でビルドすれば完全なパッケージが作れるが、環境を作るのが大変で、コンパイルコストも大きい。またビルドに利用するツールまで用意する事になるので、とっても大変
embedな環境はpkgの追加はできないのでpkgにする必要性がないかも
portsは元々pkgを作成するための仕組みであり、pkgを使わないZRouterでは位置づけが違う
manのファイルなどいらないものも多い
追加の対象は限定的
portsと同じコードベースだと脆弱性なの問題の対応がしやすい
複数の依存があるようなものは、頑張らないで、ほかの選択肢を考えた方がのかも
当面の方針
- 本家portsをできるだけ再利用する
- 出来るだけバージョンは本家portsを追従する
- hostシステムを壊さないようにroot権限は使わない
- configureを使っている場合はクロスコンパイルのため以下を追加する(ARCHはビルドホストのamd64が入り、実はこれは間違えでhostはターゲットのアーキテクチャを指定するのが正しいが、soが作られないなどの問題があるので、こうしている。)
CONFIGURE_ARGS+=--host=${ARCH}-portbld-freebsd
- openvpnはプログラム中でもhostの値を使っていたので、ZARCHで設定するようにしました。
# ./openvpn
OpenVPN 2.5.3 mips-portbld-freebsd [SSL (OpenSSL)] [LZO] [MH/RECVDA] [AEAD] built on Mar 11 2022
ファイルのコピー(インストール)はMakefileのdo-install:に書く- do-installをマクロで実行している場合はstageにコピーされたファイルをpost-installでターゲットのrootfsにコピーするようにします。
- do-installを自前で処理している場合は、それを書き換えてターゲットのrootfsにコピーする。
- ライブラリファイルは必要な物だけコピーする。
- ライブラリの場合はヘッダーもコピーして、依存するものはこれを参照するようにする。
- pkgconfのpcファイルもコピーする。
- ZRouterの標準のビルドはpkgに依存しないが、ほとんどのportsは依存する。また/usr/portsへの依存も発生する。
-
OPTIONはdbへの登録のためのroot権限が必要になるので全部外す。DBは独自の持つようにしたので、OPTIONは使えるが、原則は外す。 - 本家のportsと区別するために「portsもどき」と呼ぶことにする。
post-install:
${INSTALL_LIB} ${STAGEDIR}${PREFIX}/lib/libexpat.so.1.6.2 ${ZPREFIX}/lib/libexpat.so.1
cp ${STAGEDIR}${PREFIX}/include/*.h ${ZPREFIX}/include/
cd ${ZPREFIX}/lib;ln -s libexpat.so.1 libexpat.so
- pkgは使わない
-L/usr/libをconfigureがMakefileに入れてしまう場合はpost-configure:で削除する(例:security/racoon2)
post-configure:
@${REINPLACE_CMD} -e 's|-L/usr/lib||g' ${WRKSRC}/iked/Makefile
- ビルド用にコマンドをビルドして利用する場合は/usr/bin/ccでコンパイルする(例:www/lighttpd,lang/mruby)
# for lemon cross-compiling
CONFIGURE_ENV+= "CC_FOR_BUILD=/usr/bin/cc"
- ライブラリなど依存が発生する場合はtargetでも良いかも(例:mrubyとtarget/lib/libuv)
- gmake, autoconfなどはpkgでインストールする。この時/usr/portsのファイルとバージョンが違う場合に問題が起きることがあるのでportsをupdateしておく。
- 設定などは環境変数で引き渡す方法もある(例:lang/mrubyのMRUBY_CONFIG)
- configureが何をチェックしているかはそれぞれなので、臨機応変に考える
- 追加のファイルは/usr/local以下にコピーする
- 完全を狙ってコストをかけすぎない
configure
configureがチェックは以下のような事が考えられる
- 使用するライブラリの有無
- コンパイラーの種類
- OSの種類
- CPUのビット数
- などなど
ZRouterのportsでのconfigureの実行は、半端な状態で/usr/local/を参照するのだが、実際は別のディレクトリにライブラリがあったりする。またコンパイラのチェックも正しく行われない。自分の必要なものしか追加しないのだが、ぼちぼち整理したい。
当初configureがhostのccを使って動いてしまっていたので、直しました。
いろいろ
ZRouterの連絡網がircなので、ircクライアントのビルドを試してみました。最初にirssiを試したのですがあまり依存は多くなかったのですがglibや他のライブラリがクロスビルドが大変だったので、あきらめました。次にweechatを試してみたのですが、こちらはlibcurlとgnutlsの依存があり、これがいろいろな依存を作ってしまっていたので、あきらめました。bitchxという古くからあるソースはどうにかビルドできました。