ZRouterでのバイナリ追加方法

FreeBSDをmipsなルータのFlashに焼くために[ZRouter](http://qiita.com/yamori813/items/2fc5b14648029bb4730f)でカーネルと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もどき」と呼ぶことにする。

```Make
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)

```Make
post-configure:
        @${REINPLACE_CMD} -e 's|-L/usr/lib||g' ${WRKSRC}/iked/Makefile
```

* ビルド用にコマンドをビルドして利用する場合は/usr/bin/ccでコンパイルする(例:www/lighttpd,lang/mruby)

```Make
# 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という古くからあるソースはどうにかビルドできました。