【IMX6ULL学习笔记】三、U-BOOT Makefile详解

发布者:快乐奇迹最新更新时间:2025-03-05 来源: cnblogs关键字:U-BOOT  Makefile 手机看文章 扫描二维码
随时随地手机看文章

00、通识

版本号


VERSION = 2016      //主版本号

PATCHLEVEL = 03 //补丁版本号

SUBLEVEL = //次版本号

EXTRAVERSION =      //附加版本信息

NAME = //名字有关的,一般不使用这两个

MAKEFLAGS 变量


export VARIABLE //导出变量给子 make 

unexport VARIABLE    //不导出变量给子 make


MAKEFLAGS += -rR --include-dir=$(CURDIR)  

MAKEFLAGS /SHELL 值始终自动的传递给子make  除非使用“unexport”声明


-rR : 表示禁止使用内置的隐含规则和变量定义

--include-dir : 指明搜索路径

$(CURDIR): 表示当前目录

编译选项


V=1          来实现完整的命令输出

O=out        指定输出目录

C = 1        使能代码检查

M=dir        单独编译某个模块

HOSTARCH     主机架构

HOSTOS       系统

ARCH         架构 //ARCH = arm

CROSS_COMPILE  交叉编译工具 //arm-linux-gnueabihf- (只到 “ - ”)

CC = $(CROSS_COMPILE)gcc   //CC 为编译gcc的简短语法

常用变量


ARCH = arm

CPU = armv7

BOARD = mx6ullevk

VENDOR = freescale

SOC = mx6

CPUDIR = arch/arm/cpu/armv7

BOARDDIR = freescale/mx6ullevk

ARCH、CPU、BOARD、VENDOR、SOC、CPUDIR、BOARDDIR 等变量定义在 config.mk 文件:


config.mk:


ARCH := $(CONFIG_SYS_ARCH:'%'=%)      

CPU := $(CONFIG_SYS_CPU:'%'=%)     //'%'=% 取双引号里面的值

.....


= 是最基本的赋值

:= 是覆盖之前的值

?= 是如果没有被赋值过就赋予等号后面的值

+= 是添加等号后面的值

01、清除过程

make distclean 或者 make mrproper

会调用顶层的Makefile的 distclean 规则。

image

02、配置工程,生成.config配置文件

make xxx_defconfig

会调用顶层的Makefile的 %config 规则。

image

%config 规则: %通配符,当输入“make xxx_defconfig”的时候就会匹配到%config 目标:


%config: scripts_basic outputmakefile FORCE

第一步:依赖部分

目标 %config 依赖于 scripts_basic、outputmakefile、FORCE


1、FORCE目标:

FORCE 在顶层 Makefile的 1610 行有如下定义:


PHONY += FORCE

FORCE:

FORCE 是没有规则和依赖的,所以每次都会重新生成 FORCE。当 FORCE 作为其他目标的依赖时,由于 FORCE 总是被更新过的,因此依赖所在的规则总是会执行的。即将FORCE当做依赖时,对应的目标规则总是会被执行。


2、scripts_basic目标:

image

目标不依赖其它目标,会执行以下规则命令:


$(Q)$(MAKE) $(build)=scripts/basic

其中:


Q是显示方式:静默make -s;详细make V=1;不显示make V=0

MAKE=make

build定义在scriptskbuild.include

    build := -f $(srctree)/scripts/Makefile.build obj

    展开后:

    build := -f ./scripts/Makefile.build obj

展开后:


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

@rm -f .tmp_quiet_recordmcount

最终会调用文件./scripts/Makefile.build


3、outputmakefile目标:

image

可以通过echo查看KBUILD_SRC为空


mytest:

    @echo KBUILD_SRC = $(KBUILD_SRC)

所以该目标规则没有执行如何命令。


第二步:命令部分

目标 %config 依赖于 scripts_basic、outputmakefile、FORCE ,执行以下命令:


 $(Q)$(MAKE) $(build)=scripts/kconfig $@

展开:


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

也跟文件./scripts/Makefile.build 有关


第三步:Makefile.build

上面的分析最后指向以下两条命令:


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

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

1、 scripts_basic 目标对应的命令:

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

打开文件 scripts/Makefile.build,有如下代码:


# Modified for U-Boot

prefix := tpl

src := $(patsubst $(prefix)/%,%,$(obj))

ifeq ($(obj),$(src))

prefix := spl

src := $(patsubst $(prefix)/%,%,$(obj))

ifeq ($(obj),$(src))

prefix := .

endif

endif

# The filename Kbuild has precedence over Makefile

kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))

kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)

include $(kbuild-file)

使用@echo打印各个变量值,结果如下:


src= scripts/basic

kbuild-dir = ./scripts/basic

kbuild-file = ./scripts/basic/Makefile

include ./scripts/basic/Makefile

其中src的值即为obj=scripts/basic的值。

make执行时未指定目标,会执行Makefile.build中的默认目标,如下:


__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y))

$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target))

$(subdir-ym) $(always)

@:

其中KBUILD_BUILTIN = 1、KBUILD_MODULES = 0,展开后即为:


__build:$(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)

@:

image.png?imageView2/2/w/1000


include ./scripts/basic/Makefile

2、 %config 目标对应的命令:

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

src的值即为obj=scripts/basic的值,所以Makefile.build中各个变量值如下:


src= scripts/kconfig

kbuild-dir = ./scripts/kconfig

kbuild-file = ./scripts/kconfig/Makefile

include ./scripts/kconfig/Makefile

include包含了./scripts/kconfig目录下的Makefile,执行make时会调用scripts/kconfig/ Makefile中的内容,此文件有如下所示内容:


%_defconfig: $(obj)/conf

    $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)


# Added for U-Boot (backward compatibility)

%_config: %_defconfig

    @:

目标%_defconfig 刚好和我们输入的 xxx_defconfig 匹配,依赖为$(obj)/conf,展开后就是 scripts/kconfig/conf。接下来就是检查并生成依赖scripts/kconfig/conf。


得到 scripts/kconfig/conf 以后就要执行目标%_defconfig 的命令:


 $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)

将其展开就是:


@ scripts/kconfig/conf --defconfig=arch/../configs/xxx_defconfig Kconfig

结果是将配置输出到.config 文件中,最终生成 uboot 根目录下的.config 文件。


整体流程图:

image

参考正点原子linux驱动开发指南,使用conf程序去生成.config;另一种旧版使用mkconfig 去生成config.mk 、config.h。


03.make 生成 u-boot.bin 等文件

make   //编译u-boot,未指定目标将执行Makefile中默认目标

image

没有指明目标,使用默认的目标。

image

如果 KBUILD_EXTMOD(编译模块) 为空的话 _all 依赖于all:


all: $(ALL-y)

其中all依赖于ALL-y,即依赖于 u-boot.srec、u-boot.bin、u-boot.sym等:

image

u-boot.bin 依赖 u-boot-nodtb.bin、FORCE目标:

image

u-boot-nodtb.bin 依赖 u-boot、FORCE目标:

image

image.png?imageView2/2/w/1000


image

image.png?imageView2/2/w/1000

image

image.png?imageView2/2/w/1000

image

u-boot 依赖 $(head-y):

head-y在 arch/arm/Makefile 定义,即 u-boot 依赖 start.o :


head-y := arch/arm/cpu/$(CPU)/start.o

u-boot 依赖 $(libs-y):

libs-y 在顶层 Makefile 中定义,为依赖的源码文件目录:

image

image.png?imageView2/2/w/1000

$(patsubst ,,)


名称:模式字符串替换函数


功能:查找 中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式

,如果匹配的话,则以替换。这里,可以包括通配符 % ,

表示任意长度的字串。如果 中也包含 % ,那么,中的这

个 % 将是 中的那个 % 所代表的字串。(可以用 来转义,以 % 来表示真实含义的 % 字符)


返回:函数返回被替换过后的字符串。

image

表示 u-boot 依赖 libs-y 所指定的所有源码路径下的 built-in.o 文件


结论

image

image

u-boot 依赖 start.o、 built-in.o 文件,u-boot 将 built-in.o、start.o 文件链接在一起


04.链接

u-boot.lds 为链接脚本,将 arch/arm/cpu/armv7/start.o 和各个子目录下的 built-in.o 链接在一起生成 u-boot。


05.备注

make xxx_defconfig:用于配置 uboot,这个命令最主要的目的就是生成.config 文件。

make:用于编译 uboot,这个命令的主要工作就是生成二进制的 u-boot.bin 文件和其他的一些与 uboot 有关的文件,比如 u-boot.imx 等。


关键字:U-BOOT  Makefile 引用地址:【IMX6ULL学习笔记】三、U-BOOT Makefile详解

上一篇:【IMX6ULL学习笔记】四、 U-BOOT启动流程
下一篇:【IMX6ULL学习笔记】二、U-Boot命令合集

推荐阅读最新更新时间:2026-03-22 13:16

IMX6ULL学习笔记】三、U-BOOT Makefile详解
00、通识 版本号 VERSION = 2016 //主版本号 PATCHLEVEL = 03 //补丁版本号 SUBLEVEL = //次版本号 EXTRAVERSION = //附加版本信息 NAME = //名字有关的,一般不使用这两个 MAKEFLAGS 变量 export VARIABLE //导出变量给子 make unexport VARIABLE //不导出变量给子 make MAKEFLAGS += -rR --include-dir=$(CURDIR) MAKEFLAGS /SHELL 值始终自动的传递给子make 除非使用“unexport”声明 -rR : 表示禁止使用内置的
[单片机]
【<font color='red'>IMX6ULL</font>学习笔记】三、<font color='red'>U-BOOT</font> <font color='red'>Makefile</font>详解
U-Boot Makefile分析(4)具体子Makefile的分析
  前面分析的都是多数Makefile要读入的文件,这次我们以drivers/mtd/nand/Makefile为例,分析一个具体的子Makefile是如何工作的。   子Makefile的结构是固定的: include $(TOPDIR)/config.mk     读入配置信息 LIB := $(obj)lib_name.o        当前Makefile的目标文件 添加源文件,COBJS-y是要编译的对象。 COBJS := $(COBJS-y)        指定目标文件 SRCS := $(COBJS:%.o=%.c)     指定源文件 OBJS := $(addprefix $(obj),$(COBJS)) 给目
[单片机]
1_5.1.2_U-boot分析与使用_u-boot分析之Makefile结构分析_P
我们分析一个文件的时候,最好的方式就是看它的makefile。 之前体验编译uboot时,我们第一步是配置uboot,第二步是编译。 分析配置uboot指令 配置uboot使用的指令是make 100ask24x0_config。 首先找到Makefile,用vim打开,查找100ask24x0_config,定位如下: 那么make 100ask24x0_config其实就是执行@$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0指令,下面分析这条指令。 最左边的@符号表示执行该命令时不在终端显示该命令,然后是一个变量MKCONFIG,查
[单片机]
1_5.1.2_U-boot分析与使用_<font color='red'>u-boot</font>分析之<font color='red'>Makefile</font>结构分析_P
编译IMX6ULL开发板的Uboot和内核(一)
一《安装第三方库》 基于迅为imx6ull开发板,在编译 Uboot 和内核源码之前,我们需要安装三个第三库他们分方别是:lzop 、libncurses5-dev。 、u-boot-tools。首先在 Ubuntu 系统桌面打开终端,如下图所示: 然后在终端输入“sudo apt-get install lzop”命令,开始安装 lzop 库文件,如下图所示: 然后回车运行,会提示我们输入用户名密码,输完密码,开始继续安装,最后安装完成,如下图所示: 然后我们在终端输入“sudo apt-get install u-boot-tools”命令,最后完成安装,如下图所示: 然后我们在终端输入“sudo ap
[单片机]
编译<font color='red'>IMX6ULL</font>开发板的Uboot和内核(一)
Linux内核启动流程-迅为IMX6ULL开发板(一)
在前面的章节介绍了uboot和Linux内核的一些相关内容。在来看Linux内核的大致启动流程,Linux内核的启动流程要比uboot复杂的多,涉及到的内容也更多,因此在本章节大致简单的了解一下Linux内核的启动流程。有兴趣的用户可以参考其他书籍或资料进行深入了解。 嵌入式linux内核的启动全过程主要分为三个阶段。第一阶段为内核自解压过程,第二阶段主要工作是设置ARM处理器工作模式、使能MMU、设置一级页表等,而第三阶段则主要为C代码,包括内核初始化的全部工作。下面分别进行简单介绍。 基于迅为-IMX6ULL开发板 30.1 Linux内核启动(一):Linux内核自解压过程 Linux内核有两种映像格式:一种是非压缩
[单片机]
Linux内核启动流程-迅为IMX6ULL开发板(二)
start_kernel是所有Linux平台进入系统内核初始化后的入口函数,它主要完成剩余的与 硬件平台相关的初始化工作,在进行一系列与内核相关的初始化后,调用第一个用户进程- init 进程并等待用户进程的执行,这样整个 Linux内核便启动完毕。 30.3.1 start_kernel 函数 start_kernel 通过调用众多的子函数来完成 Linux 启动之前的一些初始化工作,由于start_kernel 函数里面调用的子函数太多,而这些子函数又很复杂,因此我们简单介绍一下一些重要的子函数。start_kernel 函数定义在文件 init/main.c中。精简并添加注释后的 start_kernel 函数内容如下:
[单片机]
迅为IMX6ULL开发板Linux驱动初探-最简单的设备驱动-helloworld
经过前面的学习,我们了解了驱动开发的框架,本章节将带领大家实验操作,写最简单的驱动-helloworld。 Linux 设备驱动会以内核模块的形式出现,因为 linux 内核的整体架构就非常庞大,包含的组件也非常多,如果把所有的功能都编译到 linux 内核中会使得内核非常臃肿,为了解决这个问题,更方便地新增和删除功能,linux 提供了这样的机制,这种机制被称为模块。为了大家对模块有一个感性的认识,我们先来看一个最简单的驱动-helloworld。 驱动分为四个部分:  头文件  驱动模块的入口函数和出口函数  声明信息  功能实现 我们在 windows 上面新建一个 helloworld.c 文件,这里使用 sour
[单片机]
迅为<font color='red'>IMX6ULL</font>开发板Linux驱动初探-最简单的设备驱动-helloworld
迅为IMX6ULL开发板Buildroot文件系统构建-配置Busybox
Buildroot 也是基于 busybox 制作的文件系统,所以我们 buildroot 里的 busybox 也可以进行配置。首先我们在 buildroot 源码目录下,使用命令“ make busybox-menuconfig”,如下图所示: 在这里我们可以看到 busybox 版本是 1.29.3,然后就是我们之前看到过得 busybox 配置界面了,用户可根据自己需要配置。如下图所示: 然后我们使用命令“make busybox”即可单独编译 busybox。如下图所示: 最后编译完成以后使用命令“make”重新编译 buildroot,主要是对其进行打包,如下图所示: 重新编译完成以后查看 output/ima
[单片机]
迅为<font color='red'>IMX6ULL</font>开发板Buildroot文件系统构建-配置Busybox
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved