OpenWrt ビルドシステムに関するメモ

(👉 公式ドキュメント

ビルドシステム
👉 基本
SSD/HDD の容量は 10~15GB 以上必要。
仕組みとして大きく分けると 3 段構成になっている:
  1. ホスト(実際に作業する PC)側用のツールチェイン
  2. ターゲット(OpenWrt をインストールするルーター)側用のツールチェイン
  3. パッケージ化したりファームウェアのイメージ化する
ツールチェインがホスト側・ターゲット側の 2 段構成になっている理由は、クロスコンパイルを可能にするため。まず、ホスト側ツールチェインを使って、ターゲット側 OpenWrt 用のツールチェインをビルドする。そうやって生み出されたターゲット側 OpenWrt 用のツールチェインを使って、実際に OpenWrt で使われるバイナリーイメージをビルドする(つまり、ホスト側のツールチェインは、単に、OpenWrt 用のツールチェインをビルドするためだけに使う。そして実際の OpenWrt の各パッケージは、ターゲット側 OpenWrt 用のツールチェインによってビルドしていく。このようにして一種の〝ビルド環境のエミュレーション〟のような仕組みとなっている)。
そうして、第 3 段階で、ビルド済みの各パッケージを .ipk の形にしたり、ファームウェアイメージにしたりして、ルーターにインストールするという流れ。
👉 セットアップ方法
GNU/Linux が標準の環境。基本は Git が使えるようにして、その他は、ツールチェインのビルドに必要な C コンパイラの環境を整えればよい。Debian / Ubuntu 系では apt を使って、build-essential clang flex bison g++ gawk gcc-multilib g++-multilib gettext git libncurses-dev libssl-dev python3-distutils rsync unzip zlib1g-dev file wget あたりを用意すればよい。
👉 セットアップ方法(macOS)
macOS は本来、非推奨。敢えて使いたいマニア向けの解説。
👉 セットアップ方法(WSL)
Windows は本来、非推奨。敢えて使いたいマニア向けの解説。
👉 使用法
基本で説明した流れを、実際に git と make コマンドによって行なう具体的な作業についての解説。
  1. git でレポジトリーをコピーし、ブランチまたはタグで特定のバージョンを選択
  2. フィードをアップデート(srcipts/feeds update -a)・インストール(srcipts/feeds install -a)して、パッケージリストの状態を最新の状態にする(必須ではないが、これをやらないと、パッケージリストの状態が最小限のものとなり、menuconfig 時に表示されるパッケージも限定される)
  3. make menuconfig でターゲット用のプロファイル(Target Profile、ビルドの対象とするルーター)を選択する
  4. make defconfig で、先に menuconfig で選んだターゲット用のデフォルトの設定状態(依存関係等)を反映する
  5. make (world)で、menuconfig で選んだターゲット用に、実際のビルドを行う(かなりの時間を要する処理)
  6. 作業ディレクトリの bin 以下に、ビルドされた結果のバイナリーが生成される
その他、make (world) する場合、マルチコア CPU を活用する場合は、-j オプションを使って
make -j $(($(nproc)+1)) download world
などとするとよい。nproc はコア数を返すコマンド、+1 のようにする理由は、コア数を上回るスレッド数とすることで、アイドル状態のコアが出現しないようにするため。シングルスレッドの場合はソースコードを都度ダウンロードするが、マルチスレッドだとスレッドごとに進行がまちまちになるためエラーの元となるので、download によってビルドに先立って全ての依存関係を先にダウンロードするために必須となる。download に続いて実際の make を行うため、world は省略できずに明示する。
また、ビルド途中でエラーが発生する場合には、V=s オプションで詳細なログを表示させると役に立つ。
👉 フィード
(割愛)
👉 技術リファレンス
(割愛)
👉 単体パッケージのビルド
ファームウェア全体を更新してルーターにファームウェアを丸ごと書き直すのではなく、単体のパッケージのみを更新したい場合のやり方。
  1. menuconfig 時に、ターゲットプロファイルを選んだ上で、目的とするパッケージと、それが依存するパッケージ群のみを選択する。依存関係がわからない場合は、ルーター上で opkg info <パッケージ名> をして情報表示させればよい。
  2. tool(make tools/install)と toolchain(make toolchain/install)のみを用意する。
  3. 依存するパッケージ群を先にコンパイルする:
    make package/<依存パッケージ名>/compile
    (ちなみにホスト用の被依存ツールをコンパイルする場合のパスは make package/<依存パッケージ名>/host/compile となる)
  4. 目的のパッケージをコンパイルする:
    make package/<パッケージ名>/compile
  5. パッケージ情報に反映させる(make package/index)
作業ディレクトリの bin 以下に、目的とするパッケージが生成される。
その他、カーネル・モジュールの単体ビルドのやり方についても説明されている(割愛)
👉 OpenWrt 上での OpenWrt のビルド
あくまで実験的なもので、技術的にはそれほど困難ではなく、ハードウェアの性能的に実用性が低い。デフォルト状態の OpenWrt OS に、何を足せばできるようになるのかが解説してある。敢えてやりたいマニア向け情報。
👉 クロスコンパイル
OpenWrt のパッケージに含まれていないプログラムをソースからクロスコンパイルする方法。基本は「使用法」の流れに沿う。
  1. OpenWrt 用のツールチェイン(staging_dir/toolchain-<アーキテクチャー名>_gcc-<gcc バージョン>_musl 以下)の bin ディレクトリーにある C コンパイラー(gcc)を見つけて、その bin ディレクトリーをホスト PC 側の PATH に追加してセット(export)する
  2. STAGING_DIR にはツールチェイン全体のディレクトリをセット(export)する
  3. コンパイルしたいプログラムのソースコードをダウンロード・解凍して、そのディレクトリーに移動する。
  4. PATH をセットした gcc を使ってそのプログラムをコンパイルするが、コンパイル(make)に先立って configure する際に --build=<アーキテクチャー名>-unknown-linux-gnu --host=<アーキテクチャー名>-openwrt-linux-musl をオプションとして使う。
    • --build= オプションを確認するためには config.guess コマンドを使う
    • クロスコンパイル設定が有効化どうかは configure のメッセージ中の 'checking whether we are cross compiling... yes' で確認できる
  5. 通常、GNU configure を使う場合には問題(必要)ないが、必要であれば、コンパイル(make)時に、CC と LD を環境変数として渡す:
    make CC=<アーキテクチャー名>-openwrt-linux-musl-gcc LD=<アーキテクチャー名>-openwrt-linux-musl-ld
  6. コンパイルされて出来あがったプログラムはソースを解凍した作業ディレクトリーのどこかにある。find -iname <プログラム名> を使うなどする。
  7. 実際のそのプログラムファイルを実行してみて、ちゃんとクロスコンパイルできているか確かめる。
  8. コンパイルがヘッダーまたは共有オブジェクトが見つからないためにエラーとなった場合には、CFLAGS や LDFLAGS 変数を上書きする必要があるかもしれない。staging_dir/target-<アーキテクチャー名>_musl 以下の usr/include と usr/lib を make 時に指定する。
  9. その他、デバッグする場合(割愛)
無事にコンパイルできたならば、実行バイナリーや関連するライブラリーを実際の OpenWrt ルーターにコピーしてテストする。この場合、ライブラリーの場所が通常と違う場合は、LD_LIBRARY_PATH 変数を指定してバイナリーを実行する必要があるかもしれない。
さらに .ipk 化したい場合には、ツールチェインの説明の範疇から外れるので、👉 独自のパッケージの作成、👉 依存関係の利用を参考のこと。
👉 イメージのビルドについての簡易ガイド
(割愛)
👉 ビルド環境の使い分け方
(割愛)
👉 SDK の使い方
SDK はクロスコンパイルする場合に、ツールチェインをゼロからコンパイルしなくて済むようにする目的で用意されたコンパイル済のツールチェインのことである。
  • 【可能】バイナリーと機能上の互換性を維持しながら独自のソフトウェアをコンパイルする
  • 【可能】特定のパッケージの新しいバージョンをコンパイルする
  • 【可能】既存のパッケージに独自のパッチを当てたり、異なる機能でコンパイルする
  • 【不可能】ファームウェア全体をクロスコンパイルするためのツールチェインとして使うことはできない
SDK の用意の仕方は、menuconfig で Build the OpenWrt SDK オプションを有効にしてコンパイルするか、OpenWrt のサイトのファームウェアイメージと同じディレクトリー(ex. WZR-HP-AG300H の場合 v23.05.2)の Supplementary Files の中からコンパイル済のものがダウンロードできる。
元々存在するパッケージに対して自分のカスタム版のパッケージに置き換えて使いたい場合は、feeds.conf.default の元のパッケージよりも前の行に追記する必要がある。
パッケージリストの反映方法:
  1. scripts/feeds update -a(通常通り)
  2. scripts/feeds install <パッケージ名>(カスタム版パッケージ用)
  3. scripts/feeds install -a(通常通り)
SDK の使い方:
  1. パッケージの選択は menuconfig して行う。
    余計な他のパッケージのビルドを避けるため、Global Build Settings で、
    • Select all target specific packages by default
    • Select all kernel module packages by default
    • Select all userspace packages by default
    を無効化する。その上で、目的とするパッケージを選択(M)する(依存パッケージも連動して選ばれる)。そうして .config を保存してメニューを終える。
  2. 目的とするパッケージをコンパイル(make)する(参考:単体パッケージのビルド):
    • make package/<パッケージ名>/download パッケージのソースのダウンロード
    • make package/<パッケージ名>/prepare ソースを解凍したりパッチをインストールして当てたりする
    • make package/<パッケージ名>/compile コンパイルする
    • make package/<パッケージ名>/clean 作業に使ったソースを削除する
    • make package/index パッケージ情報に反映させる
    コンパイルによって作成された .ipk は SDK ディレクトリー以下の bin/packages と bin/targets に置かれる。
👉 パッチの扱い方
(割愛)

コメント

このブログの人気の投稿

清水俊史『上座部仏教における聖典論の研究』

シークエンスパパともの先見の明

シークエンスパパとも 本物の霊能力