zoukankan      html  css  js  c++  java
  • U-Boot Makefile分析(2) config.mk分析

      浏览一下U-Boot各个子目录下的Makefile可以看到,几乎他们都会包含$(TOPDIR)/config.mk,那么这个文件进行了什么操作呢?简单概括:读入include/config.mk、include/autoconf.mk,指定ARCH CPU SoC Board等重要信息,并且加入各个层次上的编译选项;初始化编译处理选项、链接选项;最后有一个很重要的变量定义:

      cmd_link_o_target = $(if $(strip $1),

                $(LD) $(LDFLAGS) -r -o $@ $1,

                rm -f $@; $(AR) rcs $@)

      其实就是将输入的参数$1部分链接成目标,如果输入目标无效,则删除相关的目标,并且建立一个新的归档文件,与目标同名。

      该文件中涉及大量编译、链接选项,篇幅较大,因此不深究它们,只是分析关键步骤。

     1 ifeq ($(CURDIR),$(SRCTREE))
     2 dir :=
     3 else
     4 dir := $(subst $(SRCTREE)/,,$(CURDIR))
     5 endif
     6 
     7 ifneq ($(OBJTREE),$(SRCTREE))
     8 # Create object files for SPL in a separate directory
     9 ifeq ($(CONFIG_SPL_BUILD),y)
    10 obj := $(if $(dir),$(SPLTREE)/$(dir)/,$(SPLTREE)/)
    11 else
    12 obj := $(if $(dir),$(OBJTREE)/$(dir)/,$(OBJTREE)/)
    13 endif
    14 src := $(if $(dir),$(SRCTREE)/$(dir)/,$(SRCTREE)/)
    15 
    16 $(shell mkdir -p $(obj))
    17 else
    18 # Create object files for SPL in a separate directory
    19 ifeq ($(CONFIG_SPL_BUILD),y)
    20 obj := $(if $(dir),$(SPLTREE)/$(dir)/,$(SPLTREE)/)
    21 
    22 $(shell mkdir -p $(obj))
    23 else
    24 obj :=
    25 endif
    26 src :=
    27 endif

      CURDIR是Makefile内置变量,表示该Makefile的绝对路径,相当于执行pwd得到的输出,这里通过subst函数将CURDIR中的SRCTREE部分去掉,这样dir就表示当前路径相对于源码根目录的相对路径。

      接下来是obj和src的处理,这里SRCTREE和OBJTREE相同,而且CONFIG_SPL_BUILD没定义,因此上述两个变量是空字符串。

     1 CC_OPTIONS_CACHE_FILE := $(OBJTREE)/include/generated/cc_options.mk
     2 CC_TEST_OFILE := $(OBJTREE)/include/generated/cc_test_file.o
     3 
     4 -include $(CC_OPTIONS_CACHE_FILE)
     5 
     6 cc-option-sys = $(shell mkdir -p $(dir $(CC_TEST_OFILE)); 
     7         if $(CC) $(CFLAGS) $(1) -S -xc /dev/null -o $(CC_TEST_OFILE) 
     8         > /dev/null 2>&1; then 
     9         echo 'CC_OPTIONS += $(strip $1)' >> $(CC_OPTIONS_CACHE_FILE); 
    10         echo "$(1)"; fi)
    11 
    12 ifeq ($(CONFIG_CC_OPT_CACHE_DISABLE),y)
    13 cc-option = $(strip $(if $(call cc-option-sys,$1),$1,$2))
    14 else
    15 cc-option = $(strip $(if $(findstring $1,$(CC_OPTIONS)),$1,
    16         $(if $(call cc-option-sys,$1),$1,$2)))
    17 endif
    18 
    19 # cc-version
    20 # Usage gcc-ver := $(call cc-version)
    21 cc-version = $(shell $(SHELL) $(SRCTREE)/tools/gcc-version.sh $(CC))
    22 binutils-version = $(shell $(SHELL) $(SRCTREE)/tools/binutils-version.sh $(AS))

      这里相当于定义了两个小函数cc-option-sys,cc-option,其中后者调用前者,因此虽然前者提供了接口,但是并不使用,我不知道CONFIG_CC_OPT_CACHE_DISABLE是不是y,但是这里的核心操作就是,将要添加的CC编译选项以参数的形式传进去,然后尝试加入该选项来编译/dev/null,丢弃所有stdout/stderr输出。这里比较有意思的是,编译的源文件是/dev/null,估计作者的意思是,只要加入的这个选项存在,是编译器支持的就可以,而不是要求达到何种效果。如果选项有效,则向include/generated/cc_options.mk中写入该选项。

      接着又定义了两个函数cc-version、binutils-version,两者都是通过执行shell脚本得到的,没用到,暂不分析。

     1 AS  = $(CROSS_COMPILE)as
     2 
     3 # Always use GNU ld
     4 LD  = $(shell if $(CROSS_COMPILE)ld.bfd -v > /dev/null 2>&1; 
     5         then echo "$(CROSS_COMPILE)ld.bfd"; else echo "$(CROSS_COMPILE)ld"; fi;)
     6 
     7 CC  = $(CROSS_COMPILE)gcc
     8 CPP = $(CC) -E
     9 AR  = $(CROSS_COMPILE)ar
    10 NM  = $(CROSS_COMPILE)nm
    11 LDR = $(CROSS_COMPILE)ldr
    12 STRIP   = $(CROSS_COMPILE)strip
    13 OBJCOPY = $(CROSS_COMPILE)objcopy
    14 OBJDUMP = $(CROSS_COMPILE)objdump
    15 RANLIB  = $(CROSS_COMPILE)RANLIB
    16 DTC = dtc

      上面就很简单了,指明使用的各个工具,这是每个子Makefile都要包含config.mk的重要原因之一。

    1 # Load generated board configuration
    2 sinclude $(OBJTREE)/include/autoconf.mk
    3 sinclude $(OBJTREE)/include/config.mk

      这里虽然就两行,但是很重要,经过上一篇文章的分析,我们知道mkconfig s5p_goni_config的重要输出文件有两个:include/config.mk include/config.h,这里使用第一个,它指明了ARCH CPU SOC VENDOR BOARD,autoconf.mk目前还不知道是如何产生的,但是浏览以下可以知道里面的信息很多很重要,很多功能配置,这是子Makefile要包含config.mk的另一个重要原因。

     1 CPUDIR=arch/$(ARCH)/cpu/$(CPU)
     2 ifneq ($(SRCTREE)/$(CPUDIR),$(wildcard $(SRCTREE)/$(CPUDIR)))
     3 CPUDIR=arch/$(ARCH)/cpu
     4 endif
     5 
     6 sinclude $(TOPDIR)/arch/$(ARCH)/config.mk   # include architecture dependend rules
     7 sinclude $(TOPDIR)/$(CPUDIR)/config.mk      # include  CPU  specific rules
     8 
     9 ifdef   SOC
    10 sinclude $(TOPDIR)/$(CPUDIR)/$(SOC)/config.mk   # include  SoC  specific rules
    11 endif
    12 ifdef   VENDOR
    13 BOARDDIR = $(VENDOR)/$(BOARD)
    14 else
    15 BOARDDIR = $(BOARD)
    16 endif
    17 ifdef   BOARD
    18 sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk  # include board specific rules
    19 endif

      概括一下,上面的语句就是读入了几个config.mk:

    sinclude arch/arm/config.mk  这是加入架构层次上的配置,比如设定CROSS_COMPILE ?= arm-linux-,比如通过上面的cc-option函数加入arm架构的编译选项:

                  $(call cc-option -marm)

    sinclude arch/arm/cpu/armv7/config.mk  这是加入cpu层次上的配置,加入指令集上的配置选项,如$(call cc-option, -march=armv7-a, -march=armv5)

    sinclude arch/arm/cpu/armv7/s5pc1xx/config.mk  这是加入soc层次上的配置,检查发现目录下没有此文件,但并不报错,sinclude和-include用法一样,当被包含的文件不

                       存在的时候,不报错,继续执行。

    sinclude board/samsung/goni/config.mk   这是在board层次上加入配置,因为板卡资源决定了我们的内存容量和起始地址,所以这里指定了u-boot镜像的链接地址CONFIG_SYS_TEXT_BASE = 0x34800000,这个信息是board-specific。

     1 ARFLAGS = $(error update your Makefile to use cmd_link_o_target and not AR)
     2 RELFLAGS= $(PLATFORM_RELFLAGS)
     3 DBGFLAGS= -g # -DDEBUG
     4 OPTFLAGS= -Os #-fomit-frame-pointer
     5 
     6 OBJCFLAGS += --gap-fill=0xff
     7 
     8 gccincdir := $(shell $(CC) -print-file-name=include)
     9 
    10 CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS)        
    11     -D__KERNEL__

      注意ARFLAGS被设置成了makefile的error函数输出错误信息,这是提醒用户,在对目标文件归档的时候不要使用$(AR)了,要使用$(LD)。

      接下来就是编译链接选项的设置,有太多选项了,什么SPL启动、VENDOR address等等,不细细分析了。

    1 export  HOSTCC HOSTCFLAGS HOSTLDFLAGS PEDCFLAGS HOSTSTRIP CROSS_COMPILE 
    2     AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP MAKE
    3 export  CONFIG_SYS_TEXT_BASE PLATFORM_CPPFLAGS PLATFORM_RELFLAGS CPPFLAGS CFLAGS AFLAGS

      export到全局的变量如上所示。

      终于到了最后!

     1 # The _DEP version uses the $< file target (for dependency generation)
     2 # See rules.mk
     3 EXTRA_CPPFLAGS_DEP = $(CPPFLAGS_$(BCURDIR)/$(addsuffix .o,$(basename $<))) 
     4         $(CPPFLAGS_$(BCURDIR))
     5 $(obj)%.s:  %.S
     6     $(CPP) $(ALL_AFLAGS) -o $@ $<
     7 $(obj)%.o:  %.S
     8     $(CC)  $(ALL_AFLAGS) -o $@ $< -c
     9 $(obj)%.o:  %.c
    10     $(CC)  $(ALL_CFLAGS) -o $@ $< -c
    11 $(obj)%.i:  %.c
    12     $(CPP) $(ALL_CFLAGS) -o $@ $< -c
    13 $(obj)%.s:  %.c
    14     $(CC)  $(ALL_CFLAGS) -o $@ $< -c -S
    15 
    16 #########################################################################
    17 
    18 # If the list of objects to link is empty, just create an empty built-in.o
    19 cmd_link_o_target = $(if $(strip $1),
    20               $(LD) $(LDFLAGS) -r -o $@ $1,
    21               rm -f $@; $(AR) rcs $@ )

      这里很重要,是一些静态模式描述,分析这里的时候,着实让我纠结了一阵子。以前自己写Makefile的时候也会用静态模式,但理解是很不准确的,写依赖的时候理所当然地写$<,不知原因。举例,test.o处理依赖test.c以外,还依赖它所包含的头文件,所以该文件的完整约束描述为:

    test.o: test.c  

    header1path/header1.h

    header2path/header2.h

    ...

      上述依赖格式也正是CC -M的输出格式,而在编译生成test.o的时候,只需要test.c就够了,这就是$<的含义:依赖集中的第一个依赖。

      最后那个函数在文章开始的时候已经分析过了。

      ok.

  • 相关阅读:
    LVS基于DR模式负载均衡的配置
    Linux源码安装mysql 5.6.12 (cmake编译)
    HOSt ip is not allowed to connect to this MySql server
    zoj 3229 Shoot the Bullet(无源汇上下界最大流)
    hdu 3987 Harry Potter and the Forbidden Forest 求割边最少的最小割
    poj 2391 Ombrophobic Bovines(最大流+floyd+二分)
    URAL 1430 Crime and Punishment
    hdu 2048 神、上帝以及老天爷(错排)
    hdu 3367 Pseudoforest(最大生成树)
    FOJ 1683 纪念SlingShot(矩阵快速幂)
  • 原文地址:https://www.cnblogs.com/tech-lqh/p/8406973.html
Copyright © 2011-2022 走看看