AliOS Things Mqtt 启动分析 -- 1

1,工程构建

参见:https://github.com/alibaba/AliOS-Things/wiki/AliOS-Things-build-system

注意最新的AliOS Things 3.0版本如果使用VSCode IDE编译,需要安装AliOS Studio插件和aos-cube。

当在VSCODE中执行AliOS-Studio:Build的时候,会调用aos make app@board,比如这里我选择mqtt@stm32f429zi-nucleo,则会调用aos make mqtt@stm32f429zi-nucleo.

下面我们分析一下具体都做了什么。

1),调用关系:

aos make helloworld@linuxhost

    |-- make()

        |-- make_build()

            |-- _run_make(arg_list)

                |-- popen(make_cmd_str, shell=True, cwd=os.getcwd())


2)./build/Makefile

变量的值:build_dir = 'BUILD_DIR=./out/'app_dir = 'APPDIR=./'make_args = helloworld@linuxhostarg_list = ['-e', '-f build/Makefile', make_args, app_dir, build_dir]make_cmd = ./build/cmd/linux64/makemake_cmd_str = make_cmd + 'HOST_OS=Linux64' + 'TOOLS_ROOT=./build' + + list(arg_list)

其中,popen是Python的标准库中的subprocess包的类,用来fork一个子进程并运行一个外部程序,进入 ./build/Makefile

3)Makefile中最主要的是aos_target_config.mk,定义了构建关系。

由aos_target_config.mk生成所有组件的config.mk(包含组件源文件以来关系等信息),然后在编译、链接的时候由aos_target_build.mk依次调用,最终生成./out里面的可执行文件。

config.mk依赖于aos_target_config.mk来生成:

$(OUTPUT_DIR)/config.mk: $(MAKEFILES_PATH)/aos_target_config.mk $(MAKEFILES_PATH)/aos_host_cmd.mk

4)Makefile中的输出为main_app,以及out/config.mk中定义的输出和aos_target_build.mk中定义的输出,以及init-build-env创建的文件夹。

main_app: prebuild $(OUTPUT_DIR)/config.mk $(YOS_SDK_PRE_APP_BUILDS) $(MAKEFILES_PATH)/aos_target_build.mk init-build-env

    $(if $(MBINS_ERROR), $(call MBINS_EXIT))

    $(QUIET)$(ECHO) Build AOS Now

    $(QUIET)$(ECHO) TOOLCHAIN_PATH=$(TOOLCHAIN_PATH)

    $(QUIET)$(MAKE) -r $(JOBSNO) $(SILENT) -f $(MAKEFILES_PATH)/aos_target_build.mk $(CLEANED_BUILD_STRING) $(PASSDOWN_TARGETS)

    $(QUIET)$(ECHO) Build complete: $(BUILD_STRING)

5)board\stm32f429zi-nucleo\aos.mk举例mk文件内容说明

NAME := board_stm32f429zi-nucleo

#编译硬件board基本信息;

$(NAME)_MBINS_TYPE := kernel

$(NAME)_VERSION    := 1.0.1.1

$(NAME)_SUMMARY    := configuration for board stm32f429zi-nucleo

MODULE             := 1062

HOST_ARCH          := Cortex-M4

HOST_MCU_FAMILY    := mcu_stm32f4xx_cube

SUPPORT_MBINS       := no

HOST_MCU_NAME      := STM32F429ZIT6

ENABLE_VFP         := 1

# 组件添加kernel_init netmgr两个组件,位于kernel/init,和network/netmgr,具体可以

# 参考这两个位置的*.mk文件获取编译加入了哪些源文件;

$(NAME)_COMPONENTS += $(HOST_MCU_FAMILY) kernel_init netmgr

# 添加源文件;

$(NAME)_SOURCES += aos/board_partition.c \

                   aos/soc_init.c        \

                   mbmaster_hal/port_serial.c


$(NAME)_SOURCES += Src/stm32f4xx_hal_msp.c \

                   Src/can.c               \

                   Src/timer.c             \

                   Src/i2c.c               \

                   Src/eth.c               \

                   Src/gpio.c              \

                   Src/usart.c             \

                   Src/usb_otg.c           \

                   Src/dma.c               \

                   Src/main.c


$(NAME)_SOURCES += drv/board_drv_led.c

ywss_support    ?= 0


GLOBAL_DEFINES += KV_CONFIG_TOTAL_SIZE=32768 #32kb

GLOBAL_DEFINES += KV_CONFIG_BLOCK_SIZE_BITS=14 #(1 << 14) = 16kb


#depends on sal module if select sal function via build option "AOS_NETWORK_SAL=y"

AOS_NETWORK_SAL    ?= n

ifeq (y,$(AOS_NETWORK_SAL))

$(NAME)_COMPONENTS += sal

module             ?= wifi.mk3060

else

HTTPD_ENABLED ?= y

$(NAME)_SOURCES    += ethernetif.c

$(NAME)_SOURCES    += httpserver-netconn.c

$(NAME)_COMPONENTS += lwip

endif


ifeq ($(COMPILER), armcc)

$(NAME)_SOURCES    += startup_stm32f429xx_keil.s

$(NAME)_LINK_FILES := startup_stm32f429xx_keil.o

else ifeq ($(COMPILER), iar)

$(NAME)_SOURCES    += startup_stm32f429xx_iar.s

else

$(NAME)_SOURCES    += startup_stm32f429xx.s

endif


GLOBAL_INCLUDES += .    \

                   aos/ \

                   Inc/


GLOBAL_CFLAGS  += -DSTM32F429xx -DCENTRALIZE_MAPPING


ifeq ($(COMPILER),armcc)

GLOBAL_LDFLAGS += -L --scatter=board/stm32f429zi-nucleo/STM32F429ZITx.sct

else ifeq ($(COMPILER),iar)

GLOBAL_LDFLAGS += --config board/stm32f429zi-nucleo/STM32F429.icf

else

GLOBAL_LDFLAGS += -T board/stm32f429zi-nucleo/STM32F429ZITx_FLASH.ld

endif


CONFIG_SYSINFO_PRODUCT_MODEL := ALI_AOS_f429-nucleo

CONFIG_SYSINFO_DEVICE_NAME   := f429-nucleo


GLOBAL_CFLAGS += -DSYSINFO_PRODUCT_MODEL=\"$(CONFIG_SYSINFO_PRODUCT_MODEL)\"

GLOBAL_CFLAGS += -DSYSINFO_DEVICE_NAME=\"$(CONFIG_SYSINFO_DEVICE_NAME)\"


# Keil project support

$(NAME)_KEIL_VENDOR = STMicroelectronics

$(NAME)_KEIL_DEVICE = STM32F429ZITx


可以看到一个mk文件的基本组成为:


其中全局是指编译所有组件时都要用到的设置,局部是指仅在编译本组件时用到。一个mk文件就是描述了一个组件的配置信息。其实配置的设定都可以在 _CFLAGS 和 _LDFLAGS中指定,包括链接使用的链接脚本。


具体实现说明

下面按照上面所说的要素来展开说明构建体系的具体实现,相关关键代码等:

1)工具链选择

宿主平台在aos.py中设置。辅助命令工具在 aos_host_cmd.mk 中设置,目前主要支持 windows 和 linux64 上两种编译宿主机平台。

编译工具链的设置,在aos_target_xx.mk和 aos_library_xx.mk中会设置。

2)找到源文件

编译命令通常是app名@board名,app和board即为查找所有依赖的两个入口组件。

依赖查找过程递归实现。

事实上上面的查找除了找到源文件之外还会解析出mk中定义编译选项等信息,实际上是在递归解析组件的mk文件。为后面的编译链接步骤做好准备。

3)config.mk生成

将上面递归解析出的mk中的信息存储在config.mk中:

config.mk其实就是把所有组件 mk 中的信息汇总到一起。而后面产生的opts文件则是针对每个组件把config.mk中信息重新组合到一起产生的一个独立的文件。

4)编译

编译命令, aos_target_build.mk中,每个组件的编译选项产生, aos_target_config.mk中。

5)链接

链接命令, aos_target_build.mk中

链接选项的产生, aos_target_config.mk中

二进制及其他处理

统一进行的二进制处理如strip等

关键宏调用关系梳理

FIND_COMPONENT --找到所有需要的组件 参数:所有基本组件,递归调用

​PREPROCESS_TEST_COMPONENT  --将所有测试所需的组件也加入到组件中,无参数

PROCESS_COMPONENT --解析每个组件的 mk,参数:所有组件

​PROCESS_ONE_COMPONENT  --解析一个组件,参数:某一个组件

WRITE_FILE_CREATE --在config.mk中写入所有相关信息,包括写入所有编译,链接选项到opts文件中。

你可能感兴趣的:(AliOS Things Mqtt 启动分析 -- 1)