电子大神的日记本,供应链专家的功夫茶盘,在这里记录、分享与共鸣。

登录以开始

u-boot的Makefile分析

u-boot的Makefile分析

 

U-BOOT是一个LINUX下的工程,在编译之前必须已经安装对应体系结构的交叉编译环境,这里只针对ARM,编译器系列软件为 ppc_6xx-。U-BOOT的下载地址:http://sourceforge.net/projects/u-boot
我下载的是1.1.5版本

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

几个重要的文件分析:

u-boot-1.1.5/Makefile

u-boot-1.1.5/mkconfig

u-boot-1.1.5/config.mk

u-boot根目录下的Makefile文件(u-boot-1.1.5/Makefile)它负责配置u-boot的编译方式,具体说来包括:使用何种指令集,需包含哪些接口驱动、库等。Makefile的内容从上到下分别是:分定义编译环境:使用何种编译器、编译方式、目标文件的生成及它们最终镜像中的链接次序等。Mkconfig和config.mk在接下来的分析中会涉及到。

在编译U-BOOT之前,先要执行

# make cpci5200_config

cpci5200_config是Makefile的一个目标,定义如下:

cpci5200_config:  unconfig

   @$(MKCONFIG) -a cpci5200  ppc mpc5xxx cpci5200 esd

其中,unconfig定义如下:

unconfig:

       @rm -f $(obj)include/config.h $(obj)include/config.mk /

              $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp

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

然后才执行命令

@$(MKCONFIG) -a cpci5200  ppc mpc5xxx cpci5200 esd

$(MKCONFIG)就会被替换成$(SRCTREE)/mkconfig文件路径, MKCONFIG 是顶层目录下的mkcofig脚本文件(u-boot-1.1.5/mkconfig),后面五个是传入的参数。Mkconfig文件的详细分析见文档末尾。

注意一下u-boot对板卡的分类方法:
Target:宿主机平台
Architecture:定义芯片架构(如MIPS、POWERPC、ARM等)
CPU:定义芯片指令集版本(如ARM7、ARM9、ARM11等)
Board:芯片厂商,它细分为两类
[VENDOR]:按厂商划分(如AT9200、S3C44B0等)
[SOC]:按SOC类型(如S3C2440、S3C2410等)

1)对于cpci5200_config而言,mkconfig主要做三件事:

在include文件夹下建立相应的文件(夹)软(符号)连接,

#如果是PPC体系将执行以下操作:
#ln -s     asm-ppc        asm  

#ln -s arch-mpc5xxx    asm-ppc/arch 
#ln -s   proc-armv       asm-ppc/proc

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

ARCH   = ppc
CPU    = mpc5xxx
BOARD = cpci5200
VENDOR    = esd

这些变量可以供其它的makefile使用,作为一个基本配置.

生成include/config.h头文件,只有一行:

echo“/* Automatically generated - do not edit */”>>config.h
echo“#include ”>>config.h

这两行代码生成一个include/config.h文件,这个文件很简单,只有一句话:
    #include <$1.h> 当然这里的$1时要被替换成不同的board名字的.这个取决于我们在主Makefile中xxxx_config目标中的xxxx是什么.

mkconfig脚本文件的执行至此结束

2)分析config.mk的内容:

u-boot根目录下自带一个config.mk文件(u-boot-1.1.5/config.mk),应 该说这才是真正的Makefile,以上介绍的两个脚本Makefile和mkconfig完成了环境配置之后,在该文件中才定义具体的编译规则,所以你会发现在各个子模块(board、 cpu、lib_xxx、net、disk...)目录中的Makefile第一句就是:include $(TOPDIR)/config.mk。文件内容分析如下:

这个文件的功能就是给各个在编译过程中的变量赋值,包括编译执行的函数与编译的时候所带的参数等等。还会根据是否定义了ARCH,CPU,SOC,VENDOR,BOARD来决定是否包含相应位置的config.mk文件,这些个文件里,也是定义了相应的平台在编译的时候应该加的参数。所以如果你为你自己的开发板取了别的名字了,那么就要检查一下这个文件,看一下相应的位置上的config.mk文件有没有,内容是否为你要想的。

l        包含体系,开发板,CPU特定的规则文件:

#指定预编译体系结构选项

ifdef ARCH

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 VENDOR

BOARDDIR = $(VENDOR)/$(BOARD)

else

BOARDDIR = $(BOARD)

Endif

#指定特定板子的镜像连接时的内存基地址,重要!

ifdef BOARD

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

endif

l        定义交叉编译链工具

# 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

l        定义AR选项ARFLAGS,调试选项DBGFLAGS,优化选项OPTFLAGS 预处理选项CPPFLAGS,C编译器选项CFLAGS,连接选项LDFLAGS

#制定了在编译的时候告诉编译器生成的代码的基地址是TEXT_BASE

CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS)      /

   -D__KERNEL__ -DTEXT_BASE=$(TEXT_BASE)   /

 

AFLAGS := $(AFLAGS_DEBUG) -D__ASSEMBLY__ $(CPPFLAGS)

 

#指定了起始地址TEXT_BASE

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

 

l        指定编译规则

ifndef REMOTE_BUILD

 

%.s:  %.S

   $(CPP) $(AFLAGS) -o $@ $<

%.o:  %.S

   $(CC) $(AFLAGS) -c -o $@ $<

%.o:  %.c

   $(CC) $(CFLAGS) -c -o $@ $<

 

else

 

$(obj)%.s:  %.S

   $(CPP) $(AFLAGS) -o $@ $<

$(obj)%.o:  %.S

   $(CC) $(AFLAGS) -c -o $@ $<

$(obj)%.o:  %.c

   $(CC) $(CFLAGS) -c -o $@ $<

endif

3)分析最关键的u-boot ELF文件镜像的生成****

Makefile文件中的各个依赖目标分析如下:

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

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

l        依赖目标version:生成版本信息到版本文件VERSION_FILE中。

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)

l        伪目标SUBDIRS: 执行tools ,examples ,post,post/cpu 子目录下面的make文件。

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

$(SUBDIRS):
   $(MAKE) -C $@ all

l        依赖目标$(OBJS),即cpu/start.o

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

l        依赖目标$(LIBS),这个目标太多,都是每个子目录的库文件*.a ,通过执行相应子目录下的make来完成:

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

l        依赖目标$(LDSCRIPT):

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

对于每一种开发板来说,LDSCRIPT即连接脚本文件,例如board/esd/cpci5200/u-boot.lds,定义了连接时各个目标文件是如何组织的。内容如下:

OUTPUT_ARCH(powerpc)

SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);

/* Do we need any of these for elf?

   __DYNAMIC = 0;    */

SECTIONS

{

  /* Read-only sections, merged into text segment: */

  . = + SIZEOF_HEADERS;

  .interp : { *(.interp) }

  .hash          : { *(.hash)   }

  .dynsym        : { *(.dynsym)    }

  .dynstr        : { *(.dynstr)    }

  .rel.text      : { *(.rel.text)     }

  .rela.text     : { *(.rela.text)    }

  .rel.data      : { *(.rel.data)     }

  .rela.data     : { *(.rela.data)    }

  .rel.rodata    : { *(.rel.rodata)   }

  .rela.rodata   : { *(.rela.rodata) }

  .rel.got       : { *(.rel.got)      }

  .rela.got      : { *(.rela.got)     }

  .rel.ctors     : { *(.rel.ctors) }

  .rela.ctors    : { *(.rela.ctors)   }

  .rel.dtors     : { *(.rel.dtors) }

  .rela.dtors    : { *(.rela.dtors)   }

  .rel.bss       : { *(.rel.bss)      }

  .rela.bss      : { *(.rela.bss)     }

  .rel.plt       : { *(.rel.plt)      }

  .rela.plt      : { *(.rela.plt)     }

  .init          : { *(.init) }

  .plt : { *(.plt) }

#.text的基地址由LDFLAGS中-Ttext $(TEXT_BASE)指定

  .text      :

  {

#start.o为首

cpu/mpc5xxx/start.o  (.text)

    *(.text)

    *(.fixup)

    *(.got1)

博主
shougangshi@126.com
Get busy living,or get busy dying.
blog中大多文章由网络上转载或整理修改而来!如有侵权,请速与我联系,我将在第一时间处理!! E-Mail:shougangshi@126.com
点击跳转