(三)openwrt主Makefile解析
本周成胖子每周一博到了第四周^_^
前言
前一篇,我们大概描述了整个镜像文件的生成过程.本周我们来解析主Makefile,看看主要编译过程是怎么产生的.
主Makefile结构
我们以chaos calmer的代码为例,整个编译的入口是在源码根目录下的Makefile.编译的各种命令都应该在源码根目录下键入.
整个主Makefile的结构如下:
world:
ifneq ($(OPENWRT_BUILD),1)
顶层
else
第二层
endif
开始部分是一些注释和变量定义及路径检查.
根据Makefile的规则,在没有指定编译目标的时候,Makefile中的第一个目标将作为默认目标.
换句话说,当我们执行make V=s时,这个时候编译的目标就是world.和我们执行make world V=s效果是一样的.
顶层
通常在编译时,我们不会定义变量OPENWRT_BUILD的值,所以通常我们是会走到顶层的.
顶层代码如下:
_SINGLE=export MAKEFLAGS=$(space);
override OPENWRT_BUILD=1
export OPENWRT_BUILD
GREP_OPTIONS=
export GREP_OPTIONS
include $(TOPDIR)/include/debug.mk
include $(TOPDIR)/include/depends.mk
include $(TOPDIR)/include/toplevel.mk
这里我们看到变量OPENWRT_BUILD被置为1.然后包含了3个.mk文件.
这里稍微解释下.mk文件.它们一般没有什么执行动作,都是一些变量的定义还有依赖关系的说明.可以类比于C语言的头文件来理解.
debug.mk:
可以通过定义DEBUG的值来控制编译过程
depends.mk
主要定义了rdep这个变量
toplevel.mk
这个是我们跟踪编译过程的重要的文件.这个文件在源码根目录下的
include文件夹下.
核心代码如下:
%::
@+$(PREP_MK) $(NO_TRACE_MAKE) -r -s prereq
@( \
cp .config tmp/.config; \
./scripts/config/conf --defconfig=tmp/.config -w tmp/.config Config.in > /dev/null 2>&1; \
if ./scripts/kconfig.pl '>' .config tmp/.config | grep -q CONFIG; then \
printf "$(_R)WARNING: your configuration is out of sync. Please run make menuconfig, oldconfig or defconfig!$(_N)\n" >&2; \
fi \
)
@+$(ULIMIT_FIX) $(SUBMAKE) -r $@ $(if $(WARN_PARALLEL_ERROR), || { \
printf "$(_R)Build failed - please re-run with -j1 to see the real error message$(_N)\n" >&2; \
false; \
} )
除了少数在toplevel中被定义的目标外,其他编译目标都会走到这里.将之简化后:
%::
make prereq
make $@
首先执行prereq,然后再执行我们指定的目标或者默认目标world.
prereq整理后的依赖关系如下:
其中
staging_dir/host/.prereq-build:
将会执行一系列主机检查,是否安装了必要的软件.
prepare-tmpinfo:
根据scan.mk,扫描
target/linux和package目录,生成packageinfo和targetinfo.
总之,顶层完成一系列必要的准备工作.对于绝大多数的目标而言,顶层是必经之路.当然,在toplevel.mk中,我们也可以看到目标menuconfig.也就是说对于目标menuconfig而言,将不会执行到第二层的逻辑.
第二层
在上面执行完make prereq之后,将执行make world.
还记得我们进入顶层后修改了变量OPENWRT_BUILD么?当再次执行make world的时候,由于条件不满足,我们将直接进入第二层来执行.
include rules.mk
include $(INCLUDE_DIR)/depends.mk
include $(INCLUDE_DIR)/subdir.mk
include target/Makefile
include package/Makefile
include tools/Makefile
include toolchain/Makefile
rules.mk:
很重要的一个mk文件,其中规定了很多有用的变量,包括各种目录路径的定义,交叉编译器等等.其中
ifeq ($(DUMP),)
-include $(TOPDIR)/.config
endif就是包含了我们的配置文件.对于
Makefile而言,.config文件就是一大串变量的定义.Makefile可以直接读取这些定义,从而控制编译过程.
subdir.mk:
这个是读懂我们整个编译过程的关键所在,其中主要定义了两个函数:subdir和stampfile,我们稍后加以解释.
接下来,包含了4个Makefile文件.我们以target/Makefile为例.该文件位于target目录下.
核心部分为:
$(eval $(call stampfile,$(curdir),target,prereq,.config))
$(eval $(call stampfile,$(curdir),target,compile,$(TMP_DIR)/.build))
$(eval $(call stampfile,$(curdir),target,install,$(TMP_DIR)/.build))
$(eval $(call subdir,$(curdir)))
这里调用了subdir.mk中定义的stampfile函数.将会生成target/stamp-prereq,target/stamp-compile,target/stamp-install三个变量.
以target/stamp-prereq为例,执行部分为make target/prereq.同理target/stamp-compile,执行部分为make target/compile.
最后又调用了sbudir函数,这个函数规定了目标和各子文件夹之间的依赖关系.如果有一定的Makefile基础可以去读读subdir.mk文件.
举例而言就是:
当执行目标为
target/compile,这个目标将依赖于target/linux/compile.
当执行目标为package/compile,这个目标将依赖于package目录下,各子文件夹的compile.
下面就是规定了一系列的依赖关系,我已经将他们梳理了出来,如下图:
这里就是第二层解析后的依赖关系.当依赖关系生成后,将会从最先被依赖的目标开始执行.
比如我们可以看到进入第二层后,tools/stamp-install将会最先被执行,也就是主机工具将会最先被编译,安装.我们上一篇提高的整个编译过程能从上图中得出.
尾记
- 想要读懂Makefile,首先要梳理各个依赖关系.而要梳理各个依赖关系,关键要关注冒号和
make -C - 本周我们解析了主Makefile,在Makefile的执行过程中要理解make的执行过程.先读入Makefile,然后构建依赖关系,最后最先被依赖的目标将会先执行.
- 我主要描绘了主要枝干,如果希望了解更多细节,还是要自己去阅读Makefile.
- 接下来两篇,我们将主要分析下,和我们开发者比较相关的两个目标的执行过程:
package/stamp-compile和target/stamp-install.下周再会^_^
(三)openwrt主Makefile解析的更多相关文章
- OpenWrt的主Makefile工作过程
OpenWrt是一个典型的嵌入式Linux工程,了解OpenWrt的Makefile的工作过程对提高嵌入式Linux工程的开发能力有极其重要意义. OpenWrt的主Makefile文件只有100行, ...
- uboot-jiuding 下主Makefile详解
主Makefile位于uboot源码的根目录下,其内容主要结构为: 1. 确定版本号及主机信息(23至48行)2. 实现静默编译功能(48至55行)3. 设置各种路径(56至123行)4. 设置编译工 ...
- Spring Boot干货系列:(三)启动原理解析
Spring Boot干货系列:(三)启动原理解析 2017-03-13 嘟嘟MD 嘟爷java超神学堂 前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说 ...
- uboot主Makefile分析(t配置和编译过程详解)
1.编译uboot前需要三次make make distcleanmake x210_sd_configmake -j4 make distclean为清楚dist文件. make x210_sd_c ...
- uboot总结:uboot配置和启动过程1(主Makefile分析)
说明:文件位置:在uboot的目录下,文件名为:Makefile 从文件的头部开始分析 1.24-29行,配置uboot的版本信息. VERSION = PATCHLEVEL = SUBLEVEL = ...
- SpringBoot入门(三)——入口类解析
本文来自网易云社区 上一篇介绍了起步依赖,这篇我们先来看下SpringBoot项目是如何启动的. 入口类 再次观察工程的Maven配置文件,可以看到工程的默认打包方式是jar格式的. <pack ...
- uboot主Makefile分析
VERSION = 1 PATCHLEVEL = 3 SUBLEVEL = 4 EXTRAVERSION = U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(S ...
- uboot 主Makefile 分析。
本文以uboot_1.1.6 对应的CPU是S3C2440 为例 uboot_1.1.6 根目录下的主Makefile开头: VERSION = PATCHLEVEL = SUBLEVEL = EXT ...
- uboot 主Makefile分析
一. Makefile 配置 1.1. make xxx_config 1.1.1. 笔者实验时是make x210_sd_config a. x210_sd_config是Makefile下的一个目 ...
随机推荐
- 计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task
E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E Mean: 给定一个字符串,有q次操作, ...
- 二维KMP - 求字符矩阵的最小覆盖矩阵 - poj 2185
Milking Grid Problem's Link:http://poj.org/problem?id=2185 Mean: 给你一个n*m的字符矩阵,让你求这个字符矩阵的最小覆盖矩阵,输出这个最 ...
- C#设计模式——迭代器模式(Iterator Pattern)
一.概述在软件开发过程中,我们可能会希望在不暴露一个集合对象内部结构的同时,可以让外部代码透明地访问其中包含的元素.迭代器模式可以解决这一问题.二.迭代器模式迭代器模式提供一种方法顺序访问一个集合对象 ...
- Winform开发框架之权限管理系统的改进
权限管理系统,一直是很多Mis系统和一些常见的管理系统所需要的,所以一般可以作为独立的模块进行开发,需要的时候进行整合即可,不需要每次从头开发,除非特殊的系统需求.我在Winform开发框架介绍中的随 ...
- AEAI ESB V3.5.4开源发布,应用集成平台
AEAI ESB 应用集成平台为数通畅联的核心产品,本着分享传递的理念,数通畅联将ESB管理控制台项目开源,目的在于满足客户与伙伴的OEM需求,以及为广大IT爱好者的集成工具提供多一种选择,多一种便利 ...
- C#基础-css行内元素、块级元素基础
一.行内元素与块级元素 块级元素列表 <address> 定义地址 <caption> 定义表格标题 <dd> 定义列表中定义条目 <div> 定义文档 ...
- 【Bootstrap基础学习】04 Bootstrap的HTML和CSS编码规范
HTML 用两个空格来代替制表符(tab) -- 这是唯一能保证在所有环境下获得一致展现的方法. 嵌套元素应当缩进一次(即两个空格) 对于属性的定义,确保全部使用双引号,绝不要使用单引号. 不要在自闭 ...
- 重新想象 Windows 8.1 Store Apps (90) - 通信的新特性: 通过 HttpBaseProtocolFilter 实现 http 请求的缓存控制,以及 cookie 读写; 自定义 HttpFilter; 其他
[源码下载] 重新想象 Windows 8.1 Store Apps (90) - 通信的新特性: 通过 HttpBaseProtocolFilter 实现 http 请求的缓存控制,以及 cooki ...
- Apns推送中的的json格式介绍
在开发向苹果Apns推送消息服务功能,我们需要根据Apns接受的数据格式进行推送.下面接受我在进行apns推送时候总结的一点apns服务接受的Json数据格式 示例 1: 以下负载包含哦一个简单的 a ...
- 【转载】delete table 和 truncate table 的区别
使用delete语句删除数据的一般语法格式: delete [from] {table_name.view_name} [where] 将XS表中的所有行数据删除 delete XS 执行完后,发现X ...