OpenWrt高清无码(5)编译

tags: openwrt tutorial

OpenWrt内建了强大的编译机制,几乎所有的步骤都是自动化了,所以编译过程非常简单。

最简单的情况下,只需要两步

make menuconfig
make

第一步make menuconfig会出现一个菜单,用于定制你要编译的软件。最基本的选项是前三项,分别是指定芯片厂商、芯片系列、产品型号。一般的,选择好前三项就可以得到一个最基本的可用的路由器软件。其它的选项OpenWrt都设有一个默认值,大家可以慢慢摸索修改。

以小米路由mini为例,它用的是MTK(实际上是Ralink,Ralink在2011年被MTK收购了)的MT7620芯片,那么选择结果如下:

选择完成之后保存退出,它会在openwrt根目录下生成一个.config文件。这个文件包含了本次设定的全部配置。

第二步make直接开始编译了。

如前文所述,OpenWrt是由许许多多的零件组合成的。每个零件的编译过程都类似下面这样:先从网上下载源代码放到dl目录下,然后把源代码解压到build_dir里,如果有patch的话,再给原代码打上补丁,接下来就是编译代码,编译成功之后,结果文件被放到bin目录下(部分结果文件也会被放到staging目录下)。

make的其它形式

OpenWrt的编译命令还有其它一些形式和技巧,介绍如下:

  • make oldconfig,这个命令跟make menuconfig类似,都属于config家族。它会将前一次menuconfig的结果做为默认值。当你的工程结构发生了变化时,(比如安装或删除了一个新的软件包,又比如某些package的选项有增删等),make oldconfig就会只显示发生了变化的部分。
  • make kernel_menuconfig,这个特殊的命令是针对内核的。它会带你进入Linux内核的配置界面。一般情况下,OpenWrt的内核配置是不需要动的。关于OpenWrt的配置体系,我会在后面专门写一章来详解。
  • make -j4,使用并行编译,4为并行数。非常实用的技巧,可以极大提高编译效率。并行数设太多也不好,根据个人经验可指定并行数为“CPU核数x2”。有一点要注意,并行编译时多个编译进程输出的日志是交叉的,当你遇到编译错误时,很难找到错在哪里。这时最好是去掉并行选项,重新执行一次。
  • make V=s,加上V=s之后,会看到详细的编译日志。常用的功能,于我来说是必备的选项(我最喜欢的是make V=s -j4)。
  • make target/linux/compile V=s,只编译Linux内核。注意,这样做只是将内核重新编译一次,但并不会更新到最终的固件里。
  • make target/linux/{clean,prepare,compile} V=s,与上一条相似,但会依次执行多个过程。clean表删除build_dir下面的内核编译目录,prepare表示从dl目录下的压缩包里重新解压一份内核代码到build_dir,compile同上一条。你如果要开发一些内核的东西,这条命令比较实用。
  • make package/package_name/{clean,prepare,compile} V=s,类似上一条,只是针对某个package重新编译,在开发应用程序时非常实用。(实际上linux kernel也可以看作是OpenWrt一个比较特殊的package)。package_name可以在package目录下找到,比如dnsmsq、ubox、netifd……要注意这里package_name是目录名。

编译时间为什么这么长

第一次编译OpenWrt的时间非常长,最差的情况要一两个小时!主要原因有两点:

一是OpenWrt编译的时候会从网上下载各种各样的软件包(包括Linux内核)。如果网络条件不佳,那会有相当长的时候花在下载过程上。甚至会遇到某些软件包下载不下来的情况,要么反复重试,要么手动去网上下载这个软件包,然后放在dl目录下。

二是OpenWrt第一次编译时要生成交叉编译工具链(Cross Compile Toolchain)。所谓“交叉编译工具链”,其实也是一堆编译工具,像编译器(GCC)、链接器(LD)等等。它有别于你本机上的GCC、LD,你本机的GCC编译出来的程序是在你本机运行的,而交叉编译工具链编译的程序是放在其它平台上(这里就是路由器)上运行的。交叉编译工具链编译完成之后,会放在staging目录下。

这两关过了之后,再编译的话速度会快很多,在我的电脑上几分钟而已。

编译完成后,我们得到了什么

首先观察一下目录的变化:

drwxrwxr-x. 11 nossiac nossiac  4096 May  4 10:06 .
drwxrwxr-x. 18 nossiac nossiac  4096 May  4 10:06 ..
-rw-rw-r--.  1 nossiac nossiac   179 May  4 10:06 BSDmakefile
drwxrwxr-x.  2 nossiac nossiac    96 May  4 10:06 config
-rw-rw-r--.  1 nossiac nossiac   576 May  4 10:06 Config.in
drwxrwxr-x.  2 nossiac nossiac  4096 May  4 10:06 docs
-rw-rw-r--.  1 nossiac nossiac   904 May  4 10:06 feeds.conf.default
drwxrwxr-x.  8 nossiac nossiac  4096 May  4 10:06 .git
-rw-rw-r--.  1 nossiac nossiac     8 May  4 10:06 .gitattributes
-rw-rw-r--.  1 nossiac nossiac   224 May  4 10:06 .gitignore
drwxrwxr-x.  3 nossiac nossiac  4096 May  4 10:06 include
-rw-rw-r--.  1 nossiac nossiac 17992 May  4 10:06 LICENSE
-rw-rw-r--.  1 nossiac nossiac  2659 May  4 10:06 Makefile
drwxrwxr-x. 11 nossiac nossiac  4096 May  4 10:06 package
-rw-rw-r--.  1 nossiac nossiac  1272 May  4 10:06 README
-rw-rw-r--.  1 nossiac nossiac 10705 May  4 10:06 rules.mk
drwxrwxr-x.  4 nossiac nossiac  4096 May  4 10:06 scripts
drwxrwxr-x.  6 nossiac nossiac    94 May  4 10:06 target
drwxrwxr-x. 11 nossiac nossiac  4096 May  4 10:06 toolchain
drwxrwxr-x. 53 nossiac nossiac  4096 May  4 10:06 tools

上图中白色的文件和目录都是下载下来时就存在的,标红色的都是在编译完之后新出现的。

  • dl,下载目录。OpenWrt自身所带的代码非常少,绝大部分代码都要在编译过程中去网上下载,然后放在dl目录下。
  • .config或.config.old,这是make menuconfig生成的项目配置。
  • tmp, 顾名思义,临时文件。这也是在make menuconfig那一步时就生成的。OpenWrt在执行任何配置、编译过程前,会先扫描所有的toolchain、package、target路径,生成索引、缓存之类的临时文件,起加速作用。这个目录可以随时删除,随后自动生成。如果你改动了项目结构或配置选项,但在menuconfig里却看不到你的改动,可以删除这个目录试试。
  • build_dir, OpenWrt的编译都发生成build_dir下面。包括主机工具,交叉编译工具链(toolchain),Linux内核,各种软件包等等。这个目录也可以随时删除。
  • staging, staging代表的含义比较难用一个中文词来表示。它其实也是一个临时目录,但是它又比tmp的要“有用”一些。举两个例子:
    1. 交叉编译工具链编译的过程是在build_dir下面,其生成结果会放在staging目录下面,之后的编译会直接引用staging目录下的工具链,即使你删除了build_dir也不影响。
    2. 某些package是一个库(比如zlib),它会生成一些头文件供其它package引用。这些头文件也被放staging目录下。
    所以,staging归根结底也是一个临时目录,里面放的是一些编译生成的中间结果,在编译后其它环节会依赖这些结果。一般情况下我们不需要删除staging目录,尤其是toolchain目录,重编一次toolchain太费时间了。即使make clean,staging目录也不会被删除。
  • bin,这下面是编译的最终结果,包括崭新的路由器软件,以及可安装的软件包(.ipk文件)。
  • feeds,如果你看到这个目录,表示你使用过scripts/feeds命令。它用于配置OpenWrt的第三方软件包,类似CentOS里的yum、Ubuntu里的apt、Python里的pip。稍后会专门有一篇来讲解这个命令。

关于make clean

OpenWrt提供了几种make clean:

  • make clean,它会删除build_dir。像.config,tmp,staging等都保留着。
  • make distclean,终极clean,它让工程复原到最初下载的代码,所有编译过程中生成的文件和目录(包括.configtoolchain等等)都会被删除。
  • make dirclean,比较少用到。其实就是删除了build_dir,tmp,staging。

OpenWrt的编译架构是精心设计过的,代码的编译都拉到build_dir路径下进行,不会“污染”原始代码。所以clean动作非常简单,直接删除build_dir之类的目录就行了。所以我有时候也直接使用rm命令来clean。