参考网站:http://wiki.openwrt.org/doc/howto/buildroot.exigence

需要下载必要的库文件,编译器等。。。

1 首先要获得openwrt的源码,参考openwrt.org官方网站的内容 https://dev.openwrt.org/wiki/GetSource

其中trunk为开发版本,最新的稳定版为12.09 branch (Attitude Adjustment)。

使用git获得:git clone git://git.openwrt.org/12.09/openwrt.git

如果要更新源码则运行git pull即可。

使用svn获得:svn co svn://svn.openwrt.org/openwrt/branches/attitude_adjustment

2 下载完源码之后

获取包列表:

./scripts/feeds update -a

将包选项加到menuconfig中去:

./scripts/feeds install -a

3 make menuconfig

在此菜单中选择要编译的模块并生成依赖

3.1

我们打开openwrt根目录下的Makefile文件,发现并没有找到menuconfig这个目标,这个目标是在

include $(TOPDIR)/include/toplevel.mk

所指的toplevel.mk中定义的,如下图:

它的依赖是scripts/config/mconf和prepare-tmpinfo FORCE

  • scripts/config/mconf是一个已经存在的可执行文件;
  • prepare-tmpinfo是本文件中的一个目标,等会再阐述;
  • FORCE尚还不清楚它的作用和来源;

我们先看看menuconfig中的命令

    if [ \! -e .config -a -e $(HOME)/.openwrt/defconfig ]; then \
cp $(HOME)/.openwrt/defconfig .config; \
fi
$< Config.in

这是一句shell脚本,意思是:如果不存在.config而且存在$(HOME)/.openwrt/defconfig,则拷贝$(HOME)/.openwrt/defconfig为.config

$<是什么?The automatic variable ‘$<’ is just the first prerequisite,即是指scripts/config/mconf。
把这两个字符串连起来看就知道什么意思啦:scripts/config/mconf Config.in

你也可以直接到openwrt目录下去试运行一下这个指令,如下图,正是我们运行make menuconfig时出现的画面(下图我已经关闭了menuconfig):

3.2

好!现在我们回头去理prepare-tmpinfo的帐,并且看看能不能把Config.in这个文件搞懂是怎么回事。

prepare-tmpinfo: FORCE
mkdir -p tmp/info
$(_SINGLE)$(NO_TRACE_MAKE) -j1 -r -s -f include/scan.mk SCAN_TARGET="packageinfo" SCAN_DIR="package" SCAN_NAME="package" SCAN_DEPS="$(TOPDIR)/include/package*.mk $(TOPDIR)/overlay/*/*.mk" SCAN_DEPTH= SCAN_EXTRA=""
$(_SINGLE)$(NO_TRACE_MAKE) -j1 -r -s -f include/scan.mk SCAN_TARGET="targetinfo" SCAN_DIR="target/linux" SCAN_NAME="target" SCAN_DEPS="profiles/*.mk $(TOPDIR)/include/kernel*.mk $(TOPDIR)/include/target.mk" SCAN_DEPTH= SCAN_EXTRA="" SCAN_MAKEOPTS="TARGET_BUILD=1"
for type in package target; do \
f=tmp/.$${type}info; t=tmp/.config-$${type}.in; \
[ "$$t" -nt "$$f" ] || ./scripts/metadata.pl $${type}_config "$$f" > "$$t" || { rm -f "$$t"; echo "Failed to build $$t"; false; break; }; \
done
./scripts/metadata.pl package_mk tmp/.packageinfo > tmp/.packagedeps || { rm -f tmp/.packagedeps; false; }
touch $(TOPDIR)/tmp/.build

3.2.1

两个变量

_SINGLE在顶层Makefile中定义:

_SINGLE=export MAKEFLAGS=$(space);

NO_TRACE_MAKE的-/include/verbose.mk中定义:

ifeq ($(NO_TRACE_MAKE),)
NO_TRACE_MAKE := $(MAKE) V=s$(OPENWRT_VERBOSE)
export NO_TRACE_MAKE
endif

这里的命令先是去make V=xx -j1 -r -s -f include/scan.mk(分别Verbose,单线程,没有内建规则,指定Makefile文件)。所以我们再打开include/scan.mk文件看看怎么回事。最终目标是:

all: $(TMP_DIR)/.$(SCAN_TARGET)

3.2.2

这时scan.mk先定义了一个叫做PackageDir的“函数”(命令序列,后面将会使用):

define PackageDir
$(TMP_DIR)/.$(SCAN_TARGET): $(TMP_DIR)/info/.$(SCAN_TARGET)-$()
$(TMP_DIR)/info/.$(SCAN_TARGET)-$(): $(SCAN_DIR)/$()/Makefile $(SCAN_STAMP) $(foreach DEP,$(DEPS_$(SCAN_DIR)/$()/Makefile) $(SCAN_DEPS),$(wildcard $(if $(filter /%,$(DEP)),$(DEP),$(SCAN_DIR)/$()/$(DEP))))
{ \
$$(call progress,Collecting $(SCAN_NAME) info: $(SCAN_DIR)/$()) \
echo Source-Makefile: $(SCAN_DIR)/$()/Makefile; \
$(NO_TRACE_MAKE) --no-print-dir -r DUMP= -C $(SCAN_DIR)/$() $(SCAN_MAKEOPTS) >/dev/null || { \
mkdir -p "$(TOPDIR)/logs/$(SCAN_DIR)/$(2)"; \
$(NO_TRACE_MAKE) --no-print-dir -r DUMP= -C $(SCAN_DIR)/$() $(SCAN_MAKEOPTS) > $(TOPDIR)/logs/$(SCAN_DIR)/$()/dump.txt >&; \
$$(call progress,ERROR: please fix $(SCAN_DIR)/$()/Makefile - see logs/$(SCAN_DIR)/$()/dump.txt for details\n) \
rm -f $$@; \
}; \
echo; \
} > $$@ || true
endef

3.2.3

这个命令系列的用法可以看下面的$(call progress, Colleting....),progress也正是scan.mk文件中定义的一个命令序列:

$(TMP_DIR)/.$(SCAN_TARGET): $(TARGET_STAMP) $(SCAN_STAMP)
$(call progress,Collecting $(SCAN_NAME) info: merging...)
-cat $(FILELIST) | awk '{gsub(/\//, "_", $$0);print "$(TMP_DIR)/info/.$(SCAN_TARGET)-" $$0}' | xargs cat > $@ >/dev/null
$(call progress,Collecting $(SCAN_NAME) info: done)
echo

具体progress的定义是这样的:

ifeq ($(IS_TTY),)
define progress
printf "\033[M\r$(1)" >&;
endef
else
define progress
:;
endef
endif

所以,调用它之后会输出“<[M Collecting package info : merging... ”"....info: done"类似这样的信息(重定义到2,标准错误输出),$(1)表示第一个参数的意思

中间则输出awk信息,来研究下这个语句

-cat $(FILELIST) | awk '{gsub(/\//, "_", $$0);print "$(TMP_DIR)/info/.$(SCAN_TARGET)-" $$0}' | xargs cat > $@ >/dev/null

处理过程:

  1. -cat $(FILELIST),-cat最头的-表示如果出错也不提示如意思;
  2. cat得的数据输出通过awk的解析
    awk '{gsub(/\//, "_", $$0);print "$(TMP_DIR)/info/.$(SCAN_TARGET)-" $$0}'
  3. awk得的数据输出通过xargs cat(分小段输出给$@,也就是$(TMP_DIR)/.$(SCAN_TARGET)自己!),而错误输出的定义到null

看上面的过程,这部分主要问题是要搞清楚$(FILELIST)和awk的用法:

先上$(FILELIST)

$(FILELIST):
rm -f $(TMP_DIR)/info/.files-$(SCAN_TARGET)-*
$(call FIND_L, $(SCAN_DIR)) $(SCAN_EXTRA) -mindepth $(if $(SCAN_DEPTH),-maxdepth $(SCAN_DEPTH)) -name Makefile | xargs grep -HE 'call (Build/DefaultTargets|Build(Package|Target)|.+Package)' | sed -e 's#^$(SCAN_DIR)/##' -e 's#/Makefile:.*##' | uniq > $@

这儿的FIND_L命令序列实在x/tmp/.host.mk中定义的(该mk文件由x/include/host.mk生成)

FIND_L=/usr/bin/find -L $()

因而这个命令就演变成了系统指令find/xarg&grep/sed/uniq的用法了。

1 find查找$(SCAN_DIR)中的叫做Makefile的文件(搜索深度1~5);

2 xargs grep会展开各个Makefile文件,-H为显示时makefile名字,-E为启用后面跟着的正则表达式;

这儿call (Build/DefaultTargets|Build(Package|Target)|.+Package)会匹配到call Build/DefaultTargets或者BuildPackage或BuildTarget或者_任意多个字符_Package等三种情况的字符串(以行为结束);

3 sed

4 uniq

最后获得的文件写到了FILELIST := $(TMP_DIR)/info/.files-$(SCAN_TARGET)-$(SCAN_COOKIE)中;

spidev_test
hostapd
opkg
fuse
hotplug2
ppp
...
feeds/xwrt/webif-iw-lua-openssl
feeds/xwrt/webif-netsukuku
feeds/xwrt/webif-mesh
feeds/xwrt/webif-fonheartbeat
robocfg
comgt
rssileds
madwifi
grub
libjson-c
odhcp6c
rotary-gpio-custom
ead
rtc-rv5c386a
sierra-directip
button-hotplug
grub2
kexec-tools
linux-atm
util-linux
xfsprogs
pjsip
ltq-tapidemo
owsip
fbtest
gpioctl
uboot-omap4
i2c-gpio-custom
ltq-tapi
ltq-vmmc
uboot-lantiq
swconfig
uhttpd
trelay
iptables
switch
owipcalc
ltq-kpi2udp

3.2.4

$(TMP_DIR)/.$(SCAN_TARGET)的信赖,条件

  • $(TARGET_STAMP)
  • $(SCAN_STAMP)

4 编译得的bin文件在bin目录中。

使用make menuconfig --debug -w --just-print命令,不执行操作仅调试,结果为:

 GNU Make 3.81
Copyright (C) Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. This program built for x86_64-pc-linux-gnu
Reading makefiles...
Updating goal targets....
File `menuconfig' does not exist.
Target `scripts/config/mconf_check' is double-colon and has no prerequisites.
Must remake target `scripts/config/mconf_check'.
make: Entering directory `/home/tf/projects/openwrt'
{ [ -f "scripts/config/mconf_check.1" ] && mv "scripts/config/mconf_check.1"; /home/tf/projects/openwrt/scripts/timestamp.pl -x "*/.svn*" -x ".*" -x "*:*" -x "*\!*" -x "* *" -x "*\#*" -x "*/.*_check" -x "*/.*.swp" -n scripts/config/mconf scripts/config && { touch -r "scripts/config/mconf" "scripts/config/mconf_check"; } } || { touch "scripts/config/mconf_check"; }
Successfully remade target file `scripts/config/mconf_check'.
Prerequisite `scripts/config/mconf_check' is newer than target `scripts/config/mconf'.
Must remake target `scripts/config/mconf'.
export MAKEFLAGS= ;umask ; cmd() { >/dev/null >& make -s $* < /dev/null || { echo "make $*: build failed. Please re-run make with V=s to see what's going on"; false; } } >& >&; cmd -s -C scripts/config all CC="gcc"
Successfully remade target file `scripts/config/mconf'.
File `prepare-tmpinfo' does not exist.
File `FORCE' does not exist.
Must remake target `FORCE'.
Successfully remade target file `FORCE'.
Must remake target `prepare-tmpinfo'.
mkdir -p tmp/info
export MAKEFLAGS= ;make V=s -j1 -r -s -f include/scan.mk SCAN_TARGET="packageinfo" SCAN_DIR="package" SCAN_NAME="package" SCAN_DEPS="/home/tf/projects/openwrt/include/package*.mk /home/tf/projects/openwrt/overlay/*/*.mk" SCAN_DEPTH= SCAN_EXTRA=""
export MAKEFLAGS= ;make V=s -j1 -r -s -f include/scan.mk SCAN_TARGET="targetinfo" SCAN_DIR="target/linux" SCAN_NAME="target" SCAN_DEPS="profiles/*.mk /home/tf/projects/openwrt/include/kernel*.mk /home/tf/projects/openwrt/include/target.mk" SCAN_DEPTH= SCAN_EXTRA="" SCAN_MAKEOPTS="TARGET_BUILD=1"
for type in package target; do \
f=tmp/.${type}info; t=tmp/.config-${type}.in; \
[ "$t" -nt "$f" ] || ./scripts/metadata.pl ${type}_config "$f" > "$t" || { rm -f "$t"; echo "Failed to build $t"; false; break; }; \
done
./scripts/metadata.pl package_mk tmp/.packageinfo > tmp/.packagedeps || { rm -f tmp/.packagedeps; false; }
touch /home/tf/projects/openwrt/tmp/.build
Successfully remade target file `prepare-tmpinfo'.
Must remake target `menuconfig'.
if [ \! -e .config -a -e /home/tf/.openwrt/defconfig ]; then \
cp /home/tf/.openwrt/defconfig .config; \
fi
scripts/config/mconf Config.in
Successfully remade target file `menuconfig'.
make: Leaving directory `/home/tf/projects/openwrt'

openwrt构建过程探索的更多相关文章

  1. Linux内核剖析(五)Linux内核的构建过程

    参考 一次实验引发的故事 – kernel build system探索—vmlinux是如何炼成的– kernel makefile 深度探索Linux操作系统:系统构建和原理解析.pdf 问题 在 ...

  2. Docker容器构建过程的安全性分析

    来源:嘶吼专业版 ID:Pro4hou DevOps概念的流行跟近些年微服务架构的兴起有很大关系,DevOps是Dev(Development)和Ops(Operations)的结合,Dev负责开发, ...

  3. Mysql主从复制,读写分离(mysql-proxy),双主结构完整构建过程

    下面介绍MySQL主从复制,读写分离,双主结构完整构建过程,不涉及过多理论,只有实验和配置的过程. Mysql主从复制(转载请注明出处,博文地址:) 原理是master将改变记录到二进制日志(bina ...

  4. Android分析应用程序的构建过程

    为了方便Android应用开发要求我们Androidproject编制和包装有了更深入的了解,例如,我们知道这是做什么的每一步,境和工具.输入和输出是什么.等等. 在前文<命令行下Android ...

  5. vue 源码学习(一) 目录结构和构建过程简介

    Flow vue框架使用了Flow作为类型检查,来保证项目的可读性和维护性.vue.js的主目录下有Flow的配置.flowconfig文件,还有flow目录,指定了各种自定义类型. 在学习源码前可以 ...

  6. DOM 操作成本究竟有多高,HTML、CSS构建过程 ,从什么方向出发避免重绘重排)

    前言: 2019年!我准备好了 正文:从我接触前端到现在,一直听到的一句话:操作DOM的成本很高,不要轻易去操作DOM.尤其是React.vue等MV*框架的出现,数据驱动视图的模式越发深入人心,jQ ...

  7. android构建过程

    参考: http://blog.csdn.net/shangmingchao/article/details/47375111 首先,需要了解一下构建APK的七大工具: ①aapt 全称是Androi ...

  8. Deeplab v3+中的骨干模型resnet(加入atrous)的源码解析,以及普通resnet整个结构的构建过程

    加入带洞卷积的resnet结构的构建,以及普通resnet如何通过模块的组合来堆砌深层卷积网络. 第一段代码为deeplab v3+(pytorch版本)中的基本模型改进版resnet的构建过程, 第 ...

  9. Kylin Cube构建过程优化

    原文地址:https://kylin.apache.org/docs16/howto/howto_optimize_build.html Kylin将一个cube的build过程分解为若干个子步骤,然 ...

随机推荐

  1. linux0.11学习笔记(2)

    makefile文件: makefile 文件是make 实用简介.make 程序是用Makefile最后一次改变的数据文件和代码文件(last-modification time)确定哪些文件需要更 ...

  2. debian 该分区的部分安装移动硬盘后无法识别。

    有一个新的团购1T移动硬盘.购买格化学式ntfs经过几次简单的子区域. 4G硬盘PE.100G高速互动,盈800许多G分为两个相等的存储盘. 到您的计算机USB接口后,, 桌面弹出自己主动4一封信. ...

  3. HDU1069_Monkey and Banana【LCS】

    Monkey and Banana Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  4. LInq 与lambda表达式

    LInq 与lambda表达式 LinQ是我们常用的技术之一.因为我们绕不开的要对数据进行一系列的调整,如 排序. 条件筛选.求和.分组.多表联接 等等. lambda则是我们常用的语法糖,配合lin ...

  5. 客房收费系统改造(三)—厂+反射+DAL

    前一段时间有一个简单的三登录功能实现窗口,心灵修养一点点,但很快就被泼了一盆冷水.房费是不可能做到在短短三年,假设你使用三个,这倒房费三个功能必须使用函数来实现.了七层的研究. 经过一个星期的看博客. ...

  6. mvc5 解析route源码实现自己的route系统

    Asp.net mvc5 解析route源码实现自己的route系统   url route 路由系统的责任是找到匹配的路由,创建路由数据,并将请求分配给一个处理程序. 选择动作是 MVC 的处理程序 ...

  7. 配置静态监听解决ORA-12514错误的案例(转)

    今天做Linux下DG配置的时候,遇到一个现象,tnsname.ora文件配置都正常,tnsping也正常,监听也正常,但是仍然报ORA-12514错误:   SQL> set lin 130 ...

  8. 一个用于每一天JavaScript示例-SVG中间javaScript画廊

    <?xml version="1.0" standalone="no"? > <!DOCTYPE svg PUBLIC "-//W3 ...

  9. 1023 Train Problem II(卡特兰数)

    Problem Description As we all know the Train Problem I, the boss of the Ignatius Train Station want ...

  10. rdlc报告vs2008编辑正常,在vs2012在对错误的编辑

    最近我们的系统开发的工具vs2008升级到2012,由于系统是非常的报告是由rdlc发展.今天 有需要修改的报告满足需求.直接使用vs2012正确rdlc报告编辑,结果本次变动后.报表都报错. 后来我 ...