二、编译第一步 make xxx_defconfig

2.1 顶层make defconfig规则

  make xxx_defconfig 的执行主要分成三个部分:

  1. 执行 make -f ./scripts/Makefile.build obj=scripts/basic,编译生成 scripts/basic/fixdep 工具
  2. 执行 make -f ./scripts/Makefile.build obj=scripts/kconfig rpi_3_32b_defconfig 编译生成 scripts/kconfig/conf 工具
  3. 执行 scripts/kconfig/conf --defconfig=arch/../configs/xxx_defconfig Kconfig生成最终的 .config 配置文件

  执行 make xxx_defconfig 命令时,u-boot 根目录下的 Makefile 中有唯一的规则匹配目标:

  代码第 467 到 478 行

 1 # ===========================================================================
 2 # *config targets only - make sure prerequisites are updated, and descend
 3 # in scripts/kconfig to make the *config target
 4
 5 KBUILD_DEFCONFIG := sandbox_defconfig
 6 export KBUILD_DEFCONFIG KBUILD_KCONFIG
 7
 8 config: scripts_basic outputmakefile FORCE
 9     $(Q)$(MAKE) $(build)=scripts/kconfig [email protected]
10
11 %config: scripts_basic outputmakefile FORCE
12     $(Q)$(MAKE) $(build)=scripts/kconfig [email protected]

  注释意思为,仅限 *config 目标,确保先决条件已经更新,并在 scripts/kconfig 下创建 *config 目标。上面有两个变量 config 和 %config,% 符号为通配符,对应所有的 xxxconfig 目标,前面已经说过。我们的 make xxx_defconfig 就对应 %config,我们并没有执行 make config 命令。

  Makefile中几种变量赋值运算符:

  • =      :最简单的赋值 
  • :=     :一般也是赋值 
    • 以上这两个大部分情况下效果是一样的,但是有时候不一样。
    • 用 = 赋值的变量,在被解析时他的值取决于最后一次赋值时的值,所以看变量引用的值时不能只往前面看,还要往后面看。
    • 用 := 来赋值的,则是就地直接解析,只用往前看即可。  
  • ?=     : 如果变量前面并没有赋值过则执行这条赋值,如果前面已经赋值过了则本行被忽略。
  • +=   用来给一个已经赋值的变量接续赋值,意思就是把这次的值加到原来的值的后面,有点类似于strcat     
    • 在shell makefile等文件中,可以认为所有变量都是字符串,+= 就相当于给字符串 strcat 接续内容
    • +=续接的内容和原来的内容之间会自动加一个空格隔开

2.1.1 代码执行到%config 的条件  

  先往上分析下这段代码的执行条件: ifeq ($(config-targets),1),代码在415 到 447 行

 1 # To make sure we do not include .config for any of the *config targets
 2 # catch them early, and hand them over to scripts/kconfig/Makefile
 3 # It is allowed to specify more targets when calling make, including
 4 # mixing *config targets and build targets.
 5 # For example ‘make oldconfig all‘.
 6 # Detect when mixed targets is specified, and make a second invocation
 7 # of make so .config is not included in this case either (for *config).
 8
 9 version_h := include/generated/version_autogenerated.h
10 timestamp_h := include/generated/timestamp_autogenerated.h
11
12 no-dot-config-targets := clean clobber mrproper distclean 13              help %docs check% coccicheck 14              ubootversion backup tests
15
16 config-targets := 0
17 mixed-targets  := 0
18 dot-config     := 1
19
20 ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
21     ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
22         dot-config := 0
23     endif
24 endif
25
26 ifeq ($(KBUILD_EXTMOD),)
27         ifneq ($(filter config %config,$(MAKECMDGOALS)),)
28                 config-targets := 1
29                 ifneq ($(words $(MAKECMDGOALS)),1)
30                         mixed-targets := 1
31                 endif
32         endif
33 endif

  代码注释内容:为了确保我们不包含任何 * config 目标的 .config,请尽早捕获它们,并将它们交给 scripts / kconfig / Makefile。调用make 时允许指定更多目标,包括混合 * config 目标和构建目标。例如 ‘make oldconfig all‘ 。检测何时指定了混合目标,并进行make的第二次调用,因此 .config不包含在这种情况下(对于* config)。

  • version_h:版本号文件,此文件是自动生成的
  • timestamp_h:时间戳文件,此文件是自动生成的
  • no-dot-config-targets:指代的是那些和 .config 没有关系的目标
  • config-targets:配置目标,初始值设置为0
  • mixed-targets:混合目标,初始值设置为0
  • dot-config:初始值设置为1

  变量 MAKECMDGOALS:make 在执行时会设置一个特殊变量 -- "MAKECMDGOALS" ,该变量记录了命令行参数指定的终极目标列表,没有通过参数指定终极目标时此变量为空。该变量仅限于用在特殊场合(比如判断),在 Makefile 中最好不要对它进行重新定义。

  我们执行  make xxx_defconfig 的时候,MAKECMDGOALS 变量的值就为 xxx_defconfig。

  filter 函数 和 filter-out 函数:

1 $(filter PATTERN…,TEXT)
2 函数名称:  过滤函数— filter。
3 函数功能:  过滤掉字串“ TEXT”中所有不符合模式“ PATTERN”的单词,保留所
4         有符合此模式的单词。可以使用多个模式。模式中一般需要包含模式字
5        符“ %”。存在多个模式时,模式表达式之间使用空格分割。
6 返回值:空格分割的“ TEXT”字串中所有符合模式“ PATTERN”的字串。
7 函数说明:“ filter”函数可以用来去除一个变量中的某些字符串

1 $(filter-out PATTERN...,TEXT)
2 函数名称:  反过滤函数— filter-out
3 函数功能:  和“ filter”函数实现的功能相反。过滤掉字串“ TEXT”中所有符合模式“ PATTERN”的单词,保留所有不符合此模式的单词。        可以有多个模式。存在多个模式时,模式表达式之间使用空格分割
4 返回值:  空格分割的“ TEXT”字串中所有不符合模式“ PATTERN”的字串。
5 函数说明:  “ filter-out”函数也可以用来去除一个变量中的某些字符串,(实现和“ filter”函数相反)

  代码执行的过程就为,如果 过滤掉 MAKECMDGOALS 不符合 no-dot-config-targets 后结果不为空,则执行分支语句。很显然过滤后为空,则不执行分支语句,dot-config 依然 值为1。

  接着执行下一条 ifeq 语句,对 KBUILD_EXTMOD 进行判定。KBUILD_EXTMODE 的赋值地方在代码 182 到 191 行处:

 1 # Use make M=dir to specify directory of external module to build
 2 # Old syntax make ... SUBDIRS=$PWD is still supported
 3 # Setting the environment variable KBUILD_EXTMOD take precedence
 4 ifdef SUBDIRS
 5   KBUILD_EXTMOD ?= $(SUBDIRS)
 6 endif
 7
 8 ifeq ("$(origin M)", "command line")
 9   KBUILD_EXTMOD := $(M)
10 endif

  由注释可以知道,SUBDIRS 这个变量是通过执行 make 的时候传进来的,我们并没有执行此项,所以未定义SUBDIRS,第一个分支不会去走。第二个 if 语句为 ifeq 语句,这里使用 origin 函数。

  origin 函数不是操作变量(即它的参数),它只是获取此变量(参数)相关的信息,告诉我们这个变量的出处(定义方式)。

  那么 ifeq 语句可以理解为 如果make传入的命令行变量存在且是M,那么,变量KBUILD_EXTMOD变为变量M的值。

  第一阶段中我们并没有传入 M 值,则 KBUILD_EXTMOD 值为空

  继续回到此小节主代码处,当前执行 KBUILD_EXTMOD 的判定,此处满足 ifeq  条件,开始执行分支语句,分支语句同样是一个判断,首先过滤掉 MAKECMDGOALS 不符合 config 和 %config 模式的字符串,然后返回 xxx_defconfig ,xxx_defconfig 再与 空进行比较,if 语句为 ifneq ,很显然, filter  语句不为空,与空进行比较,满足 ifneq 执行语句。

  此处将 config-targets 重新赋值为 1;赋值完后,进行  ifneq  条件判断,再次涉及  makefile 的函数——words。

  

  显然我们的传入的单词数据为1,与1相等,则不执行分支,即 mixed-targets 不进行重新赋值,依然为0。

  再代码进行到 ifeq ($(config-targets),1) 时候,先进行了 ifeq ($(mixed-targets),1)分支,如果 mixed-targets 则执行另一条分支,就不会再执行ifeq ($(config-targets),1) 了。我们这里执行的ifeq ($(mixed-targets),1) 的 else中的分支语句。

  到此处,ifeq ($(config-targets),1) 是否会执行已经分析完毕。

  当前我们已经知道的变量的值为:

  • MAKECMDGOALS = xxx_defconfig
  • KBUILD_EXTMOD =
  • version_h := include/generated/version_autogenerated.h
  • timestamp_h := include/generated/timestamp_autogenerated.h
  • no-dot-config-targets := clean clobber mrproper distclean help %docs check% coccicheck ubootversion backup tests
  • config-targets := 1
  • mixed-targets := 0
  • dot-config := 1

2.1.2 %config分析

  ifeq ($(config-targets),1) 中也由else分支,我们从上面的小节可以知道,else 分支不会去执行。所以很多代码可以忽略了

  

  从这里可以知道,此处此处选择语句一直执行到 1655 行,466~480 行才是我们需要分析的。

  471 到 472 行

1 KBUILD_DEFCONFIG := sandbox_defconfig
2 export KBUILD_DEFCONFIG KBUILD_KCONFIG

  这里定义了两个环境变量:

  • KBUILD_DEFCONFIG = sandbox_defconfig  
  • KBUILD_KCONFIG 为空

  继续执行474 到 475 行

1 config: scripts_basic outputmakefile FORCE
2     $(Q)$(MAKE) $(build)=scripts/kconfig [email protected]

  此处目标没有匹配,不会去执行

  继续执行477 478 行

1 %config: scripts_basic outputmakefile FORCE
2     $(Q)$(MAKE) $(build)=scripts/kconfig [email protected]

  %config 依赖scripts_basic outputmakefile  FORCE

(1)依赖 FORCE

  FORCE 的定义在 1748 和 1749 行

1 PHONY += FORCE
2 FORCE:

  FORCE被定义为一个空目标。如果一个目标添加 FORCE 依赖,每次编译都会去先去执行 FORCE(实际上什么都不做),然后运行命令更新目标,这样就能确保目标每次都会被更新。

(2)依赖 scripts_basic

  392 - 402 行

 1 # ===========================================================================
 2 # Rules shared between *config targets and build targets
 3
 4 # Basic helpers built in scripts/
 5 PHONY += scripts_basic
 6 scripts_basic:
 7     $(Q)$(MAKE) $(build)=scripts/basic
 8     $(Q)rm -f .tmp_quiet_recordmcount
 9
10 # To avoid any implicit rule to kick in, define an empty command.
11 scripts/basic/%: scripts_basic ;

  Q = @,MAKE = make,build 变量的定义在 scripts/Kbuild.include 文件中

  主Makefile 在327-329 行包含 scripts/Kbuild.include 文件

1 # We need some generic definitions (do not try to remake the file).
2 scripts/Kbuild.include: ;
3 include scripts/Kbuild.include

  build 变量在 scripts/Kbuild.include 在177 - 181 行定义

1 ###
2 # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
3 # Usage:
4 # $(Q)$(MAKE) $(build)=dir
5 build := -f $(srctree)/scripts/Makefile.build obj

  srctree 定义在主 Makefile 中202-212 行

 1 ifeq ($(KBUILD_SRC),)
 2         # building in the source tree
 3         srctree := .
 4 else
 5         ifeq ($(KBUILD_SRC)/,$(dir $(CURDIR)))
 6                 # building in a subdirectory of the source tree
 7                 srctree := ..
 8         else
 9                 srctree := $(KBUILD_SRC)
10         endif
11 endif

  KBUILD_SRC (构建的源码目录) 在执行 make 命令的时候并没有传入,设为空,则srctree 为当前 uboot 源码的根目录

  scripts/Kbuild.include 在177 - 181 行的展开为:build := -f ./scripts/Makefile.build obj

  主 Makefile 中 scripts_basic 的展开为:

1 scripts_basic:
2      make -f ./scripts/Makefile.build obj=scripts/basic  # 根据传入的 obj 参数显示的执行 ./scripts/Makefile.build 文件
3      rm -f .tmp_quiet_recordmcount

  ./scripts/Makefile.build 文件之后再分析。

(3)outputmakefile 依赖

  404 - 413 行

 1 PHONY += outputmakefile
 2 # outputmakefile generates a Makefile in the output directory, if using a
 3 # separate output directory. This allows convenient use of make in the
 4 # output directory.
 5 outputmakefile:
 6 ifneq ($(KBUILD_SRC),)
 7     $(Q)ln -fsn $(srctree) source
 8     $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile  9         $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
10 endif

  KBUILD_SRC 为空,所以ifneq 中的语句不会执行。 outputmakefile 为空

  重新回到 %config 处

1 %config: scripts_basic outputmakefile FORCE
2     $(Q)$(MAKE) $(build)=scripts/kconfig [email protected]

  依据前面的条件,展开表达式为:

1 make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig

2.2 总结

2.2.1 变量

  • MAKECMDGOALS = xxx_defconfig
  • KBUILD_EXTMOD =
  • version_h := include/generated/version_autogenerated.h
  • timestamp_h := include/generated/timestamp_autogenerated.h
  • no-dot-config-targets := clean clobber mrproper distclean help %docs check% coccicheck ubootversion backup tests
  • config-targets := 1
  • mixed-targets := 0
  • dot-config := 1
  • KBUILD_SRC =
  • build := -f ./scripts/Makefile.build obj

2.2.2 环境变量

  • KBUILD_DEFCONFIG := sandbox_defconfig
  • KBUILD_KCONFIG =

2.2.3 需要进行分析的地方

(1)scripts_basic 目标执行的命令

  make -f ./scripts/Makefile.build obj=scripts/basic

(2)%config 目标执行的命令

  make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig

原文地址:https://www.cnblogs.com/idyllcheung/p/11206629.html

时间: 2024-11-08 17:06:47

二、编译第一步 make xxx_defconfig的相关文章

第一讲 从头开始做一个web qq 机器人,第一步获取smart qq二维码

新手教程: 前言:最近在看了一下很久很久以前做的qq机器人失效了,最近也在换工作目前还在职,时间很挺宽裕的.就决定从新搞一个web qq机器人 PC的协议解析出来有点费时间以后再做. 准备工作: 编译工具:vs2017 编程语言:C# 或者.net 开始建一个SDK  新建文件 -项目 -选择类库-(WEBQQSDK)-添加一个类 smartqq 第一步,登录了一下Smart QQ,以这个HTTP协议,做机器人交互吧,TX把这个版本的很多功能去掉了,基本的群聊,私聊 收发信息之类还在.(用谷歌浏

【转】APUE学习1:迈出第一步,编译myls.c

原文网址:http://blog.csdn.net/sddzycnqjn/article/details/7252444 注:以下写作风格均学习自潘云登前辈 /******************************************************************/   By:             聂强 Date:          2012-2-12 Email:         [email protected] Homepage: http://blog.c

APP反编译第一课《如何找到核心代码》

相信很多人都应该会去接触APP反编译,本小七给大家带来入门级别套路,自己也在慢慢摸索学习,一起成长吧.第一步,反编译需要的工具有:一.java环境,其实这里你只要安装了burp就不用管这个的二.apktool工具三.dex2jar工具四.sublime工具:Sublime Text 是一款流行的代码编辑器软件,也是HTML和散文先进的文本编辑器,可运行在Linux,Windows和Mac OS X.五.jd-gui.exe工具首先我们来看看 Apk 文件的结构: META-INF:签名文件(这个

Java 学习第一步-JDK安装和Java环境变量配置

Java学习第一步——JDK安装及Java环境变量配置 [原文] 2014-05-30 9:09  Java SE  阿超  9046 views Java作为当下很主流的编程语言,学习Java的朋友也越来越多了,作为一门面向对象的编程语言,Java也有着安全.高效等诸多有点.从TIOBE(TIOBE排行榜是根据互联网上有经验的程序员.课程和第三方厂商的数量,并使用搜索引擎(如Google.Bing.Yahoo!.百度)以及Wikipedia.Amazon.YouTube统计出排名数据,只是反映

第一节,基础知识之第一步:代数

先声明:theano模块的内容大都是参考来源于网上,并亲手实践复现一遍,也有部分内容是自己补充 本文会列出所参考文章,如有版权问题,请联系我,我会及时删除 # -*- coding: utf-8 -*- """ Created on Fri Mar 23 13:33:20 2018 @author: zy """ '''x= T.dscalar('x')y= T.dscalar('y')z = x + yf = theano.function([

TensorFlow实战-TensorFlow第一步-第3章

3 TensorFlow第一步 39 3.1 TensorFlow的编译及安装 39 install ancondalink CPU versionconda install tensorflow GPU versionconda install tensorflow-gpu 3.2 TensorFlow实现SoftmaxRegression识别手写数字 46 导入数据 MNIST是一个非常简单的机器视觉数据集,由几万张28x28像素的手写数字组成,这些图片只包含灰度信息. 123456 fro

第三 章、面向对象 第一步部分

一.类与对象的基本概念 类:抽象的概念集合,表示的是一个共性的产物,类之中定义的是属性和行为(方法): 对象:是一种个性的表示,表示一个独立的个体,每个对象拥有自己独立的属性,依靠属性区分不同的对象. 类与对象的区别:类是对象的模板,对象是类的实例,类只有通过对象才可以使用,开发中应该先产生类,再产生对象.类不能直接使用,方法可以直接使用. 二.类与对象的定义 1.类的定义: 在JAVA中定义类,可以使用class关键字完成, 语法为: 1 class 类名称{ 2 属性(变量): 3 行为(方

标题优化是google海外推广的第一步吗

在很多站长的眼里,都认为标题优化是google推广的第一步,但真的是这样吗?下面具体分析分析其中的正确性. 1.网站标题应该对用户有足够的吸引力. 什么都有就是没有重点,网页标题好像一个人的头衔一样,如果你看到一张名片上印了十几个头衔,你会很鄙视这个人,而对于这样的网页,搜索引擎也不喜欢.所以,你的一个网页只要用一个主要的关键词写入标题中,如果一个意思有多个表达,可以适当列举几个.比如"网站运营-网站运营方案下载"这样还是可以的.搜索引擎也是根据网站标题和网站内容判定你的网站主要写的是

mac下zephir第一步,安装+hello zephir!

第一步 安装autoconf re2c automake libtool等依赖,如果没有安装git的记得先安装git brew install autoconf brew install automake brew install libtool brew install re2c 第二步,下载源代码安装 git clone http://github.com/phalcon/zephir cd zephir ./install -c 第三步,测试zephir是否安装成功 zephir help