zoukankan      html  css  js  c++  java
  • uboot2010.03 Makefile分析 .

    转载自:http://blog.csdn.net/yyttiao/article/details/7899530
     
    对于Makefile 由于源码特别长,所以,我在这里就一边摘录一边分析
    1. # Include autoconf.mk before config.mk so that the config options are available   
    2. # to all top level build files. We need the dummy all: target to prevent the   
    3. # dependency target in autoconf.mk.dep from being the default.   
    4. all:  
    5. sinclude $(obj)include/autoconf.mk.dep  
    6. sinclude $(obj)include/autoconf.mk  
    7.   
    8. # load ARCH, BOARD, and CPU configuration   
    9. # 该文件为配置时生成的   
    10. include $(obj)include/config.mk  
    11. export  ARCH CPU BOARD VENDOR SOC  
    12.   
    13. # set default to nothing for native builds   
    14. ifeq ($(HOSTARCH),$(ARCH))  
    15. CROSS_COMPILE ?= arm-linux-  
    16. endif  
    17.   
    18. # load other configuration   
    19. include $(TOPDIR)/config.mk  
    这段代码中,上面的解释已经很到位了.我这里就不多说了,直接看一个相对比较重要的文件include $(TOPDIR)/config.mk
    不知道怎么分析好.就挑几个重点讲下.
    1:编译器的变量声明
    2:连接脚本
    3:连接选项

    1:编译器的变量声明
    1. #   
    2. # Include the make variables (CC, etc...)   
    3. #   
    4. AS       = $(CROSS_COMPILE)as  
    5. LD       = $(CROSS_COMPILE)ld  
    6. CC       = $(CROSS_COMPILE)gcc  
    7. CPP      = $(CC) -E  
    8. AR       = $(CROSS_COMPILE)ar  
    9. NM       = $(CROSS_COMPILE)nm  
    10. LDR      = $(CROSS_COMPILE)ldr  
    11. STRIP    = $(CROSS_COMPILE)strip  
    12. OBJCOPY  = $(CROSS_COMPILE)objcopy  
    13. OBJDUMP  = $(CROSS_COMPILE)objdump  
    14. RANLIB   = $(CROSS_COMPILE)RANLIB  
    这里就知道为什么交叉编译器只需要指定前缀的原因了。

    2:连接脚本
    1. ifndef LDSCRIPT  
    2.     #LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug   
    3. ifeq ($(CONFIG_NAND_U_BOOT),y)  
    4.     LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds  
    5. else  
    6.     LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds  
    7. endif  
    8. endif  
    LDSCRIPT会根据是否启用nand_boot的选项,来选择连接脚本,连接脚本可以指定代码生成的先后位置,比如把nand相关的函数指定到最前面.
    uboot就是通过该连接脚本来使start.S这段代码放到整个程序的最前面,这样才能保证arm能正常启动

    3:连接选项
    1. LDFLAGS += -Bstatic -T $(obj)u-boot.lds $(PLATFORM_LDFLAGS)  
    2. ifneq ($(TEXT_BASE),)  
    3.     LDFLAGS += -Ttext $(TEXT_BASE)  
    4. endif  
    LDFLAGS指明在连接的时候,指定连接地址,还有连接脚本的参数之类的.
    剩下的就自己分析吧....



    再回到Makefile,指定要编译的对象了
    1. #########################################################################   
    2. # U-Boot objects....order is important (i.e. start must be first)   
    3.   
    4. OBJS = cpu/$(CPU)/start.o  
    5. ifeq ($(CPU),i386)  
    6.     OBJS += cpu/$(CPU)/start16.o  
    7.     OBJS += cpu/$(CPU)/resetvec.o  
    8. endif  
    9. ifeq ($(CPU),ppc4xx)  
    10.     OBJS += cpu/$(CPU)/resetvec.o  
    11. endif  
    12. ifeq ($(CPU),mpc85xx)  
    13.     OBJS += cpu/$(CPU)/resetvec.o  
    14. endif  
    15.   
    16. OBJS := $(addprefix $(obj),$(OBJS))  
    17.   
    18. LIBS = lib_generic/libgeneric.a  
    19. LIBS += lib_generic/lzma/liblzma.a  
    20. LIBS += lib_generic/lzo/liblzo.a  
    21. LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \  
    22. "board/$(VENDOR)/common/lib$(VENDOR).a"; fi)  
    23. LIBS += cpu/$(CPU)/lib$(CPU).a  
    24. ifdef SOC  
    25.     LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a  
    26. endif  
    27. ifeq ($(CPU),ixp)  
    28.     LIBS += cpu/ixp/npe/libnpe.a  
    29. endif  
    30. LIBS += lib_$(ARCH)/lib$(ARCH).a  
    31. LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \  
    32. fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a fs/yaffs2/libyaffs2.a \  
    33. fs/ubifs/libubifs.a  
    34. LIBS += net/libnet.a  
    35. LIBS += disk/libdisk.a  
    36. LIBS += drivers/bios_emulator/libatibiosemu.a  
    37. LIBS += drivers/block/libblock.a  
    38. LIBS += drivers/dma/libdma.a  
    39. LIBS += drivers/fpga/libfpga.a  
    40. LIBS += drivers/gpio/libgpio.a  
    41. LIBS += drivers/hwmon/libhwmon.a  
    42. LIBS += drivers/i2c/libi2c.a  
    43. LIBS += drivers/input/libinput.a  
    44. LIBS += drivers/misc/libmisc.a  
    45. LIBS += drivers/mmc/libmmc.a  
    46. LIBS += drivers/mtd/libmtd.a  
    47. LIBS += drivers/mtd/nand/libnand.a  
    48. LIBS += drivers/mtd/onenand/libonenand.a  
    49. LIBS += drivers/mtd/ubi/libubi.a  
    50. LIBS += drivers/mtd/spi/libspi_flash.a  
    51. LIBS += drivers/net/libnet.a  
    52. LIBS += drivers/net/phy/libphy.a  
    53. LIBS += drivers/pci/libpci.a  
    54. LIBS += drivers/pcmcia/libpcmcia.a  
    55. LIBS += drivers/power/libpower.a  
    56. LIBS += drivers/spi/libspi.a  
    57. ifeq ($(CPU),mpc83xx)  
    58.     LIBS += drivers/qe/qe.a  
    59. endif  
    60. ifeq ($(CPU),mpc85xx)  
    61.     LIBS += drivers/qe/qe.a  
    62.     LIBS += cpu/mpc8xxx/ddr/libddr.a  
    63.     LIBS += cpu/mpc8xxx/lib8xxx.a  
    64. endif  
    65. ifeq ($(CPU),mpc86xx)  
    66.     LIBS += cpu/mpc8xxx/ddr/libddr.a  
    67.     LIBS += cpu/mpc8xxx/lib8xxx.a  
    68. endif  
    69. LIBS += drivers/rtc/librtc.a  
    70. LIBS += drivers/serial/libserial.a  
    71. LIBS += drivers/twserial/libtws.a  
    72. LIBS += drivers/usb/gadget/libusb_gadget.a  
    73. LIBS += drivers/usb/host/libusb_host.a  
    74. LIBS += drivers/usb/musb/libusb_musb.a  
    75. LIBS += drivers/usb/phy/libusb_phy.a  
    76. LIBS += drivers/video/libvideo.a  
    77. LIBS += drivers/watchdog/libwatchdog.a  
    78. LIBS += common/libcommon.a  
    79. LIBS += libfdt/libfdt.a  
    80. LIBS += api/libapi.a  
    81. LIBS += post/libpost.a  
    82.   
    83. LIBS := $(addprefix $(obj),$(LIBS))  
    84. .PHONY : $(LIBS) $(TIMESTAMP_FILE) $(VERSION_FILE)  
    85.   
    86. LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).a  
    87. LIBBOARD := $(addprefix $(obj),$(LIBBOARD))  
    88.   
    89. # Add GCC lib   
    90. ifdef USE_PRIVATE_LIBGCC  
    91. ifeq ("$(USE_PRIVATE_LIBGCC)""yes")  
    92.     PLATFORM_LIBGCC = -L $(OBJTREE)/lib_$(ARCH) -lgcc  
    93. else  
    94.     PLATFORM_LIBGCC = -L $(USE_PRIVATE_LIBGCC) -lgcc  
    95. endif  
    96. else  
    97.     PLATFORM_LIBGCC = -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc  
    98. endif  
    99. PLATFORM_LIBS += $(PLATFORM_LIBGCC)  
    100. export PLATFORM_LIBS  
    101.   
    102. # Special flags for CPP when processing the linker script.   
    103. # Pass the version down so we can handle backwards compatibility   
    104. # on the fly.   
    105. LDPPFLAGS += \  
    106. -include $(TOPDIR)/include/u-boot/u-boot.lds.h \  
    107. $(shell $(LD) --version | \  
    108. sed -ne 's/GNU ld version \([0-9][0-9]*\)\.\([0-9][0-9]*\).*/-DLD_MAJOR=\1 -DLD_MINOR=\2/p')  
    109.   
    110. ifeq ($(CONFIG_NAND_U_BOOT),y)  
    111.     NAND_SPL = nand_spl  
    112.     U_BOOT_NAND = $(obj)u-boot-nand.bin  
    113. endif  
    114.   
    115. ifeq ($(CONFIG_ONENAND_U_BOOT),y)  
    116.     ONENAND_IPL = onenand_ipl  
    117.     U_BOOT_ONENAND = $(obj)u-boot-onenand.bin  
    118.     ONENAND_BIN ?= $(obj)onenand_ipl/onenand-ipl-2k.bin  
    119. endif  
    120.   
    121. __OBJS := $(subst $(obj),,$(OBJS))  
    122. __LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))  
    123.   
    124. #########################################################################   
    125. #########################################################################  
    由上面的可以看出
    OBJS 对应的是 .o文件
    LIBS对应的是 .a文件
    LIBBOARD 对应的是目录
    等等.主要看下这3个是怎么被处理的
    1. $(OBJS):    depend  
    2.     $(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))  
    3.   
    4. $(LIBS):    depend $(SUBDIRS)  
    5.     $(MAKE) -C $(dir $(subst $(obj),,$@))  
    6.   
    7. $(LIBBOARD):    depend $(LIBS)  
    8.     $(MAKE) -C $(dir $(subst $(obj),,$@))  
    由这里可以看出,会逐个的make出来

    最后就是连接的过程了.连接会调用
    1. GEN_UBOOT = \  
    2.     UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \  
    3.     sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\  
    4.     cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \  
    5.     --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \  
    6.     -Map u-boot.map -o u-boot  
    7. $(obj)u-boot:   depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds  
    最终会连接成功.后面只要通过
    1. $(obj)u-boot.bin:   $(obj)u-boot  
    2. $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@  
    将二进制内容拷贝出来,那么uboot.bin就生成了

    来看一下连接脚本吧
    1. OUTPUT_FORMAT("elf32-littlearm""elf32-littlearm""elf32-littlearm")  
    2. OUTPUT_ARCH(arm)  
    3. ENTRY(_start)  
    4. SECTIONS  
    5. {  
    6.     . = 0x00000000;  
    7.     . = ALIGN(4);  
    8.     .text :  
    9.     {  
    10.         cpu/arm1176/start.o (.text)  
    11.         cpu/arm1176/s3c64xx/cpu_init.o (.text)  
    12.        *(.text)  
    13.     }  
    14.     . = ALIGN(4);  
    15.     .rodata :   
    16.     {   
    17.         *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))   
    18.     }  
    19.     . = ALIGN(4);  
    20.     .data : {  
    21.         *(.data)   
    22.     }  
    23.     . = ALIGN(4);  
    24.     .got :   
    25.     {  
    26.         *(.got)   
    27.     }  
    28.     __u_boot_cmd_start = .;  
    29.     .u_boot_cmd :   
    30.     {   
    31.         *(.u_boot_cmd)   
    32.     }  
    33.     __u_boot_cmd_end = .;  
    34.     . = ALIGN(4);  
    35.     .mmudata :   
    36.     {   
    37.         *(.mmudata)   
    38.     }  
    39.     . = ALIGN(4);  
    40.     __bss_start = .;  
    41.     .bss :   
    42.     {   
    43.         *(.bss) . = ALIGN(4);   
    44.     }  
    45.     _end = .;  
    46. }  
    从这个链接脚本可以看出,uboot将整个程序进行了如下的布置
    .text :
    .rodata :
    .data :
    .got :
    .u_boot_cmd :
    .mmudata :
    .bss :
    代码段被首先链接,在代码段内第一个就是start.s 因为这就是uboot启动的第一条代码的地方,看一下map文件
    Memory Configuration

    Name                  Origin                        Length                Attributes
    *default*             0x00000000             0xffffffff

    Linker script and memory map

    0x00000000  . = 0x0
    0x00000000 . = ALIGN (0x4)

    .text                 0x57e00000                  0x27b8c
    cpu/arm1176/start.o(.text)
    .text                 0x57e00000                  0x440              cpu/arm1176/start.o
                            0x57e00040                                           _end_vect
                            0x57e0004c                                           _bss_start
                            0x57e00050                                          _bss_end
                            0x57e00048                                          _armboot_start
                            0x57e00114                                          copy_from_nand
                            0x57e00000                                          _start

    从map文件中,可以看到0x57e00000=_start 被放到了一条的位置(0x57e00000就是链接脚本指定的连接地址)
    接着打开cpu/arm1176/start.S
    1. .globl _start  
    2. _start: b   reset  
    3. #ifndef CONFIG_NAND_SPL   
    4. ldr pc, _undefined_instruction  
    5. ldr pc, _software_interrupt  
    6. ldr pc, _prefetch_abort  
    7. ldr pc, _data_abort  
    8. ldr pc, _not_used  
    9. ldr pc, _irq  
    10. ldr pc, _fiq  
    第一条语句 b reset就被放到了_start的位置,这样uboot启动之后,就会开始执行这条语句,uboot的移植也会从这开始分析了

    完。

    Thanks a lot!
  • 相关阅读:
    ElasticSearch搜索引擎安装配置拼音插件pinyin
    ElasticSearch搜索引擎安装配置中文分词器IK插件
    Linux系统中ElasticSearch搜索引擎安装配置Head插件
    阿里云服务器Linux系统安装配置ElasticSearch搜索引擎
    盒子模型
    div与span的区别
    .与localhost与 .sqlexpress的区别
    C#-多态
    C#-里氏转换
    C#-继承
  • 原文地址:https://www.cnblogs.com/start530/p/3834392.html
Copyright © 2011-2022 走看看