二、主目录 Makefile 分析(2)

2.7 编译选项---config.mk

  代码 163 164 行

1 # load other configuration
2 include $(TOPDIR)/config.mk

  此段就是包含顶层目录下的 config.mk,在顶层的  config.mk 中包含了编译选项。

2.7.1 topdir/config.mk 分析

  代码 26 到 45行:

 1 ifneq ($(OBJTREE),$(SRCTREE))
 2 ifeq ($(CURDIR),$(SRCTREE))
 3 dir :=
 4 else
 5 dir := $(subst $(SRCTREE)/,,$(CURDIR))
 6 endif
 7 
 8 obj := $(if $(dir),$(OBJTREE)/$(dir)/,$(OBJTREE)/)
 9 src := $(if $(dir),$(SRCTREE)/$(dir)/,$(SRCTREE)/)
10 
11 $(shell mkdir -p $(obj))
12 else
13 obj :=
14 src :=
15 endif
16 
17 # clean the slate ...
18 PLATFORM_RELFLAGS =
19 PLATFORM_CPPFLAGS =
20 PLATFORM_LDFLAGS =
  1. 代码首先判断 目标存放目录是否不等于源码目录,若不等于,则执行分支语句,等于 则不执行。
  2. 执行分支语句,判断当前目录是否等于源码目录,若等于则将 dir 置空,否则,把$(CURDIR)中的$(SRCTREE)/替换称空,然后赋给dir
  3. 执行完之后,如果 dir 不为空,则把$(OBJTREE)/$(dir)/赋给obj,否则把直接把$(OBJTREE)/赋给obj
  4. 如果src不为空,则把$(SRCTREE)/$(dir)/赋给src,否则把$(SRCTREE)/赋给src
  5. 通过一个shell 函数创建 obj 路径,obj 的路径为 $(OBJTREE)/$(dir)/ 或 $(OBJTREE)/
  6. 若是目标目录和源码目录相同,则 obj 和 src 都为空
  7. 最后清除三个 编译选项 标志

  PLATFORM_RELFLAGS、PLATFORM_CPPFLAGS 和 PLATFORM_LDFLAGS 这三个变量被置空,之后会被赋值上编译参数,接下来的 54 到 92 行都是给三个编译选项赋值参数:

  63 到 70行,是架构为ARM的赋值,但里面的 CROSS_COMPILE 不能匹配,不会执行

1 ifeq ($(ARCH),arm)
2 ifeq ($(CROSS_COMPILE),powerpc-netbsd-)
3 PLATFORM_CPPFLAGS+= -D__ARM__
4 endif
5 ifeq ($(CROSS_COMPILE),powerpc-openbsd-)
6 PLATFORM_CPPFLAGS+= -D__ARM__
7 endif
8 endif

  76 到 92 行,会根据前面#include/config.mk 导出的环境变量参数来包含相应的 config.mk 文件

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

  根据前面的参数进行展开即可

  96 到 106 行,是给几个参数赋值,HOSTCC 赋值为 gcc,HOSTCFLAGS 和 HOSTSTRIP

  CONFIG_SHELL,涉及到  shell 语法和命令

  • if 语句的 -x 参数为测试文件对当前用户是都可执行
  • 再看一下 shell  的特殊变量:
    • $0      当前脚本的文件名
    • $n      传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
    • $#      传递给脚本或函数的参数个数。
    • $*      传递给脚本或函数的所有参数。
    • $@      传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。 
    • $?      上个命令的退出状态,或函数的返回值。一般情况下,大部分命令执行成功会返回 0,失败返回 1。 
    • $$      当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。
    • $* 和 $@ 的区别 : 
      1. $* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。  
      2. 但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。
 1 CONFIG_SHELL    := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
 2             else if [ -x /bin/bash ]; then echo /bin/bash; \
 3             else echo sh; fi ; fi)
 4 
 5 ifeq ($(HOSTOS)-$(HOSTARCH),darwin-ppc)
 6 HOSTCC        = cc
 7 else
 8 HOSTCC        = gcc
 9 endif
10 HOSTCFLAGS    = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
11 HOSTSTRIP    = strip

  113 到 114行, 这是一个选项检查器,以确保我们只使用所支持的编译器,际上使用了一个shell函数,本函数使用了if-then语句,检测条件分别为"-S, -o, -xc",也用到了重定向

1 cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
2         > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)

  119 到 166 行,定义了交叉工具编译连,指定了交叉工具编译连的参数

 1 AS    = $(CROSS_COMPILE)as
 2 LD    = $(CROSS_COMPILE)ld
 3 CC    = $(CROSS_COMPILE)gcc
 4 CPP    = $(CC) -E
 5 AR    = $(CROSS_COMPILE)ar
 6 NM    = $(CROSS_COMPILE)nm
 7 STRIP    = $(CROSS_COMPILE)strip
 8 OBJCOPY = $(CROSS_COMPILE)objcopy
 9 OBJDUMP = $(CROSS_COMPILE)objdump
10 RANLIB    = $(CROSS_COMPILE)RANLIB
11 
12 ifneq (,$(findstring s,$(MAKEFLAGS)))
13 ARFLAGS = cr
14 else
15 ARFLAGS = crv
16 endif
17 RELFLAGS= $(PLATFORM_RELFLAGS)
18 DBGFLAGS= -g # -DDEBUG
19 OPTFLAGS= -Os #-fomit-frame-pointer
20 ifndef LDSCRIPT
21 #LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug
22 ifeq ($(CONFIG_NAND_U_BOOT),y)
23 LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds
24 else
25 LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
26 endif
27 endif
28 OBJCFLAGS += --gap-fill=0xff
29 
30 gccincdir := $(shell $(CC) -print-file-name=include)
31 
32 CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS)        \
33     -D__KERNEL__ -DTEXT_BASE=$(TEXT_BASE)        \
34 
35 ifneq ($(OBJTREE),$(SRCTREE))
36 CPPFLAGS += -I$(OBJTREE)/include2 -I$(OBJTREE)/include
37 endif
38 
39 CPPFLAGS += -I$(TOPDIR)/include
40 CPPFLAGS += -fno-builtin -ffreestanding -nostdinc     \
41     -isystem $(gccincdir) -pipe $(PLATFORM_CPPFLAGS)
42 
43 ifdef BUILD_TAG
44 CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes \
45     -DBUILD_TAG='"$(BUILD_TAG)"'
46 else
47 CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes
48 endif
  • #如果函数$(findstring s,$(MAKEFLAGS))不为空,也就是说能从$(MAKEFLAGS)中找到字符s,则定义AR选项为cr,否则为 crv
  • RELFLAGS、DBGFLAGS 和 OPTFLAGS 赋值
  • 如果没有定义链接脚本(LDSCRIPT),则指定链接脚本
  • 下面的都是编译的一些标志了,不具体分析了

  227 到 244 行,则是指定编译依赖

 1 ifndef REMOTE_BUILD
 2 
 3 %.s:    %.S
 4     $(CPP) $(AFLAGS) -o $@ $<
 5 %.o:    %.S
 6     $(CC) $(AFLAGS) -c -o $@ $<
 7 %.o:    %.c
 8     $(CC) $(CFLAGS) -c -o $@ $<
 9 
10 else
11 
12 $(obj)%.s:    %.S
13     $(CPP) $(AFLAGS) -o $@ $<
14 $(obj)%.o:    %.S
15     $(CC) $(AFLAGS) -c -o $@ $<
16 $(obj)%.o:    %.c
17     $(CC) $(CFLAGS) -c -o $@ $<
18 endif

  例如

  %.s: %.S

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

  %.s 依赖于 %.S

    -o  后面的为 $@ 为 %.s,$< 为所有依赖

  

  

posted @ 2018-04-21 09:44  游戏进行中  阅读(401)  评论(0编辑  收藏  举报