最近想研究一下Openwrt,于是开始搭建openwrt环境,虽然现在没有现成的板子,但是
可以先编译起来。
openwrt的特点是基于下载 -> patch -> 编译 的一个工作模式,openwrt整个包一开始下载下来也不是很大,因为里面
基本上没有源码,要在编译的时候下载。
看了别人的帖子,都推荐使用svn从官网下载源码,
svn co svn://svn.openwrt.org/openwrt/trunk/
但是实际测试发现它的速度太慢了,为了得到官方的源码,从github上找到了它:
https://github.com/openwrt-mirror/openwrt
将它下载下来之后,要安装一些必要的包来编译它,我使用的是ubuntu12.04.
sudo apt-get install flex g++ gawk zlib1g-dev libncurses5-dev libssl-dev subversion
先看一下它的目录树:
tree -d -L 2 . ├── config ├── docs ├── include │ └── site ├── package │ ├── base-files │ ├── boot │ ├── devel │ ├── firmware │ ├── kernel │ ├── libs │ ├── network │ ├── system │ └── utils ├── scripts │ ├── config │ └── flashing ├── target │ ├── imagebuilder │ ├── linux │ ├── sdk │ └── toolchain ├── toolchain │ ├── binutils │ ├── gcc │ ├── gdb │ ├── glibc │ ├── insight │ ├── kernel-headers │ ├── musl │ ├── uClibc │ └── wrapper └── tools ├── autoconf ├── automake ├── b43-tools ├── bc ├── bison ├── ccache ├── cloog ├── cmake ├── dosfstools ├── e2fsprogs ├── elftosb ├── findutils ├── firmware-utils ├── flex ├── flock ├── genext2fs ├── gengetopt ├── gmp ├── include ├── libelf ├── libtool ├── lzma ├── lzma-old ├── m4 ├── missing-macros ├── mkimage ├── mklibs ├── mm-macros ├── mpc ├── mpfr ├── mtd-utils ├── mtools ├── padjffs2 ├── patch ├── patchelf ├── patch-image ├── pkg-config ├── ppl ├── qemu ├── quilt ├── scons ├── sed ├── sparse ├── squashfs ├── squashfs4 ├── sstrip ├── upslug2 ├── upx ├── wrt350nv2-builder ├── xz └── yaffs2
首先是更新一下feed:
./scripts/feeds update -a
./scripts/feeds install -a
这里的-a表示更新所有的feed,那么这里有哪些feed呢,可以从log里面看出来:
tan@love:~/openwrt-git/openwrt$ scripts/feeds update -a Updating feed 'packages' from 'https://github.com/openwrt/packages.git' ... Cloning into './feeds/packages'... remote: Counting objects: 3682, done. remote: Compressing objects: 100% (2941/2941), done. remote: Total 3682 (delta 488), reused 3055 (delta 247), pack-reused 0 Receiving objects: 100% (3682/3682), 2.00 MiB | 24 KiB/s, done. Resolving deltas: 100% (488/488), done. Create index file './feeds/packages.index' Collecting package info: done Collecting target info: done Updating feed 'luci' from 'https://github.com/openwrt/luci.git' ... Cloning into './feeds/luci'... remote: Counting objects: 11683, done. remote: Compressing objects: 100% (6278/6278), done. remote: Total 11683 (delta 3832), reused 9770 (delta 2394), pack-reused 0 Receiving objects: 100% (11683/11683), 8.42 MiB | 85 KiB/s, done. Resolving deltas: 100% (3832/3832), done. Create index file './feeds/luci.index' Collecting package info: done Collecting target info: done Updating feed 'routing' from 'https://github.com/openwrt-routing/packages.git' ... Cloning into './feeds/routing'... remote: Counting objects: 441, done. remote: Compressing objects: 100% (343/343), done. Receiving objects: 100% (441/441), 242.46 KiB | 58 KiB/s, done. remote: Total 441 (delta 81), reused 330 (delta 38), pack-reused 0 Resolving deltas: 100% (81/81), done. Create index file './feeds/routing.index' Collecting package info: done Collecting target info: done Updating feed 'telephony' from 'https://github.com/openwrt/telephony.git' ... Cloning into './feeds/telephony'... remote: Counting objects: 268, done. remote: Compressing objects: 100% (222/222), done. remote: Total 268 (delta 51), reused 211 (delta 22), pack-reused 0 Receiving objects: 100% (268/268), 140.49 KiB | 102 KiB/s, done. Resolving deltas: 100% (51/51), done. Create index file './feeds/telephony.index' Collecting package info: done Collecting target info: done Updating feed 'management' from 'https://github.com/openwrt-management/packages.git' ... Cloning into './feeds/management'... remote: Counting objects: 40, done. remote: Compressing objects: 100% (28/28), done. remote: Total 40 (delta 7), reused 27 (delta 2), pack-reused 0 Unpacking objects: 100% (40/40), done. Create index file './feeds/management.index' Collecting package info: done Collecting target info: done Updating feed 'targets' from 'https://github.com/openwrt/targets.git' ... Cloning into './feeds/targets'... remote: Counting objects: 137, done. remote: Compressing objects: 100% (95/95), done. remote: Total 137 (delta 17), reused 122 (delta 16), pack-reused 0 Receiving objects: 100% (137/137), 130.80 KiB | 44 KiB/s, done. Resolving deltas: 100% (17/17), done. Create index file './feeds/targets.index' Collecting package info: done Collecting target info: done
可以从上面的网址看出来更新的feed。
更新feed后目录树的变化:
. ├── config ├── docs ├── feeds │ ├── luci │ ├── luci.tmp │ ├── management │ ├── management.tmp │ ├── packages │ ├── packages.tmp │ ├── routing │ ├── routing.tmp │ ├── targets │ ├── targets.tmp │ ├── telephony │ └── telephony.tmp ├── include │ └── site ├── package │ ├── base-files │ ├── boot │ ├── devel │ ├── feeds │ ├── firmware │ ├── kernel │ ├── libs │ ├── network │ ├── system │ └── utils ├── scripts │ ├── config │ └── flashing ├── staging_dir │ └── host ├── target │ ├── imagebuilder │ ├── linux │ ├── sdk │ └── toolchain ├── tmp │ └── info ├── toolchain │ ├── binutils │ ├── gcc │ ├── gdb │ ├── glibc │ ├── insight │ ├── kernel-headers │ ├── musl │ ├── uClibc │ └── wrapper └── tools ├── autoconf ├── automake ├── b43-tools ├── bc ├── bison ├── ccache ├── cloog ├── cmake ├── dosfstools ├── e2fsprogs ├── elftosb ├── findutils ├── firmware-utils ├── flex ├── flock ├── genext2fs ├── gengetopt ├── gmp ├── include ├── libelf ├── libtool ├── lzma ├── lzma-old ├── m4 ├── missing-macros ├── mkimage ├── mklibs ├── mm-macros ├── mpc ├── mpfr ├── mtd-utils ├── mtools ├── padjffs2 ├── patch ├── patchelf ├── patch-image ├── pkg-config ├── ppl ├── qemu ├── quilt ├── scons ├── sed ├── sparse ├── squashfs ├── squashfs4 ├── sstrip ├── upslug2 ├── upx ├── wrt350nv2-builder ├── xz └── yaffs2
然后使用:
make menuconfig
make
编译的过程会持续好几个小时,因为编译的时候还需要在线下载工具包,如果网络慢的话就会
更慢了。
关于make的作用,README是这样说的:
Simply running "make" will build your firmware. It will download all sources, build the cross-compile toolchain, the kernel and all choosen applications.
中文手册是这样说的:
OpenWrt选择了另一种方式来生成固件:下载,打补丁,编译,一切从零开始,即使交叉编译链也是如此。
一开始下载openwrt源码的时候,也就大约300MB,但是里面基本上没有代码,大部分
都是配置文件。
openwrt的英文文档如下:
https://downloads.openwrt.org/kamikaze/docs/openwrt.html
在编译过程中,使用make -j V=99 可以加快编译速度,并且显示所有信息,
在编译的时候,我的swap被占满,并且报错,可能是因为屏幕上刷的太快导致的:
virtual memory exhaustedvirtual memory exhausted
不打开V=99的情况下,我的编译log如下:
tan@ubuntu:~/openwrt$ make -j4 make[1] world make[2] target/compile make[2] package/cleanup make[3] -C target/linux compile make[2] package/compile make[3] -C package/system/opkg host-compile make[3] -C package/libs/toolchain compile make[3] -C package/kernel/gpio-button-hotplug compile make[3] -C package/libs/ncurses host-compile make[3] -C package/libs/libnl-tiny compile make[3] -C package/utils/lua compile make[3] -C package/libs/libjson-c compile make[3] -C package/libs/lzo compile make[3] -C package/libs/zlib compile make[3] -C package/libs/ncurses compile make[3] -C package/boot/uboot-ar71xx compile make[3] -C package/firmware/linux-firmware compile make[3] -C package/libs/ocf-crypto-headers compile make[3] -C package/network/utils/iw compile make[3] -C package/network/services/dropbear compile make[3] -C package/libs/libpcap compile make[3] -C package/network/utils/linux-atm compile make[3] -C package/network/utils/resolveip compile make[3] -C package/utils/busybox compile make[3] -C package/libs/libubox compile make[3] -C package/utils/util-linux compile make[3] -C package/kernel/linux compile make[3] -C package/libs/openssl compile make[3] -C package/system/ubus compile make[3] -C package/system/uci compile make[3] -C package/utils/jsonfilter compile make[3] -C package/system/mtd compile make[3] -C package/system/opkg compile make[3] -C package/network/config/netifd compile make[3] -C package/system/ubox compile make[3] -C package/utils/ubi-utils compile make[3] -C package/network/services/hostapd compile make[3] -C package/network/config/swconfig compile make[3] -C package/network/services/odhcpd compile make[3] -C package/network/utils/iwinfo compile make[3] -C package/system/procd compile make[3] -C package/system/fstools compile make[3] -C package/base-files compile make[3] -C package/boot/uboot-envtools compile make[3] -C package/kernel/mac80211 compile make[3] -C package/network/utils/iptables compile make[3] -C package/network/services/dnsmasq compile make[3] -C package/network/ipv6/odhcp6c compile make[3] -C package/network/services/ppp compile make[3] -C package/network/config/firewall compile make[2] package/install make[3] package/preconfig make[2] target/install make[3] -C target/linux install make[2] package/index
最终会生成下面的文件(在bin文件夹内):
由于我使用默认的配置,生成的文件太多,这里只给一个部分的截图
初次下载源代码,为了理解openwrt的架构和编译过程,下面做一下简要的分析:
openwrt是基于linux kernel的,并且使用uclibc作为c库。
注意到编译过程中生成了三个文件夹,那么他们分别是干什么的呢?
dl
build_dir
staging_dir
dl是在编译的时候下载文件的目录,这些文件都是编译所需要的,下面是它们的的一部分:
├── ath10k-firmware-da0f85d924226ee30c46e037120621c9e192b39e.tar.bz2 ├── autoconf-2.69.tar.xz ├── automake-1.15.tar.xz ├── bc-1.06.95.tar.bz2 ├── binutils-linaro-2.24.0-2014.09.tar.xz ├── bison-3.0.2.tar.xz ├── broadcom-wl-4.150.10.5.tar.bz2 ├── broadcom-wl-5.100.138.tar.bz2 ├── busybox-1.23.2.tar.bz2 ├── cmake-2.8.12.2.tar.gz ├── compat-wireless-2015-03-09.tar.bz2 ├── dnsmasq-2.72.tar.gz ├── dropbear-2014.65.tar.bz2 ├── e2fsprogs-1.42.8.tar.gz ├── findutils-4.4.2.tar.gz ├── firewall-2015-02-26-165029cb8c0f1545628f44143aec965e64cef021.tar.gz ├── flex-2.5.39.tar.bz2 ├── fstools-2015-03-30-a5fa5b6144253726dcd7e769197eed787a723f5f.tar.gz ├── gcc-linaro-4.8-2014.04.tar.xz ├── gdb-linaro-7.6-2013.05.tar.bz2 ├── genext2fs-1.4.1.tar.gz ├── gengetopt-2.22.6.tar.gz ├── gmp-5.1.3.tar.xz ├── hostapd-2015-03-25.tar.bz2 ├── iptables-1.4.21.tar.bz2 ├── ipw2100-fw-1.3.tgz ├── ipw2200-fw-3.1.tgz ├── iw-3.17.tar.xz ├── json-c-0.12.tar.gz ├── jsonfilter-2014-06-19-cdc760c58077f44fc40adbbe41e1556a67c1b9a9.tar.gz ├── libelf-0.8.13.tar.gz ├── libiwinfo-2015-03-23-40f2844fadc05f4a4de7699dbc12fee295b7057b.tar.gz ├── libpcap-1.5.3.tar.gz ├── libtool-2.4.tar.gz ├── libubox-2015-03-22-b8d9b382e39823850331edc2a92379173daf1be3.tar.gz ├── linux-3.18.10.tar.xz ├── linux-atm-2.5.2.tar.gz ├── linux-firmware-2015-03-20-f404336ba808cbd57547196e13367079a23b822c.tar.bz2 ├── lua-5.1.5.tar.gz
注意到,这些都是从网上下载的,要注意保留,以后编译的时候就不用上网下载了。
而build_dir
的作用就是存放上述这些压缩包的解压路径,也就是说,dl的包会解压到build_dir
里面,
并且编译这些包。
其中,这里有三个目录:
tan@ubuntu:~/openwrt$ tree build_dir/ -d -L 1 build_dir/ ├── host ├── target-mips_34kc_uClibc-0.9.33.2 └── toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2
host目录是为了编译一些tools用于协助生成openwrt image
target目录是为目标主机编译用的,可以在目录上看到CPU的架构和所用的c库
toolchain是用来编译交叉编译器的
在staging_dir下面可以看到类似的三个目录:
tan@ubuntu:~/openwrt$ tree staging_dir/ -d -L 1 staging_dir/ ├── host ├── target-mips_34kc_uClibc-0.9.33.2 └── toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2
host目录下存放了一些编译主机上的一些工具(tools)
target 目录主要存放编译出来的firmware,是给目标机器用的
toolchain目录包含了交叉编译器,你可以在里面写一个简单的c文件,并且使用交叉编译器编译它,
生成的程序可以在目标机器上运行。
虽然不完全如此,可以将staging_dir的每个文件夹对应理解成build_dir的产物
这里有编译过程的大体介绍:
http://wiki.openwrt.org/doc/howto/build
http://downloads.openwrt.org/docs/buildroot-documentation.html
openwrt是一个高度定制版的buildroot,官网有它的介绍:
http://wiki.openwrt.org/about/toolchain
使用这个系统,可以基本做到全自动的编译过程。
bin目录下面的文件粗看可以分为两类:
openwrt-ar71xx-generic-a02-rb-w300n-squashfs-factory.bin
openwrt-ar71xx-generic-a02-rb-w300n-squashfs-sysupgrade.bin
其中这两个的区别是(转自http://see.sl088.com/wiki/Openwrt_factory%E5%9B%BA%E4%BB%B6/%E4%B8%BA%E4%BD%95%E5%85%88%E5%88%B7factory):
factory是用来从原厂固件升级到openwrt用的。 sysupgrade是用来给openwrt升级用的
无论你是升级还是从官方方刷openwrt,openwrt-XXXXXXX-factory.bin的固件都是适用的。 而openwrt-XXXXXXX-sysupgrade.bin.固件只能用来升级用。如TTL救砖就不能用sysupgrade的固件。
其中这里又进一步说明了:
http://www.cnblogs.com/siikee/p/4224086.html
bin文件下还有很多ipk文件,这些文件是opkg包管理系统的文件,在openwrt
运行起来的时候可以使用opkg安装,用起来和debian的deb差不多。
另外,openwrt 官方说了,the bootloader is not part of OpenWrt
http://wiki.openwrt.org/doc/techref/bootloader
而且,bootloader对于每一个路由器都是不一样的,负责将最底层开起来。厂家也不见得会将最底层的
代码开源。
目前有很多卖修改好的openwrt路由器,一个卖点就是不死uboot,就是说
你的firmware不管怎么刷都可以恢复,它包括一个网页接口,可以上传firmware
到路由器上,这样大大方便了openwrt的调试。
openwrt的menuconfig是定制好的,项目在config**.in里面:
最后看看openwrt 的patch系统
package的很多子目录都包含这两个东西,patches 是一些patch,Makefile包含了下载地址和其他的一些信息。
当发现这些用户空间软件出问题的时候,为其加patch就可以了,
实际上linux kernel出问题时,也可以这样类似地对其加一些patch进去。