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 =
- 代码首先判断 目标存放目录是否不等于源码目录,若不等于,则执行分支语句,等于 则不执行。
- 执行分支语句,判断当前目录是否等于源码目录,若等于则将 dir 置空,否则,把$(CURDIR)中的$(SRCTREE)/替换称空,然后赋给dir
- 执行完之后,如果 dir 不为空,则把$(OBJTREE)/$(dir)/赋给obj,否则把直接把$(OBJTREE)/赋给obj
- 如果src不为空,则把$(SRCTREE)/$(dir)/赋给src,否则把$(SRCTREE)/赋给src
- 通过一个shell 函数创建 obj 路径,obj 的路径为 $(OBJTREE)/$(dir)/ 或 $(OBJTREE)/
- 若是目标目录和源码目录相同,则 obj 和 src 都为空
- 最后清除三个 编译选项 标志
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" "$2" … "$n" 的形式输出所有参数。
- 但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$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,$< 为所有依赖