XR871SDK编译框架分析


XR871SDK编译框架分析:

—> 从/src/project/echocloud_demo/gcc 输入make编译, 解析当前文件夹下的Makefile文件:


#
# Rules for building application
#

# ----------------------------------------------------------------------------
# project local config ---> 1. 包含配置文件localconfig.mk 后面分析
# ----------------------------------------------------------------------------
include localconfig.mk

# ----------------------------------------------------------------------------
# common rules ---> 定义全局变量 ROOT_PATH 为 ../../..
# ----------------------------------------------------------------------------
ROOT_PATH := ../../..

# ----------------------------------------------------------------------------
# ---> 2. 包含配置文件gcc.mk 后面分析
# ----------------------------------------------------------------------------
include $(ROOT_PATH)/gcc.mk

# ----------------------------------------------------------------------------
# project and objects ---> 定义全局变量 PROJECT
# ----------------------------------------------------------------------------
PROJECT := echocloud_demo

# ----------------------------------------------------------------------------
# ---> 给全局变量 INCLUDE_PATHS 追加值,包含路径:
#      ../../../project/echocloud_demo
#      ../../../project/common/framework/sys_ctrl
# ----------------------------------------------------------------------------
INCLUDE_PATHS += -I$(ROOT_PATH)/project/$(PROJECT)
INCLUDE_PATHS += -I$(ROOT_PATH)/project/common/framework/sys_ctrl/

# ----------------------------------------------------------------------------
# ---> 定义全局变量 DIRS_IGNORE 其值为: 
#      ../gcc%
#      ../image%
#      ../../../project/common/board/%
# ----------------------------------------------------------------------------
DIRS_IGNORE := ../gcc% ../image% $(ROOT_PATH)/project/common/board/%

# ----------------------------------------------------------------------------
# 定义全局变量 DIRS_ALL := $(shell find .. $(ROOT_PATH)/project/common -type d)
# 即递归包含(如果该文件夹下包含子文件夹,也包含在内):
#    | 父目录 | 下所有文件夹
#    | ../../../project/common | 下所有文件夹
# 先炒个手撕包菜*^_^*, 完了再分析。。。。。。
# ----------------------------------------------------------------------------
DIRS_ALL := $(shell find .. $(ROOT_PATH)/project/common -type d)

# ----------------------------------------------------------------------------
# ---> 定义全局变量 DIRS 为:
#      从 DIRS_ALL 中过滤掉 DIRS_IGNORE 之后余下的文件夹
#      ../../../project/common/board/__PRJ_CONFIG_BOARD 文件夹
# ----------------------------------------------------------------------------
DIRS := $(filter-out $(DIRS_IGNORE),$(DIRS_ALL))
DIRS += $(ROOT_PATH)/project/common/board/$(__PRJ_CONFIG_BOARD)

# ----------------------------------------------------------------------------
# ---> 定义全局变量 SRCS 为:DIRS 中后缀为 *.c/*.s *.S的文件,此处只用去掉后缀的部分 
# ----------------------------------------------------------------------------
SRCS := $(basename $(foreach dir,$(DIRS),$(wildcard $(dir)/*.[csS])))

# ----------------------------------------------------------------------------
# ---> 定义全局变量 OBJS 为: SRCS所代表的所有文件分别加入.o后缀
# ----------------------------------------------------------------------------
OBJS := $(addsuffix .o,$(SRCS))

# ----------------------------------------------------------------------------
# ---> extra libs:指定需要用到的静态链接库
# ----------------------------------------------------------------------------
PRJ_EXTRA_LIBS := -lechocloud

# ----------------------------------------------------------------------------
# override project variables
# ----------------------------------------------------------------------------
# linker script path/file 自定义链接脚本、路径
#   - relative to "./"
#   - define your own "LINKER_SCRIPT_PATH" and/or "LINKER_SCRIPT" to override
#     the default one
#LINKER_SCRIPT_PATH := .
#LINKER_SCRIPT := ./xr871_appos_xip.ld

# image config path/file 自定义镜像文件路径
#   - relative to "../image/xxxxx/", eg. "../image/xr871/"
#   - define your own "IMAGE_CFG_PATH" and/or "IMAGE_CFG" to override the
#     default one

# ----------------------------------------------------------------------------
# ---> 3. 如果镜像需要压缩, 指定 IMAGE_CFG_PATH 为当前路径,IMAGE_CFG 为 ./image_xip.cfg (后面分析)
# ----------------------------------------------------------------------------
ifeq ($(__PRJ_CONFIG_IMG_COMPRESS), y)
	IMAGE_CFG_PATH := .
	IMAGE_CFG := ./image_xip.cfg
endif

# image name, default to xr_system 镜像文件名称
# IMAGE_NAME :=

# project make rules 包含make规则,PRJ_MAKE_RULES 指定
include $(PRJ_MAKE_RULES)

1. 配置文件 ./localconfig.mk 分析

# ---> 工程本地配置文件,覆盖掉公共的配置文件;
# project local config options, override the common config options
#

# ----------------------------------------------------------------------------
# board definition ---> 指定单板类型
# ----------------------------------------------------------------------------
__PRJ_CONFIG_BOARD := xr871_evb_audio

# ----------------------------------------------------------------------------
# override global config options ---> 覆盖全局配置操作
# export: 将特定变量导出到 sub-make
# ----------------------------------------------------------------------------
# set y to enable bootloader and disable some features, for bootloader only
# export __CONFIG_BOOTLOADER := y

# set n to disable dual core features, for bootloader only
# export __CONFIG_ARCH_DUAL_CORE := n

# ----------------------------------------------------------------------------
# override project common config options
# ----------------------------------------------------------------------------
# support both sta and ap, default to n
# __PRJ_CONFIG_WLAN_STA_AP := y

# ---> 定义全局变量 __PRJ_CONFIG_XPLAYER
# support xplayer, default to n
__PRJ_CONFIG_XPLAYER := y

# ---> 定义全局变量 __PRJ_CONFIG_XIP
# enable XIP, default to n
__PRJ_CONFIG_XIP := y

# ---> 链接函数级别的text/rodata/data段到.xip 段中
# set y to link function level's text/rodata/data to ".xip" section
ifeq ($(__PRJ_CONFIG_XIP), y)
export __CONFIG_XIP_SECTION_FUNC_LEVEL := y
endif

# enable OTA, default to n
# __PRJ_CONFIG_OTA := y

# enable image compress
# __PRJ_CONFIG_IMG_COMPRESS := y

2. 配置文件 …/…/…/gcc.mk 分析

#
# Common rules for GCC Makefile ---> gcc Makefile 通用规则
#

# ----------------------------------------------------------------------------
# cross compiler ---> 交叉编译器
# ----------------------------------------------------------------------------
#CC_DIR := ~/tools/gcc-arm-none-eabi-4_9-2015q2/bin
# 定义全局变量 ---> 交叉编译器路径
CC_DIR := /opt/gcc-arm-none-eabi-4_9-2015q3/bin
# 定义全局变量 ---> 交叉编译器命令
CC_PREFIX := $(CC_DIR)/arm-none-eabi-

AS      := $(CC_PREFIX)as
CC      := $(CC_PREFIX)gcc
CPP     := $(CC_PREFIX)g++
LD      := $(CC_PREFIX)ld
AR      := $(CC_PREFIX)ar
OBJCOPY := $(CC_PREFIX)objcopy
OBJDUMP := $(CC_PREFIX)objdump
SIZE    := $(CC_PREFIX)size
STRIP   := $(CC_PREFIX)strip

# ----------------------------------------------------------------------------
# tools ---> | -u copy only when the SOURCE file is newer than the 
# destination file or when the destination file is missing |
# ----------------------------------------------------------------------------
CP := cp -u

# ---> 根据宿主平台,定义 makeimage 命令
# $(MKIMAGE) is a tool for creating image
ifeq ($(shell uname -o), Cygwin)
  MKIMAGE := mkimage.exe
else
  MKIMAGE := mkimage
endif

# ----------------------------------------------------------------------------
# global configuration ---> 2.1 全局配置文件 ../../../config.mk 
# ----------------------------------------------------------------------------
include $(ROOT_PATH)/config.mk

# ----------------------------------------------------------------------------
# options 全局变量
# ----------------------------------------------------------------------------
QUIET ?= n
OPTIMIZE := y
MDK_DBG_EN := y
HARDFP := n

# building display ---> 静默编译
ifeq ($(QUIET), y)
  Q := @
  S := -s
endif

# ---> 优化标志 -Os -DNDEBUG
# Level 2.5,-Os 相当于-O2.5
# 专门优化目标文件大小,执行所有的不增加目标文件大小的-O2优化选项.并且执行专门减小目标文件大小的优化选项
ifeq ($(OPTIMIZE), y) 
  OPTIMIZE_FLAG := -Os -DNDEBUG
else
  OPTIMIZE_FLAG := -O0 -DDEBUG
endif

# ---> 调试选项,-gdwarf-2: 产生DWARF version2 的格式的调试信息,常用于IRIXX6上的DBX调试器.GCC会使用DWARF version3的一些特性
ifeq ($(MDK_DBG_EN), y)
  DBG_FLAG := -gdwarf-2
else
  DBG_FLAG := -g
endif

# ---> FPU,这里是softfp
ifeq ($(HARDFP), y)
  FLOAT_ABI := hard
else
  FLOAT_ABI := softfp
endif

# ----------------------------------------------------------------------------
# flags for compiler and linker ---> 编译连接标志;
# ----------------------------------------------------------------------------
# CPU/FPU options ---> ok 此处为 m4
ifeq ($(__CONFIG_CPU_CM4F), y)
  CPU := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=$(FLOAT_ABI)
else
  CPU := -mcpu=cortex-m3 -mthumb
endif

# ---> 编译标志 
CC_FLAGS = $(CPU) -c $(DBG_FLAG) -fno-common -fmessage-length=0 \
	-fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer \
	-Wall -Werror -Wpointer-arith -Wno-error=unused-function \
	-MMD -MP $(OPTIMIZE_FLAG)
# ---> 链接标志, 其中 -Wl,-Map=$(basename $@).map ---> 指定生成的map文件名称:echocloud_demo.map
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs \
	-Wl,-Map=$(basename $@).map,--cref

# config symbols --> 在2.1全局配置文件 ../../../config.mk中定义
CC_SYMBOLS = $(CONFIG_SYMBOLS)
AS_SYMBOLS = $(CONFIG_SYMBOLS)

# 串口重定向以及打印浮点型数字
ifeq ($(__CONFIG_LIBC_PRINTF_FLOAT), y)
  LD_FLAGS += -u _printf_float
endif

ifeq ($(__CONFIG_LIBC_SCANF_FLOAT), y)
  LD_FLAGS += -u _scanf_float
endif

# ---> 使用ld的wrap选项替换已有库函数,链接时library interpositioning库内插技术
LD_FLAGS += -Wl,--wrap,main
LD_FLAGS += -Wl,--wrap,malloc
LD_FLAGS += -Wl,--wrap,realloc
LD_FLAGS += -Wl,--wrap,free
LD_FLAGS += -Wl,--wrap,_malloc_r
LD_FLAGS += -Wl,--wrap,_realloc_r
LD_FLAGS += -Wl,--wrap,_free_r
# ---> 如果启动了malloc trace
ifeq ($(__CONFIG_MALLOC_TRACE), y)
LD_FLAGS += -Wl,--wrap,calloc
LD_FLAGS += -Wl,--wrap,strdup
endif

# standard libraries ---> 系统标准库
LD_SYS_LIBS := -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys

# include path ---> 头文件包含路径 INCLUDE_PATHS 全局变量
INCLUDE_ROOT_PATH := $(ROOT_PATH)/include
INCLUDE_PATHS = -I$(INCLUDE_ROOT_PATH) \
	-I$(INCLUDE_ROOT_PATH)/libc \
	-I$(INCLUDE_ROOT_PATH)/driver/cmsis

ifeq ($(__CONFIG_OS_FREERTOS), y)
  INCLUDE_PATHS += -I$(INCLUDE_ROOT_PATH)/kernel/FreeRTOS
  ifeq ($(__CONFIG_CPU_CM4F), y)
    INCLUDE_PATHS += -I$(INCLUDE_ROOT_PATH)/kernel/FreeRTOS/portable/GCC/ARM_CM4F
  else
    INCLUDE_PATHS += -I$(INCLUDE_ROOT_PATH)/kernel/FreeRTOS/portable/GCC/ARM_CM3
  endif
endif

# ---> lwip-1.4.1 网络协议库版本
ifeq ($(__CONFIG_LWIP_V1), y)
  LWIP_DIR := lwip-1.4.1
else
  LWIP_DIR := lwip-2.0.3
endif

INCLUDE_PATHS += -I$(INCLUDE_ROOT_PATH)/net/$(LWIP_DIR)
ifeq ($(__CONFIG_LWIP_V1), y)
  INCLUDE_PATHS += -I$(INCLUDE_ROOT_PATH)/net/$(LWIP_DIR)/ipv4
endif

# ----------------------------------------------------------------------------
# common makefile for library and project ---> 库和工程的通用配置文件
# 2.2 ---> 分析 ../../../src/lib.mk 
# 2.3 ---> 分析 ../../../project/project.mk 
# ----------------------------------------------------------------------------
LIB_MAKE_RULES := $(ROOT_PATH)/src/lib.mk
PRJ_MAKE_RULES := $(ROOT_PATH)/project/project.mk

# ----------------------------------------------------------------------------
# common rules of compiling objects 编译目标文件的通用规则
# $(Q):静默编译,此处不使能
# $(CC): arm-none-eabi-gcc
# $(CPU): -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp
# -x assembler-with-cpp,明确指定后面的输入语言文件为:已经预处理的汇编文件???
# 例如:gcc –c hello.s –o hello.o,得到一个.o为后缀的目标文件
# 即:此处为将全部的.asm/.s/.S/.c/.cpp 文件编译得到对应的.o目标文件
# ----------------------------------------------------------------------------
%.o: %.asm
	$(Q)$(CC) $(CPU) $(AS_SYMBOLS) -c -x assembler-with-cpp -o $@ $<

%.o: %.s
	$(Q)$(CC) $(CPU) $(AS_SYMBOLS) -c -x assembler-with-cpp -o $@ $<

%.o: %.S
	$(Q)$(CC) $(CPU) $(AS_SYMBOLS) -c -x assembler-with-cpp -o $@ $<
# 此处用 INCLUDE_PATHS 即 -I 指定头文件路径
%.o: %.c
	$(Q)$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu99 $(INCLUDE_PATHS) -o $@ $<
# -fno-rtti 禁止运行时类型识别
%.o: %.cpp
	$(Q)$(CPP) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu++98 -fno-rtti $(INCLUDE_PATHS) -o $@ $<

2.1 全局配置文件 …/…/…/config.mk

#
# global config options
#

# ----------------------------------------------------------------------------
# config options 配置
# ----------------------------------------------------------------------------
# chip and cpu 芯片及cpu内核
__CONFIG_CHIP_XR871 ?= y
__CONFIG_CPU_CM4F ?= y

# arch and core 架构及其核数
__CONFIG_ARCH_DUAL_CORE ?= y
__CONFIG_ARCH_APP_CORE ?= y
__CONFIG_ARCH_NET_CORE ?= n

# redefine int32_t to signed int, but not signed long
__CONFIG_LIBC_REDEFINE_GCC_INT32_TYPE ?= y

# support printf float variables ---> 使能串口重定向以及打印浮点型数字
__CONFIG_LIBC_PRINTF_FLOAT ?= y

# support scanf float variables
__CONFIG_LIBC_SCANF_FLOAT ?= y

# heap managed by stdlib ---> 堆管理使用标准库的malloc
__CONFIG_MALLOC_USE_STDLIB ?= y

# trace heap memory usage and error when using malloc, free, etc. 
# ---> 禁止跟踪堆内存的使用和错误
__CONFIG_MALLOC_TRACE ?= n

# os ---> 指定使用的操作系统FREERTOS
__CONFIG_OS_FREERTOS ?= y

# lwIP ---> 指定使用的网络协议栈lwIP 1.4.1
#   - y: lwIP 1.4.1, support IPv4 stack only
#   - n: lwIP 2.x.x, support dual IPv4/IPv6 stack
__CONFIG_LWIP_V1 ?= y

# mbuf implementation mode ---> mbuf的实现方式0
#   - mode 0: continuous memory allocated from net core
#   - mode 1: continuous memory (lwip pbuf) allocated from app core
__CONFIG_MBUF_IMPL_MODE ?= 0

# link function level's text/rodata/data to ".xip" section
# ---> 禁止链接函数级别的text/rodata/data段到.xip 段中
__CONFIG_XIP_SECTION_FUNC_LEVEL ?= n

# bin compression ---> 禁止二进制文件压缩
__CONFIG_BIN_COMPRESS ?= n

# enable/disable bootloader, y to enable bootloader and disable some features 
# ---> 禁止bootloader
__CONFIG_BOOTLOADER ?= n

# ----------------------------------------------------------------------------
# config symbols ---> 定义宏配置 CONFIG_SYMBOLS 全局变量
# ----------------------------------------------------------------------------
CONFIG_SYMBOLS =
# ---> ok 
ifeq ($(__CONFIG_CHIP_XR871), y)
  CONFIG_SYMBOLS += -D__CONFIG_CHIP_XR871
endif
# ---> ok
ifeq ($(__CONFIG_CPU_CM4F), y)
  CONFIG_SYMBOLS += -D__CONFIG_CPU_CM4F
endif
# ---> ok
ifeq ($(__CONFIG_ARCH_DUAL_CORE), y)
  CONFIG_SYMBOLS += -D__CONFIG_ARCH_DUAL_CORE
endif
# ---> ok
ifeq ($(__CONFIG_ARCH_APP_CORE), y)
  CONFIG_SYMBOLS += -D__CONFIG_ARCH_APP_CORE
endif
# ---> n
ifeq ($(__CONFIG_ARCH_NET_CORE), y)
  CONFIG_SYMBOLS += -D__CONFIG_ARCH_NET_CORE
endif
# ---> ok
ifeq ($(__CONFIG_LIBC_REDEFINE_GCC_INT32_TYPE), y)
  CONFIG_SYMBOLS += -D__CONFIG_LIBC_REDEFINE_GCC_INT32_TYPE
endif
# ---> ok
ifeq ($(__CONFIG_MALLOC_USE_STDLIB), y)
  CONFIG_SYMBOLS += -D__CONFIG_MALLOC_USE_STDLIB
endif
# ---> n
ifeq ($(__CONFIG_MALLOC_TRACE), y)
  CONFIG_SYMBOLS += -D__CONFIG_MALLOC_TRACE
endif
# ---> ok
ifeq ($(__CONFIG_OS_FREERTOS), y)
  CONFIG_SYMBOLS += -D__CONFIG_OS_FREERTOS
endif
# ---> ok
ifeq ($(__CONFIG_LWIP_V1), y)
  CONFIG_SYMBOLS += -D__CONFIG_LWIP_V1
endif
# ---> 0
CONFIG_SYMBOLS += -D__CONFIG_MBUF_IMPL_MODE=$(__CONFIG_MBUF_IMPL_MODE)
# ---> n
ifeq ($(__CONFIG_XIP_SECTION_FUNC_LEVEL), y)
  CONFIG_SYMBOLS += -D__CONFIG_XIP_SECTION_FUNC_LEVEL
endif
# ---> n
ifeq ($(__CONFIG_BIN_COMPRESS), y)
  CONFIG_SYMBOLS += -D__CONFIG_BIN_COMPRESS
endif
# ---> n
ifeq ($(__CONFIG_BOOTLOADER), y)
  CONFIG_SYMBOLS += -D__CONFIG_BOOTLOADER
endif

# ----------------------------------------------------------------------------
# config chip name ---> 芯片名称 全局变量 CONFIG_CHIP_NAME
# ----------------------------------------------------------------------------
ifeq ($(__CONFIG_CHIP_XR871), y)
  CONFIG_CHIP_NAME = xr871
else
  error "CONFIG_CHIP_NAME" is not defined!
endif

2.2 分析 …/…/…/src/lib.mk

#
# Rules for building library ---> 库构件规则
#

# ----------------------------------------------------------------------------
# common targets and building rules 
# ----------------------------------------------------------------------------
# ---> 安装路径: INSTALL_PATH
INSTALL_PATH := $(ROOT_PATH)/lib

.PHONY: all install size clean install_clean

all: $(LIBS)
# ---> 将.o目标文件 归档打包为库文件
$(LIBS): $(OBJS)
	$(Q)$(AR) -crs $@ $^
# ---> 安装到指定目录下: 
# cp -t, --target-directory=DIRECTORY  copy all SOURCE arguments into DIRECTORY
install: $(LIBS)
	$(Q)$(CP) -t $(INSTALL_PATH) $^
# ---> arm-none-eabi-size
# The GNU size utility lists the section sizes—and the total size—for each of 
# the object or archive files objfile in its argument list. By default, 
# one line of output is generated for each object file or each module in an archive.
# -t Show totals of all objects listed (Berkeley format listing mode only).
size:
	$(Q)$(SIZE) -t $(LIBS)

clean:
	$(Q)-rm -f $(LIBS) $(OBJS) $(DEPS)

install_clean:
	$(Q)-rm -f $(INSTALL_PATH)/$(LIBS)

# ----------------------------------------------------------------------------
# dependent rules 依赖文件 把$(OBJS)中的变量符合后缀是.o的全部替换成.d
# linux shell规则: 
# - 表示:使任何命令行的任何非零退出状态都被忽略,就是,忽略当前此行命令执行时候所遇到的错误
# @ 表示在make执行时候,输出的信息中,不要显示此行命令,静默编译;
# ----------------------------------------------------------------------------
DEPS = $(OBJS:.o=.d)
-include $(DEPS)

2.3 —> 分析 …/…/…/project/project.mk

#
# Rules for building project ---> 构件工程规则
#

# ----------------------------------------------------------------------------
# project common config ---> 2.3.1 工程通用配置文件 后面分析
# ----------------------------------------------------------------------------
include $(ROOT_PATH)/project/prjconfig.mk 

# ----------------------------------------------------------------------------
# library ---> 指定链接库的路径
# ----------------------------------------------------------------------------
LIBRARY_PATHS := -L$(ROOT_PATH)/lib

# There are strong and weak symbols in "lchip", it may link to the weak symbol
# as they are static libraries, so use --whole-archive to solve this problem.
# ---> --whole-archive:For each archive mentioned on the command line after the --whole-archive 
# option, include  every  object  file  in the archive in the link, rather than
# searching  the  archive  for  the  required  object files.
# 在代码中定义的符号(如函数名)还未使用到之前,链接器并不会把它加入到连接表中,使用--whole-archive 强制读取
# 此处为将chip库中的所有符号都加载到连接表中;
LIBRARIES := -Wl,--whole-archive -lchip -Wl,--no-whole-archive -lota -limage

# add extra libs from specific project
# ---> 顶层/src/project/echocloud_demo/gcc/Makefile:
# PRJ_EXTRA_LIBS := -lechocloud
LIBRARIES += $(PRJ_EXTRA_LIBS)

ifneq ($(__CONFIG_BOOTLOADER), y)

# audio player libs
# ---> ok 
ifeq ($(__PRJ_CONFIG_XPLAYER), y)
  LIBRARIES += \
            -lcedarx \
            -lmp3 \
            -lamr \
            -lamren \
            -laac \
            -lcedarx
endif

# network libs
# ---> ok 
LIBRARIES += -lmqtt \
	-lnopoll \
	-llibwebsockets \
	-lhttpd \
	-lhttpcli \
	-lmbedtls \
	-lsntp \
	-lping \
	-ludhcpd \
	-lxrsys \
	-lwlan \
	-lsmartlink \
	-lairkiss_aes \
	-lsc_assistant \
	-llwip \
	-lxrsys
# ---> ok 
LIBRARIES += -lcjson -lfs -lconsole -lcomponent -lefpg -lpm -laudmgr -lpcm \
	-luncompress -ladt -lutil

endif # __CONFIG_BOOTLOADER
# ---> ok os
LIBRARIES += -los
# ---> ok freertos
ifeq ($(__CONFIG_OS_FREERTOS), y)
  LIBRARIES += -lfreertos
endif
# ---> LD_SYS_LIBS 在2. ../../../gcc.mk 中
LIBRARIES += $(LD_SYS_LIBS) -lxrc

# ----------------------------------------------------------------------------
# extra include path
# ----------------------------------------------------------------------------、
# ---> ok
ifeq ($(__PRJ_CONFIG_XPLAYER), y)
  CEDARX_INC_DIRS := $(shell find $(ROOT_PATH)/include/cedarx -type d)
  INCLUDE_PATHS += $(foreach dir, $(CEDARX_INC_DIRS), -I$(dir))
endif

INCLUDE_PATHS += -I$(ROOT_PATH)/project
# ---> 单板 __PRJ_CONFIG_BOARD := xr871_evb_audio 
ifneq ($(__PRJ_CONFIG_BOARD),)
  INCLUDE_PATHS += -I$(ROOT_PATH)/project/common/board/$(__PRJ_CONFIG_BOARD)
else
  $(error board is not defined!)
endif

# ----------------------------------------------------------------------------
# include config header for all project
# ----------------------------------------------------------------------------
CC_FLAGS += -include common/prj_conf_opt.h

# ----------------------------------------------------------------------------
# common suffix
# ----------------------------------------------------------------------------
# ---> n
ifeq ($(__PRJ_CONFIG_WLAN_STA_AP), y)
  SUFFIX_WLAN := _sta_ap
endif
# ---> ok
ifeq ($(__PRJ_CONFIG_XIP), y)
  SUFFIX_XIP := _xip
endif
# ---> n
ifeq ($(__CONFIG_XIP_SECTION_FUNC_LEVEL), y)
  LINKER_SCRIPT_SUFFIX := _max
endif

# ----------------------------------------------------------------------------
# linker script
# ----------------------------------------------------------------------------
# linker script, maybe override by the specific project ---> ?= 如果未赋值,则赋值
# := 是覆盖之前的值
LINKER_SCRIPT_PATH ?= $(ROOT_PATH)/project/linker_script/gcc/$(CONFIG_CHIP_NAME)

# ---> ./project/linker_script/gcc/xr871/appos_xip.ld
LINKER_SCRIPT ?= $(LINKER_SCRIPT_PATH)/appos$(SUFFIX_XIP)$(LINKER_SCRIPT_SUFFIX).ld

# ----------------------------------------------------------------------------
# image ---> xr871
# ----------------------------------------------------------------------------
# original path of bin files
BIN_PATH := $(ROOT_PATH)/bin/$(CONFIG_CHIP_NAME)

# output image path ---> xr871
IMAGE_PATH := ../image/$(CONFIG_CHIP_NAME)

# $(IMAGE_TOOL) is relative to $(IMAGE_PATH) ---> mkimage
IMAGE_TOOL := ../$(ROOT_PATH)/tools/$(MKIMAGE)

# image config file, maybe override by the specific project
# $(IMAGE_CFG_PATH) is relative to $(IMAGE_PATH)
IMAGE_CFG_PATH ?= ../$(ROOT_PATH)/project/image_cfg/$(CONFIG_CHIP_NAME)
# ./project/image_cfg/xr871/image_xip.cfg
IMAGE_CFG ?= $(IMAGE_CFG_PATH)/image$(SUFFIX_WLAN)$(SUFFIX_XIP).cfg

# image tool's options to enable/disable OTA 
# ---> n
ifeq ($(__PRJ_CONFIG_OTA), y)
  IMAGE_TOOL_OPT := -O
else
  IMAGE_TOOL_OPT :=
endif

# image name, maybe override by the specific project ---> 镜像名称xr_system
IMAGE_NAME ?= xr_system

# ----------------------------------------------------------------------------
# common targets and building rules
# ----------------------------------------------------------------------------
CC_SYMBOLS += $(PRJ_CONFIG_SYMBOLS)
# ---> axf
ifeq ($(MDK_DBG_EN), y)
  ELF_EXT = axf
else
  ELF_EXT = elf
endif

# ---> echocloud_demo.axf
.PHONY: all $(PROJECT).$(ELF_EXT) objdump size clean lib lib_clean \
	lib_install_clean install image image_clean build build_clean
	
# ---> echocloud_demo.bin
all: $(PROJECT).bin size

# ---> echocloud_demo.axf
$(PROJECT).$(ELF_EXT): $(OBJS)
	$(Q)$(CC) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $@ $(OBJS) $(LIBRARIES)

%.bin: %.$(ELF_EXT)
# ---> ok
# -R .xip  (--remove-section)    输出文件中不要.xip这个section,缩小了文件尺寸
# -j Copy only the indicated sections from the input file to the output file.
ifeq ($(__PRJ_CONFIG_XIP), y)
	$(Q)$(OBJCOPY) -O binary -R .xip $< $@
	$(Q)$(OBJCOPY) -O binary -j .xip $< $(basename $@)$(SUFFIX_XIP).bin
else
	$(Q)$(OBJCOPY) -O binary $< $@
endif
# -S Display source code intermixed with disassembly, if possible
# -d disassemble Display the assembler mnemonics for the machine instructions from objfile
# -h Display summary information from the section headers of the object file
%.objdump: %.$(ELF_EXT)
	$(Q)$(OBJDUMP) -Sdh $< > $@

objdump: $(PROJECT).objdump

size:
	$(Q)$(SIZE) $(PROJECT).$(ELF_EXT)

clean:
	$(Q)-rm -f $(PROJECT).* *.bin $(OBJS) $(DEPS)
# ---> 执行src目录下面的makefile文件:2.3.2
# MAKE_COMMAND := make 
# MAKE = $(MAKE_COMMAND)     
# 即$(MAKE) = make 
# make -C: Change to DIRECTORY before doing anything
lib:
	$(Q)$(MAKE) $(S) -C $(ROOT_PATH)/src install

lib_clean:
	$(Q)$(MAKE) $(S) -C $(ROOT_PATH)/src clean

lib_install_clean:
	$(Q)$(MAKE) $(S) -C $(ROOT_PATH)/src install_clean
# ---> n
ifeq ($(__CONFIG_BOOTLOADER), y)

install:
	$(Q)$(CP) $(PROJECT).bin $(ROOT_PATH)/bin/$(CONFIG_CHIP_NAME)/boot.bin

build: lib all install

build_clean: clean lib_clean lib_install_clean

else # __CONFIG_BOOTLOADER

install:
	# ---> 创建镜像目录
	@mkdir -p $(IMAGE_PATH)
	# ---> echocloud_demo.bin 拷贝重命名为 app.bin
	$(Q)$(CP) $(PROJECT).bin $(IMAGE_PATH)/app.bin
# ---> n
ifeq ($(__PRJ_CONFIG_IMG_COMPRESS), y)
	rm -f $(PROJECT).bin.xz
	xz -k --check=crc32 --lzma2=preset=6e,dict=32KiB $(PROJECT).bin
	$(Q)$(CP) $(PROJECT).bin.xz $(IMAGE_PATH)/app.bin.xz
	rm -f $(PROJECT).bin.xz
endif
# ---> echocloud_demo_xip.bin 拷贝重命名为 app_xip.bin
ifeq ($(__PRJ_CONFIG_XIP), y)
	$(Q)$(CP) $(PROJECT)$(SUFFIX_XIP).bin $(IMAGE_PATH)/app$(SUFFIX_XIP).bin
endif
# ---> image 依赖于install
# -t target directories
# ../../../bin/xrb71/*.bin
image: install
	$(Q)$(CP) -t $(IMAGE_PATH) $(BIN_PATH)/*.bin
# ---> n
ifeq ($(__PRJ_CONFIG_IMG_COMPRESS), y)
	rm -f $(BIN_PATH)/*.bin.xz
	xz -k --check=crc32 --lzma2=preset=6e,dict=32KiB $(BIN_PATH)/net.bin
	xz -k --check=crc32 --lzma2=preset=6e,dict=32KiB $(BIN_PATH)/net_ap.bin
	$(Q)$(CP) -t $(IMAGE_PATH) $(BIN_PATH)/*.bin.xz
	rm -f $(BIN_PATH)/*.bin.xz
endif
	cd $(IMAGE_PATH) && \
	chmod a+rw *.bin && \
	# 通过mkimage 和 image配置文件 生成 xr_system.img
	$(IMAGE_TOOL) $(IMAGE_TOOL_OPT) -c $(IMAGE_CFG) -o $(IMAGE_NAME).img

image_clean:
	-rm -f $(IMAGE_PATH)/*.bin $(IMAGE_PATH)/*.xz $(IMAGE_PATH)/*.img

build: lib all image

build_clean: image_clean clean lib_clean lib_install_clean

endif # __CONFIG_BOOTLOADER

# ----------------------------------------------------------------------------
# dependent rules
# ----------------------------------------------------------------------------
DEPS = $(OBJS:.o=.d)
-include $(DEPS)

2.3.1 工程通用配置文件

#
# project common config options
#

# ----------------------------------------------------------------------------
# config options
# ----------------------------------------------------------------------------
# support both sta and ap
__PRJ_CONFIG_WLAN_STA_AP ?= n

# support xplayer
__PRJ_CONFIG_XPLAYER ?= n

# enable XIP
__PRJ_CONFIG_XIP ?= n

# enable OTA
__PRJ_CONFIG_OTA ?= n

# enable ETF CLI
__PRJ_CONFIG_ETF_CLI ?= n

# enable image compress
__PRJ_CONFIG_IMG_COMPRESS ?= n

# ----------------------------------------------------------------------------
# config symbols ---> 由工程通用配置文件,转换为 PRJ_CONFIG_SYMBOLS 宏配置来干预工程编译
# ----------------------------------------------------------------------------
PRJ_CONFIG_SYMBOLS :=

ifeq ($(__PRJ_CONFIG_WLAN_STA_AP), y)
  PRJ_CONFIG_SYMBOLS += -D__PRJ_CONFIG_WLAN_STA_AP
endif

ifeq ($(__PRJ_CONFIG_XPLAYER), y)
  PRJ_CONFIG_SYMBOLS += -D__PRJ_CONFIG_XPLAYER
endif

ifeq ($(__PRJ_CONFIG_XIP), y)
  PRJ_CONFIG_SYMBOLS += -D__PRJ_CONFIG_XIP
endif

ifeq ($(__PRJ_CONFIG_OTA), y)
  PRJ_CONFIG_SYMBOLS += -D__PRJ_CONFIG_OTA
endif

ifeq ($(__PRJ_CONFIG_ETF_CLI), y)
  PRJ_CONFIG_SYMBOLS += -D__PRJ_CONFIG_ETF_CLI
endif

ifeq ($(__PRJ_CONFIG_IMG_COMPRESS), y)
  PRJ_CONFIG_SYMBOLS += -D__PRJ_CONFIG_IMG_COMPRESS
endif

2.3.2 执行src目录下面的makefile文件:

#
# Rules for building sub-modules
#

# ----------------------------------------------------------------------------
# common rules
# ----------------------------------------------------------------------------
ROOT_PATH := ..

# ---> gcc Makefile 通用规则
include $(ROOT_PATH)/gcc.mk 

# ----------------------------------------------------------------------------
# sub-modules
# ----------------------------------------------------------------------------
SUBDIRS := driver/chip libc ota image ------------- 子模块目录

ifeq ($(__CONFIG_OS_FREERTOS), y)
SUBDIRS += kernel/FreeRTOS kernel/os/FreeRTOS
endif

ifneq ($(__CONFIG_BOOTLOADER), y)

SUBDIRS += driver/component \          ------------- 子模块目录
	pm \
	console \
	efpg \
	fs/fatfs \
	audio/pcm \
	audio/manager \
	sys \
	net/wlan \
	net/$(LWIP_DIR) \
	net/ping \
	net/HTTPClient \
	net/mbedtls-2.2.0 \
	net/nopoll \
	net/libwebsockets/lib \
	net/mqtt \
	net/shttpd-1.42 \
	net/sntp \
	net/udhcp-0.9.8 \
	net/cloud/aliyun \
	smartlink \
	cjson \
	atcmd \
	xz \
	util \
	echocloud                         --------------- 此处用的 demo 模块目录

endif

# ----------------------------------------------------------------------------
# building rules
# ----------------------------------------------------------------------------
.PHONY: all install clean install_clean $(SUBDIRS) _all _install _clean _install_clean

all:
	$(Q)$(MAKE) _all TARGET=all

install:
	$(Q)$(MAKE) _install TARGET=install

clean:
	$(Q)$(MAKE) _clean TARGET=clean

install_clean:
	$(Q)$(MAKE) _install TARGET=install_clean
# ---> 进入每个子模块目录执行Makefile,此处分析 echocloud 目录下的 Makefile 2.3.2.1 分析
$(SUBDIRS):
	$(Q)$(MAKE) $(S) -C $@ $(TARGET)

_all: $(SUBDIRS)

_install: $(SUBDIRS)

_clean: $(SUBDIRS)

_install_clean: $(SUBDIRS)
2.3.2.1 分析 src/echocloud 目录下的 Makefile
#
# Rules for building library
#

# ----------------------------------------------------------------------------
# common rules
# ----------------------------------------------------------------------------
ROOT_PATH := ../..

include $(ROOT_PATH)/gcc.mk

# ----------------------------------------------------------------------------
# library and objects
# ----------------------------------------------------------------------------
LIBS := libechocloud.a

DIRS := .

SRCS := $(basename $(foreach dir,$(DIRS),$(wildcard $(dir)/*.[csS])))

OBJS := $(addsuffix .o,$(SRCS))

# library make rules
include $(LIB_MAKE_RULES)

3 配置文件 ./image_xip.cfg

{
    "magic"   :"AWIH",
    "version" :"0.3",
    "OTA"     :{"addr": "1024K", "size": "32K"},
    "count"   :7,
    "section" :[
		{"id": "0xa5ff5a00", "bin" :"boot.bin",	"cert": "null",	"flash_offs": "0K",	"sram_offs": "0x00067000", "ep": "0x00067101", "attr":"0x1"},
		{"id": "0xa5fe5a01", "bin" :"app.bin",	"cert": "null",	"flash_offs": "32K",	"sram_offs": "0x00010000", "ep": "0x00010101", "attr":"0x1"},
		{"id": "0xa5fd5a02", "bin" :"app_xip.bin",	"cert": "null",	"flash_offs": "161K",	"sram_offs": "0xffffffff", "ep": "0xffffffff", "attr":"0x2"},
		{"id": "0xa5fc5a03", "bin" :"net.bin",	"cert": "null",	"flash_offs": "650K",	"sram_offs": "0x60000000", "ep": "0xffffffff", "attr":"0x1"},
		{"id": "0xa5fa5a05", "bin" :"wlan_bl.bin",	"cert": "null",	"flash_offs": "872K",	"sram_offs": "0xffffffff", "ep": "0xffffffff", "attr":"0x1"},
		{"id": "0xa5f95a06", "bin" :"wlan_fw.bin",	"cert": "null",	"flash_offs": "875K",	"sram_offs": "0xffffffff", "ep": "0xffffffff", "attr":"0x1"},
		{"id": "0xa5f85a07", "bin" :"wlan_sdd.bin",	"cert": "null",	"flash_offs": "1006K",	"sram_offs": "0xffffffff", "ep": "0xffffffff", "attr":"0x1"}
	]
}

代码结构

➜ 在xr871sdk目录下运行$: tree -L 2
.
├── bin
│ └── xr871
├── config.mk ------------------- 全局配置文件 上面 2.1 分析
├── gcc.mk ------------------- gcc Makefile 通用规则 上面 2 分析
├── include ------------------- 头文件路径
│ ├── compiler.h
│ ├── driver
│ ├── echocloud
│ ├── fs
│ ├── kernel
│ ├── types.h
│ ├── version.h …
├── lib ------------------- 生成的静态库 install 目录
│ ├── libechocloud.a
│ ├── libfreertos.a
│ ├── libfs.a …
├── project ------------------- 工程路径
│ ├── bootloader
│ ├── common
│ ├── echocloud_demo ------------------- make 运行的示例工程
│ │ ├── command.c
│ │ ├── command.h …
│ │ ├── gcc ------------------- 此处执行 make 命令
│ │ │ ├── echocloud_demo.axf
│ │ │ ├── echocloud_demo.bin
│ │ │ ├── echocloud_demo.map
│ │ │ ├── echocloud_demo_xip.bin
│ │ │ ├── echocloud.map
│ │ │ ├── image_xip.cfg
│ │ │ ├── localconfig.mk ---------------- 上面的 1 分析
│ │ │ ├── Makefile ---------------- 根Makefile
│ │ │ └── xr871_appos_xip.ld ---------------- 自定义链接脚本(此工程中未使用)
│ │ ├── image ---------------- 生成的镜像文件路径
│ │ │ └── xr871
│ │ │ ├── app.bin
│ │ │ ├── app_xip.bin
│ │ │ ├── boot.bin
│ │ │ ├── net_ap.bin
│ │ │ ├── net.bin
│ │ │ ├── wlan_bl.bin
│ │ │ ├── wlan_fw.bin
│ │ │ ├── wlan_sdd.bin
│ │ │ └── xr_system.img
│ │ ├── main.c
│ │ ├── prj_config.h …
│ ├── image_cfg
│ ├── linker_script ------------------- linker_script/gcc/xr871/appos_xip.ld 默认链接脚本
│ ├── prjconfig.mk ------------------- 工程通用配置文件 2.3.1 中分析
│ ├── project.mk ------------------- 工程构建编译规则 2.3 中分析
├── README
├── src ------------------- 每个子模块目录下包含自己的 makefile 文件
│ ├── driver
│ ├── echocloud
│ │ ├── Makefile … 子模块echocloud目录下的 makefile 文件 2.3.2.1
│ ├── fs
│ ├── kernel
│ ├── lib.mk ------------------- 库构件规则 2.2 中分析
│ ├── Makefile ------------------- 负责各个子模块的编译规则 2.3.2 # Rules for building sub-modules
│ ├── net
└── tools
├── mkimage
├── mkimage.exe
├── phoenixMC
└── phoenixMC.exe

总结:

├── project ------------------- 工程路径
│ ├── echocloud_demo ------------------- make 运行的示例工程
│ │ ├── gcc ------------------- 此处执行 make 命令
│ │ │ ├── Makefile ---------------- 根Makefile
│ │ │ ├── localconfig.mk--------- 1. project local config
├── gcc.mk -------------------------- 2. gcc Makefile 通用规则
├── config.mk ----------------------- 2.1 全局配置文件
├── src
│ ├── lib.mk --------------------------2.2 库构件规则
├── project ------------------- 工程路径
│ ├── project.mk --------------------2.3 工程构建编译规则
│ ├── prjconfig.mk ------------------2.3.1 工程通用配置文件
├── src
│ ├── Makefile -----------------------2.3.2 负责各个子模块的编译规则
│ ├── echocloud
│ │ ├── Makefile --------------------2.3.2.1 子模块echocloud目录下的 makefile 文件

你可能感兴趣的:(XR871,sdk源码剖析)