u-boot顶层Makefile分析(转)

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

要了解一个LINUX工程的结构必须看懂Makefile,尤其是顶层的,没办法,UNIX世界就是这么无奈,什么东西都用文档去管理、配置。首先在这方面我是个新手,时间所限只粗浅地看了一些Makefile规则。

以smdk_2410为例,顺序分析Makefile大致的流程及结构如下:

1) Makefile中定义了源码及生成的目标文件存放的目录,目标文件存放目录BUILD_DIR可以通过make O="dir" 指定。如果没有指定,则设定为源码顶层目录。一般编译的时候不指定输出目录,则BUILD_DIR为空。其它目录变量定义如下:

#OBJTREE和LNDIR为存放生成文件的目录,TOPDIR与SRCTREE为源码所在目录
OBJTREE   := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))



export   TOPDIR SRCTREE OBJTREE

2)定义变量MKCONFIG:这个变量指向一个脚本,即顶层目录的mkconfig。


export MKCONFIG

smdk2410_config

smdk2410_config : unconfig
 @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0

unconfig:
 @rm -f $(obj)include/config.h $(obj)include/config.mk \
  $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp

显然,执行# make smdk2410_config时,先执行unconfig目标,注意不指定输出目标时,obj,src变量均为空,unconfig下面的命令清理上一次执行make *_config时生成的头文件和makefile的包含文件。主要是include/config.h 和include/config.mk文件。

 @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
MKCONFIG 是顶层目录下的mkcofig脚本文件,后面五个是传入的参数。

对于smdk2410_config而言,mkconfig主要做三件事:


#ln -s     asm-arm        asm  


#ln -s     proc-armv       asm-arm/proc

生成Makefile包含文件include/config.mk,内容很简单,定义了四个变量:

ARCH   = arm
CPU    = arm920t
BOARD  = smdk2410

/* Automatically generated - do not edit */
#include "config/smdk2410.h"

mkconfig

3)包含include/config.mk,其实也就相当于在Makefile里定义了上面四个变量而已。

ifeq ($(ARCH),arm)#
CROSS_COMPILE = arm-linux-
endif

#包含顶层目录下的config.mk,这个文件里面主要定义了交叉编译器及选项和编译规则
# load other configuration
include $(TOPDIR)/config.mk


sinclude $(TOPDIR)/$(ARCH)_config.mk # include architecture dependend rules
endif
ifdef CPU #定义编译时对齐,浮点等选项
sinclude $(TOPDIR)/cpu/$(CPU)/config.mk # include  CPU specific rules
endif
ifdef SOC #没有这个文件
sinclude $(TOPDIR)/cpu/$(CPU)/$(SOC)/config.mk # include  SoC specific rules
endif

ifdef BOARD
sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk # include board specific rules
endif

# Include the make variables (CC, etc...)
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
RANLIB = $(CROSS_COMPILE)RANLIB

@定义AR选项ARFLAGS,调试选项DBGFLAGS,优化选项OPTFLAGS

 预处理选项CPPFLAGS,C编译器选项CFLAGS,连接选项LDFLAGS

 LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)

$(obj)%.s: %.S
$(CPP) $(AFLAGS) -o $@ $<
$(obj)%.o: %.S
$(CC) $(AFLAGS) -c -o $@ $<
$(obj)%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<

OBJS  = cpu/$(CPU)/start.o #

LIBS  = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
LIBS += cpu/$(CPU)/lib$(CPU).a
ifdef SOC
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a
endif
LIBS += lib_$(ARCH)/lib$(ARCH).a
LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \
 fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a
LIBS += net/libnet.a
LIBS += disk/libdisk.a
LIBS += rtc/librtc.a
LIBS += dtt/libdtt.a
LIBS += drivers/libdrivers.a
LIBS += drivers/nand/libnand.a
LIBS += drivers/nand_legacy/libnand_legacy.a
LIBS += drivers/sk98lin/libsk98lin.a
LIBS += post/libpost.a post/cpu/libcpu.a
LIBS += common/libcommon.a

LIBS := $(addprefix $(obj),$(LIBS))

根据上面的include/config.mk文件定义的ARCH、CPU、BOARD、SOC这些变量。硬件平台依赖的目录文件可以根据这些定义来确定。SMDK2410平台相关目录及对应生成的库文件如下。
:库文件board/smdk2410/libsmdk2410.a
    cpu/arm920t/            :库文件cpu/arm920t/libarm920t.a
    cpu/arm920t/s3c24x0/    :库文件cpu/arm920t/s3c24x0/libs3c24x0.a
    lib_arm/                :库文件lib_arm/libarm.a
    include/asm-arm/        :下面两个是头文件。
    include/configs/smdk2410.h

ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)

$(obj)u-boot.hex: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@

$(obj)u-boot.srec: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@

$(obj)u-boot.bin: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@

$(obj)u-boot:  depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
  UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed  -n -e ''''''''''''''''''''''''''''''''s/.*\(__u_boot_cmd_.*\)/-u\1/p''''''''''''''''''''''''''''''''|sort|uniq`;\
  cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
   --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
   -Map u-boot.map -o u-boot

@:生成各个子目录的.depend文件,.depend列出每个目标文件的依赖文件。生成方法,调用每个子目录的make _depend。

depend dep:
  for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir _depend ; done

@

version:
  @echo -n "#define U_BOOT_VERSION \"U-Boot " > $(VERSION_FILE); \
  echo -n "$(U_BOOT_VERSION)" >> $(VERSION_FILE); \
  echo -n $(shell $(CONFIG_SHELL) $(TOPDIR)/tools/setlocalversion \
    $(TOPDIR)) >> $(VERSION_FILE); \
  echo "\"" >> $(VERSION_FILE)

@: 执行tools ,examples ,post,post\cpu 子目录下面的make文件。

SUBDIRS = tools \
   examples \
   post \
   post/cpu
.PHONY : $(SUBDIRS)

$(OBJS):
  $(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))

@,这个目标太多,都是每个子目录的库文件*.a ,通过执行相应子目录下的make来完成:

$(LIBS):
  $(MAKE) -C $(dir $(subst $(obj),,$@)) 

LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)

对于smdk2410,LDSCRIPT即连接脚本文件是board/smdk2410/u-boot.lds,定义了连接时各个目标文件是如何组织的。内容如下:

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
 . = 0x00000000;

 . = ALIGN(4);
 .text    :/*.text的基地址由LDFLAGS中-Ttext $(TEXT_BASE)指定*/
 {                      /*smdk2410
   cpu/arm920t/start.o (.text)         /*start.o

 . = .;
 __u_boot_cmd_start = .;
 .u_boot_cmd : { *(.u_boot_cmd) }
 __u_boot_cmd_end = .;

 . = ALIGN(4);
 __bss_start = .;
 .bss : { *(.bss) }
 _end = .;
}

cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
   --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
   -Map u-boot.map -o u-boot

其实就是把start.o和各个子目录makefile生成的库文件按照LDFLAGS连接在一起,生成ELF文件u-boot 和连接时内存分配图文件u-boot.map。

9)对于,主要是生成*.o文件然后执行AR生成对应的库文件。如lib_generic文件夹Makefile:

LIB = $(obj)libgeneric.a

COBJS = bzlib.o bzlib_crctable.o bzlib_decompress.o \
   bzlib_randtable.o bzlib_huffman.o \
   crc32.o ctype.o display_options.o ldiv.o \
   string.o vsprintf.o zlib.o

SRCS  := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))

$(LIB): $(obj).depend $(OBJS) #项层Makefile执行make libgeneric.a
 $(AR) $(ARFLAGS) $@ $(OBJS)

整个makefile剩下的内容全部是各种不同的开发板的*_config:目标的定义了。

概括起来,工程的编译流程也就是通过执行执行一个make *_config传入ARCH,CPU,BOARD,SOC参数,mkconfig根据参数将include头文件夹相应的头文件夹连接好,生成config.h。然后执行make分别调用各子目录的makefile 生成所有的obj文件和obj库文件*.a.  最后连接所有目标文件,生成镜像。不同格式的镜像都是调用相应工具由elf镜像直接或者间接生成的。

U-Boot顶层Makefile详解 直接参考【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.81本文仅作为个人笔记使用,方便进一步记录自己的实践总结。上一章我们详细的讲解了 uboot 的使用方法,其实就是各种命令的使用,学会 uboot 使用以后就可以尝试移植 uboot 到自己的开发板上了,但是在移植之前需要我们得先分析一遍 uboot的启动流程源码,得捋一下 uboot 的启动流程,否则移植的时候都不知道该修改那些文件。 阅读详情

相关推荐

U-Boot 顶层 Makefile 详解

U-Boot 顶层 Makefile 详解 1、U-Boot 工程目录分析 我们在分析 uboot 源码之前一定要 先在 Ubuntu 中编译一下 uboot 源码,因为编译过程会生成一些文件,而生成的这些恰恰是分析 uboot 源码不可或缺的文件。使用上一章创建的 shell 脚本来完成编译工作,命令如下: cd alientek_uboot //进入正点原子 uboot 源码目录 ./mx6ull_alientek_emmc.sh //编译 uboot cd ../ //返回上一级目录 tar -vcj

嵌入式技术 1654

02-分析uboot编译过程

分析uboot编译过程 make 查看顶层Makefile include $(OBJTREE)/include/config.mk 包含的就是配置时生成的config.mk文件 export ARCH CPU BOARD VENDOR SOC 从include/config.mk得到以下几个参数的值 ARCH = arm CPU = arm920t BOARD = 100a...

zhhe14的博客 269

u-boot顶层Makefile分析及u-boot启动流程分析

清理整个u-boot工程,包括编译出来的.o 、.h 、.bin 、 .imx 、.config 等,其中最重要的是.config,它是由使用u-boot的工程师来根据自己需要配置出来的文件,所以在清除时最好备份一下.config。

qq_42745986的博客 1220

Makefile 小知识

解决库文件的循环依赖关系 $(EXEC): $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) -Wl,--start-group $(LDLIBS) -Wl,--end-group @cp $@ $@.elf   -Wl,--start-group $(LIBS) -Wl,--end-group 以下是英文解释: -( archi...

CodingTheFuture 580

(3)Makefie:C语言编译标志、通配符、CFLAGS、LDFLAGS、LDLIBS

Makefie:C语言编译标志、通配符、CFLAGS、LDFLAGS、LDLIBS、-Wl,--start-group-Wl,--end-group、$(LDLIBS_$@)、$^和$@的使用、句子前面加@:不输出到终端、目标文件依赖于头文件、%_output的使用、%_only

weixin_45981798的博客 1930

实用的GCC Makefile语法及参数详解

实用的GCC Makefile语法及参数详解

yangsong4353的博客 2115

:Linux内核Makefile浅析

Linux内核Makefile浅析  1. 配置系统的基本结构 Linux内核的配置系统由三个部分组成,分别是: Makefile:分布在 Linux 内核源代码中的 Makefile,定义 Linux 内核的编译规则; 配置文件(config.in):给用户提供配置选择的功能; 配置工具:包括配置命令解释器(对配置脚本中使用的配置命令进行解释)和配置用户界面(提供基于字符界面、基于

melvda的专栏 546

u-boot的的makefile分析

<br />u-bootMakefile分析<br /><br />   U-BOOT是一个LINUX下的工程,在编译之前必须已经安装对应体系结构的交叉编译环 境,这里只针对ARM,编译器系列软件为arm-linux-*。<br /><br />   U-BOOT的下载地址: http://sourceforge.net/projects/u-boot<br />   我下载的是1.1.6版本,一开始在FTP上下载了一个次新 版,结果编译失败。1.1.6是没问题的。<br /><br />

PCWUNG的专栏 687

U-boot顶层Makefile分析及编译流程

梳理了一下正点原子教程中对u-boot编译过程的讲解,方便回头查阅

xi_xix_i的博客 2556

关于Linux U-boot顶层Makefile分析

顶层Makefile定义了U-boot构建过程中的主要目标(如编译,链接等),并通过对Kconfig和.config文件的引用来决定编译过程中需要包含哪些模块和功能(Kconfig其实就是一个配置脚本,其中包括了配置关系,依赖关系,菜单结构,默认值,帮助文字,而.config文件就是由Kconfig脚本生成的配置结果文件)。以下就是部分的Kconfig文件,可以看到在Kconfig中有非常多的配置文件,下面我们以config LOCALVERSION_AUTO为例,可以看到第一行。

weixin_44226801的博客 970

imx6ull-系统移植篇5——U-Boot 顶层 Makefile 简析

本文简单分析了U-Boot顶层Makefile的关键功能与编译流程。

m0_62228566的博客 1871

6.2 U-boot 顶层 Makefile

如果要分析uboot源码,首先要将uboot源码进行编译,编译需要在Ubuntu进行,把uboot文件放在一个目录下。编译完成后的文件是这样:我们需要看的文件夹如下。

Toutiegongzhu的博客 2065

U-Boot 顶层 Makefile 详解1之U-Boot 工程目录分析

分析uboot顶层 Makefile,理清了 uboot 的编译流程。

Redhat_yan 1101

U-Boot 顶层Makefile 详解

1、准备工作 2、重要文件 2.1、arch文件 2.2、 board 文件夹 2.3、 configs 文件夹 2.4、 .u-boot.xxx_cmd 文件 2.5、 Makefile 文件 2.6、 u-boot.xxx 文件 2.7、 .config 文件 2.8、 README

zhuguanlin121的博客 2192

U-BOOT顶层MAKEFILE详解

U-BOOT顶层MAKEFILE详解 1) U-Boot 配置过程 # (C) Copyright 2000-2006 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.            # See file CREDITS for list of people who contributed to this

2302

U-Boot顶层Makefile分析

顶层Makefile也就是uboot根目录下的Makefile文件,由于顶层Makefile文件内容比较多,所以我们将其分开来看。本文主要参考正点原子。

qq_64033704的博客 968

U-BOOT分析(二)之顶层Makefile文件(1)

uboot顶层Makfile分析,介绍Makefile编译uboot的前期make设置,编译前的准备过程,config文件的解析,uboot 的编译等。

u012826733的博客 2059

U-Boot顶层Makefile介绍

U-Boot顶层Makefile介绍1、准备好uboot源码2、分析顶层Makefile2.1、版本号2.2、MAKEFLAGS 变量2.3、命令输出2.4、静默输出2.5、设置编译结果输出目录2.6、代码检查2.7、模块编译2.8、获取主机架构和系统2.9 、设置目标架构、交叉编译器和配置文件2.10、调用 scripts/Kbuild.include2.11、交叉编译工具变量设置3.12、导出其他变量 1、准备好uboot源码 这里分析的是2016.版本的uboot。 uboot源码下载:https:/

一只青木呀 1380
上一篇: 微kernel和单kernel
下一篇: bison & flex
我不会Debug
博客等级 码龄16年 47粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值