1宛官,工程構(gòu)建
參見:https://github.com/alibaba/AliOS-Things/wiki/AliOS-Things-build-system
注意最新的AliOS Things 3.0版本如果使用VSCode IDE編譯葫松,需要安裝AliOS Studio插件和aos-cube。
當(dāng)在VSCODE中執(zhí)行AliOS-Studio:Build的時(shí)候底洗,會(huì)調(diào)用aos make app@board腋么,比如這里我選擇mqtt@stm32f429zi-nucleo,則會(huì)調(diào)用aos make mqtt@stm32f429zi-nucleo.
下面我們分析一下具體都做了什么。
1)亥揖,調(diào)用關(guān)系:
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的標(biāo)準(zhǔn)庫中的subprocess包的類,用來fork一個(gè)子進(jìn)程并運(yùn)行一個(gè)外部程序,進(jìn)入 ./build/Makefile
3)Makefile中最主要的是aos_target_config.mk,定義了構(gòu)建關(guān)系摧扇。
由aos_target_config.mk生成所有組件的config.mk(包含組件源文件以來關(guān)系等信息)圣贸,然后在編譯、鏈接的時(shí)候由aos_target_build.mk依次調(diào)用扳剿,最終生成./out里面的可執(zhí)行文件旁趟。
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創(chuàng)建的文件夾庇绽。
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文件內(nèi)容說明
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兩個(gè)組件,位于kernel/init,和network/netmgr瞧掺,具體可以
# 參考這兩個(gè)位置的*.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
可以看到一個(gè)mk文件的基本組成為:
其中全局是指編譯所有組件時(shí)都要用到的設(shè)置辟狈,局部是指僅在編譯本組件時(shí)用到肠缔。一個(gè)mk文件就是描述了一個(gè)組件的配置信息。其實(shí)配置的設(shè)定都可以在 _CFLAGS 和 _LDFLAGS中指定哼转,包括鏈接使用的鏈接腳本明未。
具體實(shí)現(xiàn)說明
下面按照上面所說的要素來展開說明構(gòu)建體系的具體實(shí)現(xiàn),相關(guān)關(guān)鍵代碼等:
1)工具鏈選擇
宿主平臺(tái)在aos.py中設(shè)置壹蔓。輔助命令工具在 aos_host_cmd.mk 中設(shè)置趟妥,目前主要支持 windows 和 linux64 上兩種編譯宿主機(jī)平臺(tái)。
編譯工具鏈的設(shè)置佣蓉,在aos_target_xx.mk和 aos_library_xx.mk中會(huì)設(shè)置披摄。
2)找到源文件
編譯命令通常是app名@board名,app和board即為查找所有依賴的兩個(gè)入口組件勇凭。
依賴查找過程遞歸實(shí)現(xiàn)疚膊。
事實(shí)上上面的查找除了找到源文件之外還會(huì)解析出mk中定義編譯選項(xiàng)等信息,實(shí)際上是在遞歸解析組件的mk文件虾标。為后面的編譯鏈接步驟做好準(zhǔn)備寓盗。
將上面遞歸解析出的mk中的信息存儲(chǔ)在config.mk中:
config.mk其實(shí)就是把所有組件 mk 中的信息匯總到一起。而后面產(chǎn)生的opts文件則是針對(duì)每個(gè)組件把config.mk中信息重新組合到一起產(chǎn)生的一個(gè)獨(dú)立的文件璧函。
4)編譯
編譯命令, aos_target_build.mk中傀蚌,每個(gè)組件的編譯選項(xiàng)產(chǎn)生, aos_target_config.mk中。
5)鏈接
鏈接命令, aos_target_build.mk中
鏈接選項(xiàng)的產(chǎn)生, aos_target_config.mk中
統(tǒng)一進(jìn)行的二進(jìn)制處理如strip等
FIND_COMPONENT --找到所有需要的組件 參數(shù):所有基本組件柳譬,遞歸調(diào)用
?PREPROCESS_TEST_COMPONENT ?--將所有測試所需的組件也加入到組件中喳张,無參數(shù)
PROCESS_COMPONENT --解析每個(gè)組件的 mk,參數(shù):所有組件
?PROCESS_ONE_COMPONENT ?--解析一個(gè)組件美澳,參數(shù):某一個(gè)組件
WRITE_FILE_CREATE --在config.mk中寫入所有相關(guān)信息销部,包括寫入所有編譯摸航,鏈接選項(xiàng)到opts文件中。