OpenWRT Closs Compile メモ
OpenWRTをインストールできたので、OpenWRT上で動くアプリケーションをコンパイルする。
OpenWRTが動いているルータ(TP-Link WDR4300 N750)はディスク容量もメモリもかなり少ないため、ルータ上でプログラムをコンパイルすることができない。
そのため、別のLinuxサーバでクロスコンパイル環境を構築し、ソースコードをビルドする必要がある。
今回はOpenWRT上で最新版のHostapdを動かすことを目標に、クロスコンパイルを実行していく。
OpenWRT SDKの準備
OpenWRT SDKとはOpenWRT用のクロスコンパイル環境が一式そろったものである。
それぞれのバージョン・アーキテクチャごとにSDKが用意されているので、自分のバージョンに合ったものをダウンロードする。
(ファームウェアイメージと同じ場所にある)
linux上でファイルを解凍。 名前が長いので変更しました。
root@ubuntu # tar -xvf OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64.tar.bz2 ... ... ... root@ubuntu # mv OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64.tar.bz2 openwrt root@ubuntu # ls -al drwxr-xr-x 12 root root 4096 Aug 17 14:40 openwrt
実はクロスコンパイル環境はこれで準備完了。
SDKが用意されているのは便利ですね。
本来ならば、自分の環境のSDKはgitのソースから自分でビルドする必要があります。
やり方は公式ページのDeveloper Guideを参照
https://wiki.openwrt.org/doc/playground/developer
"Hello,World!"のコンパイル
まずは簡単なプログラムからビルドする。
root@ubuntu # cd openwrt root@ubuntu # mkdir helloworld root@ubuntu # cd helloworld
適当に作業用ディレクトリを作成し、その中にc言語のプログラムを作成
#include <stdio.h> int main(void) { printf("Hello World\n"); return 0; }
このコードをコンパイルするのだが、Host環境のgcc(/usr/bin/gcc)でコンパイルしてはいけない。
今回はSDKの中にあるgccでコンパイルを実行する。
root@ubuntu # ../staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-gcc -o helloworld.o helloworld.c root@ubuntu # ls helloworld.o helloworld.c root@ubuntu # ./helloworld.o -su: ./helloworld.o: cannot execute binary file: Exec format error
出来上がったファイルをHost環境で実行するとformat error
で実行できない。
これはOpenWRT環境で動くファイルなので当然である。
出来上がったファイルをOpenWRT化されているルータに移す。
root@ubuntu # scp helloworld.o root@192.168.1.1:
OpenWRTルータ内でファイルを実行
root@OpenWRT # chmod a+x helloworld.o root@OpenWRT # ./helloworld.o Hello World
実行できた。
Hostapdのコンパイル
OpenWRTで使われていたhostapdは最新versionでは無く、hostapd_cliも使えない。
何か開発しようとすると使い勝手が悪いので、今回は最新版のhostapdをOpenWRT上で動かせるようにコンパイルを行う。
hostapdをダウンロードして解凍。わかりやすいようにopenwrtディレクトリ配下に入れておく。
root@ubuntu # wget https://w1.fi/releases/hostapd-2.5.tar.gz root@ubuntu # tar -zxvf hostapd-2.5.tar.gz root@ubuntu # mc hostapd-2.5 openwrt/hostapd
ほとんどのMakefileは
ifndef CC CC=/usr/bin/gcc endif ... ... ...
という感じで、明示的にコンパイラを指定しない限りはHostのコンパイラを使用するようになっている。
したがってMakefileがクロスコンパイル環境のgccを読み込んでくれるようにCCを明示しておく。
root@ubuntu # export OPENWRT_HOME=[openwrt直下のディレクトリ] root@ubuntu # export CC=$OPENWRT_HOME/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-gcc
さて、
これでmake
を実行すればhostapdのコンパイル完了。
というわけにはいかなかった。
hostapdのmake
はopenwrt/hostapd/hostapd/
直下で行う。
root@ubuntu # cd hostapd/hostapd/ root@ubuntu # make mips-openwrt-linux-gcc: warning: environment variable 'STAGING_DIR' not defined
まずこんなエラーがたくさん出てくるので、言われているとおりにSTAGING_DIR
を設定する。
root@ubuntu # export STAGING_DIR=$OPENWRT_HOME/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2
再びmake
root@ubuntu # make .... .... CC ../src/drivers/driver_hostap.c ../src/drivers/driver_nl80211.c:17:31: fatal error: netlink/genl/genl.h: No such file or directory #include <netlink/genl/genl.h> ^ compilation terminated. make: *** [../src/drivers/driver_nl80211.o] Error 1
やはりというか、途中でとまりました。
クロスコンパイル環境なので、いろいろとファイルが足りないことがある。
今回のようにヘッダーファイルが無いだけならHost環境の/usr/include/
などからひっぱてくればよい。
以下のようにssl系とnetlink系のヘッダファイルが無いというエラーがでたので、これらを引っ張ってくる。
root@ubuntu # cp -r /usr/include/netlink/ ../../staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/usr/include/ root@ubuntu # cp -r /usr/include/openssl/ ../../staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/usr/include/ root@ubutnu # cp /usr/include/x86_64-linux-gnu/openssl/opensslconf.h ../../staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/usr/include/openssl/
問題なのは共有ライブラリが無かった場合。
root@ubuntu # make ..... ..... ../../staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/../lib/gcc/mips-openwrt-linux-uclibc/4.8.3/../../../../mips-openwrt-linux-uclibc/bin/ld: cannot find -lnl ../../staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/../lib/gcc/mips-openwrt-linux-uclibc/4.8.3/../../../../mips-openwrt-linux-uclibc/bin/ld: cannot find -lssl ../../staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/../lib/gcc/mips-openwrt-linux-uclibc/4.8.3/../../../../mips-openwrt-linux-uclibc/bin/ld: cannot find -lcrypto collect2: error: ld returned 1 exit status make: *** [hostapd] Error 1
普通このようなエラーが出た場合はapt-get
とかでライブラリをとってくれば解決なのだが、クロスコンパイル環境では頑張ってネットからライブラリを探すか、ソースからビルドする必要がある。
ちなみに共有ライブラリは
- -lnl => libnl.so
- -lssl => libssl.so
- -lcrypto => libcrypto.so
というように読み替える。この.soファイル(バイナリファイル)を参照できるようにする必要がある。
libssl.so
とlibcrypto.so
はOpenwrt SDKの中に見つかったので、参照できる場所にコピーする。
root@ubuntu # ls -l ../../staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/libssl* lrwxrwxrwx 1 root root 15 Jul 25 2015 ../../staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/libssl.so -> libssl.so.1.0.0 -r-xr-xr-x 1 root root 381267 Jul 25 2015 ../../staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/libssl.so.1.0.0 root@ubuntu # ls -l ../../staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/libcrypto* lrwxrwxrwx 1 root root 18 Jul 25 2015 ../../staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/libcrypto.so -> libcrypto.so.1.0.0 -r-xr-xr-x 1 root root 1765806 Jul 25 2015 ../../staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/libcrypto.so.1.0.0 root@ubuntu # cp ../../staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/libssl.so.1.0.0 ../../staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/usr/lib/ root@ubuntu # cp ../../staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/libcrypto.so.1.0.0 ../../staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/usr/lib/ root@ubuntu # cd ../../staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/usr/lib/libcrypto.so.1.0.0 root@ubuntu # ln -s libssl.so.1.0.0 libssl.so root@ubuntu # ln -s libcrypto.so.1.0.0 libcrypto.so
共有ライブラリは新しいバージョンの.soファイルにリンクする形になっているので、ここでも同じ形式で管理するのがよい。
libnl.so
は見つからない。調べてみると、OpenWRT自体libnlは以下のライブラリしか扱っていないらしい。
Name Size Description
libnl-core 37K Common code for all netlink libraries
libnl-genl 8K Generic Netlink Library Functions
libnl-nf 25K Netfilter Netlink Library Functions
libnl-route 91K Routing Netlink Library Functions
libnl-3を使ってもコンパイルが失敗する。 仕方が無いので、libnlのversion1のソースをダウンロードしてコンパイルすることにする。
root@ubuntu # wget https://www.infradead.org/~tgr/libnl/files/libnl-1.1.4.tar.gz root@ubuntu # tar -zxvf libnl-1.1.4.tar.gz root@ubuntu # cd libnl-1.1.4/ root@ubuntu # ./configure root@ubuntu # make
これもちゃんとクロスコンパイル環境のgccでコンパイルする。
出来上がった.soファイルをその他2つと同じようにSTAGING_DIR/usr/lib/
の中に入れて再びmake
をすればOK。
あとは出来上がったhostapd
とhostapd_cli
をOpenWRTルータに移して実行できる。
結構長かったけど、お疲れ様でした。
makeファイルをデバック
makeファイルをデバックしたいときはこんな感じでコンソールに出力できる。
読み込んでいるライブラリとかをまとめて確認したいときは便利。
dummy := $(shell echo 表示したい内容 1>&2)