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部分链接成目标,如果输入目标无效,则删除相关的目标,并且建立一个新的归档文件,与目标同名。
该文件中涉及大量编译、链接选项,篇幅较大,因此不深究它们,只是分析关键步骤。
ifeq ($(CURDIR),$(SRCTREE))
dir :=
else
dir := $(subst $(SRCTREE)/,,$(CURDIR))
endif ifneq ($(OBJTREE),$(SRCTREE))
# Create object files for SPL in a separate directory
ifeq ($(CONFIG_SPL_BUILD),y)
obj := $(if $(dir),$(SPLTREE)/$(dir)/,$(SPLTREE)/)
else
obj := $(if $(dir),$(OBJTREE)/$(dir)/,$(OBJTREE)/)
endif
src := $(if $(dir),$(SRCTREE)/$(dir)/,$(SRCTREE)/) $(shell mkdir -p $(obj))
else
# Create object files for SPL in a separate directory
ifeq ($(CONFIG_SPL_BUILD),y)
obj := $(if $(dir),$(SPLTREE)/$(dir)/,$(SPLTREE)/) $(shell mkdir -p $(obj))
else
obj :=
endif
src :=
endif
CURDIR是Makefile内置变量,表示该Makefile的绝对路径,相当于执行pwd得到的输出,这里通过subst函数将CURDIR中的SRCTREE部分去掉,这样dir就表示当前路径相对于源码根目录的相对路径。
接下来是obj和src的处理,这里SRCTREE和OBJTREE相同,而且CONFIG_SPL_BUILD没定义,因此上述两个变量是空字符串。
CC_OPTIONS_CACHE_FILE := $(OBJTREE)/include/generated/cc_options.mk
CC_TEST_OFILE := $(OBJTREE)/include/generated/cc_test_file.o -include $(CC_OPTIONS_CACHE_FILE) cc-option-sys = $(shell mkdir -p $(dir $(CC_TEST_OFILE)); \
if $(CC) $(CFLAGS) $(1) -S -xc /dev/null -o $(CC_TEST_OFILE) \
> /dev/null 2>&1; then \
echo 'CC_OPTIONS += $(strip $1)' >> $(CC_OPTIONS_CACHE_FILE); \
echo "$(1)"; fi) ifeq ($(CONFIG_CC_OPT_CACHE_DISABLE),y)
cc-option = $(strip $(if $(call cc-option-sys,$1),$1,$2))
else
cc-option = $(strip $(if $(findstring $1,$(CC_OPTIONS)),$1,\
$(if $(call cc-option-sys,$1),$1,$2)))
endif # cc-version
# Usage gcc-ver := $(call cc-version)
cc-version = $(shell $(SHELL) $(SRCTREE)/tools/gcc-version.sh $(CC))
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脚本得到的,没用到,暂不分析。
AS = $(CROSS_COMPILE)as # Always use GNU ld
LD = $(shell if $(CROSS_COMPILE)ld.bfd -v > /dev/null 2>&1; \
then echo "$(CROSS_COMPILE)ld.bfd"; else echo "$(CROSS_COMPILE)ld"; fi;) CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
LDR = $(CROSS_COMPILE)ldr
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
RANLIB = $(CROSS_COMPILE)RANLIB
DTC = dtc
上面就很简单了,指明使用的各个工具,这是每个子Makefile都要包含config.mk的重要原因之一。
# Load generated board configuration
sinclude $(OBJTREE)/include/autoconf.mk
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的另一个重要原因。
CPUDIR=arch/$(ARCH)/cpu/$(CPU)
ifneq ($(SRCTREE)/$(CPUDIR),$(wildcard $(SRCTREE)/$(CPUDIR)))
CPUDIR=arch/$(ARCH)/cpu
endif sinclude $(TOPDIR)/arch/$(ARCH)/config.mk # include architecture dependend rules
sinclude $(TOPDIR)/$(CPUDIR)/config.mk # include CPU specific rules ifdef SOC
sinclude $(TOPDIR)/$(CPUDIR)/$(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
概括一下,上面的语句就是读入了几个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。
ARFLAGS = $(error update your Makefile to use cmd_link_o_target and not AR)
RELFLAGS= $(PLATFORM_RELFLAGS)
DBGFLAGS= -g # -DDEBUG
OPTFLAGS= -Os #-fomit-frame-pointer OBJCFLAGS += --gap-fill=0xff gccincdir := $(shell $(CC) -print-file-name=include) CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS) \
-D__KERNEL__
注意ARFLAGS被设置成了makefile的error函数输出错误信息,这是提醒用户,在对目标文件归档的时候不要使用$(AR)了,要使用$(LD)。
接下来就是编译链接选项的设置,有太多选项了,什么SPL启动、VENDOR address等等,不细细分析了。
export HOSTCC HOSTCFLAGS HOSTLDFLAGS PEDCFLAGS HOSTSTRIP CROSS_COMPILE \
AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP MAKE
export CONFIG_SYS_TEXT_BASE PLATFORM_CPPFLAGS PLATFORM_RELFLAGS CPPFLAGS CFLAGS AFLAGS
export到全局的变量如上所示。
终于到了最后!
# The _DEP version uses the $< file target (for dependency generation)
# See rules.mk
EXTRA_CPPFLAGS_DEP = $(CPPFLAGS_$(BCURDIR)/$(addsuffix .o,$(basename $<))) \
$(CPPFLAGS_$(BCURDIR))
$(obj)%.s: %.S
$(CPP) $(ALL_AFLAGS) -o $@ $<
$(obj)%.o: %.S
$(CC) $(ALL_AFLAGS) -o $@ $< -c
$(obj)%.o: %.c
$(CC) $(ALL_CFLAGS) -o $@ $< -c
$(obj)%.i: %.c
$(CPP) $(ALL_CFLAGS) -o $@ $< -c
$(obj)%.s: %.c
$(CC) $(ALL_CFLAGS) -o $@ $< -c -S ######################################################################### # If the list of objects to link is empty, just create an empty built-in.o
cmd_link_o_target = $(if $(strip $1),\
$(LD) $(LDFLAGS) -r -o $@ $1,\
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.
U-Boot Makefile分析(2) config.mk分析的更多相关文章
- uboot总结:uboot配置和启动过程3(config.mk分析)
说明:文件位置:在uboot的目录下,文件名为:config.mk.是一个makefile文件,以后会被主Makefile调用. 它的主要作用的是: (1)具体的设置交叉编译工具链接(主Makefil ...
- 2014-10 u-boot 顶层config.mk分析
/** ****************************************************************************** * @author Maox ...
- uboot顶层config.mk分析
uboot顶层目录中的config.mk定义了确定了当前执行makefile所对应的源文件目录.目标文件目录,编译的程序编译.连接的选项,以及目标文件生成的规则等等.它被包含在顶层的makefile以 ...
- u-boot顶层目录config.mk分析
1. 设置obj与src ifneq ($(OBJTREE),$(SRCTREE)) ifeq ($(CURDIR),$(SRCTREE)) dir := else dir := $(subst $( ...
- U-Boot Makefile分析(3) rules.mk分析
浏览各个子Makefile可以发现,他们都会在文件的后面包含rules.mk,这个文件的作用就是更新源文件的依赖,并生成各种.depend文件. _depend: $(obj).depend # Sp ...
- Spring Boot 启动(一) SpringApplication 分析
Spring Boot 启动(一) SpringApplication 分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html ...
- Spring Boot 揭秘与实战 源码分析 - 工作原理剖析
文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoCo ...
- Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机
文章目录 1. 开箱即用,内藏玄机 2. 总结 3. 源代码 Spring Boot提供了很多”开箱即用“的依赖模块,那么,Spring Boot 如何巧妙的做到开箱即用,自动配置的呢? 开箱即用,内 ...
- Spring Boot自动装配原理源码分析
1.环境准备 使用IDEA Spring Initializr快速创建一个Spring Boot项目 添加一个Controller类 @RestController public class Hell ...
随机推荐
- .Net23种设计模式
C#常见的设计模式 一.概要: 模式分为三种,设计模式.体系结构模式与惯用法.其中惯用法是一种语言紧密相关的模式,例如,定界加锁模式其实是一种惯用法. 在C#项目开发过程中,很多情况下您已经使用了某些 ...
- 微信小程序生成携带参数的小程序码
https://blog.csdn.net/qq_28988969/article/details/77969365
- 编写一个 rpc
手动编写一个 RPC 调用 package com.alibaba.study.rpc.framework; import java.io.ObjectInputStream; import java ...
- centos查看自启动服务
1,查看自启动服务? 2,查看某服务的开机启动状态? 3,启动(关闭,重启,查看)某个服务? 4,设置开机启动或者关闭某个服务? 1,查看自启动服务? systemctl list-unit-file ...
- mysql表理解
4.1 索引组织表 1.在innodb存储引擎中,每张表都有个主键,如果在创建表时没有显式地定义主键,则innodb存储引擎会按如下方式选择或创建主键: ①:首先判断表中是否有非空的唯一索引,如果有, ...
- 【搬运】 Page Object 官方文档 (新增了Widget特性)
Appium Java client has facilities which components to [Page Object](https://github.com/SeleniumHQ/se ...
- Analysis Services(SSAS) 性能优化
1.聚合选项中添加聚合,以空间换时间提升性能. 如下图: 性能提升百分比越高,聚合数越高,生成的Cube越大,这就是以空间换时间. 2.修改SSAS服务器上的线程池配置选项.提升并发数. 通过X:\P ...
- How to find SPRO path by t-code name
e.g:OB58 F1->Technical Information Find Table Name->V_T011 3.SM30 V_T011 Customizing Continue ...
- js 加减乘除以及四舍五入 新写法
1 四舍五入 eg: (1.23).round() = 1.2 (1.2456).round(3) = 1.246 Number.prototype.round = function (count) ...
- vue学习笔记(WebStorm安装)
慕课网:https://www.imooc.com/video/18553 一.前往官网下载:https://www.jetbrains.com/webstorm/download/#section= ...