本帖最后由 奋起直追 于 2023-11-25 21:09 编辑
本帖最后由 奋起直追 于 2023-11-25 17:53 编辑
工程编译
在项目子目录中只需要执行 make
即可编译想要的项目,分析从执行这个make开始一系列动作有助于我们理解工程结构以及依赖关系。
这里以最简单的 Project_basic
为例。
1 文件夹结构
从git拉取的工程结构如图所示
在 Project_basic
目录下执行make命令则默认会寻找当前目录下的 Makefile
文件
2 工程结构
2.1 Makefile阶段
打开该Makefile,可看到
# 当前工程文件路径(Current project file path)
SDK_DEMO_PATH ?= .
# 配置SDK路径(Configure SDK path)
BL_SDK_BASE ?= $(SDK_DEMO_PATH)/../aithinker_Ai-M6X_SDK
# 设置SDK路径(Set SDK path)
export BL_SDK_BASE
#配置芯片型号,M61/M62都配置成bl616(Configure chip models, with both M61 and M62 configured as bl616)
CHIP ?= bl616
#配置板子类型,M61/M62 保持 “bl616dk”(Configuration board subtype, M61/M62 maintains' bl616dk ')
BOARD ?= bl616dk
#配置编译工具链(Configure Compilation Toolchain)
CROSS_COMPILE ?= riscv64-unknown-elf-
# add custom cmake definition
#cmake_definition+=-Dxxx=sss
#引用实际的编译配置(Reference the actual compilation configuration)
include $(BL_SDK_BASE)/project.build
SDK_DEMO_PATH设置了当前项目的工作目录
BL_SDK_BASE
指向了博流智能的二次开发SDK目录 aithinker_Ai-M6X_SDK
,在19行
之后设置了二次开发SDK需要的关键参数,包含芯片型号、板子类型以及交叉工具链
最后在19行引入了二次开发的编译脚本。
打开该文件可看到
command_flash = $(BL_FLASH_PROGRAM) --interface=uart --baudrate=$(BAUDRATE) \
--port=$(COMX) --chipname=$(CHIP) --cpu_id=$(CPU_ID) --config=flash_prog_cfg.ini
command_efuse = $(BL_FLASH_PROGRAM) --interface=uart --baudrate=$(BAUDRATE) \
--port=$(COMX) --chipname=$(CHIP) --efuse=build/build_out/efusedata.bin
command_puncover = $(PUNCOVER_PROGRAM) \
--elf_file ./build/build_out/*.elf --map_file ./build/build_out/*.map \
--build_dir ./build --src_root ${BL_SDK_BASE} --port 5001
PS_PROGRAM = /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe
CMAKE = $(BL_SDK_BASE)/tools/cmake/bin/cmake
command_flash = $(PS_PROGRAM) make flash CHIP=$(CHIP) CPU_ID=$(CPU_ID) COMX=$(COMX) BAUDRATE=$(BAUDRATE)
command_efuse = $(PS_PROGRAM) make efuse CHIP=$(CHIP) CPU_ID=$(CPU_ID) COMX=$(COMX) BAUDRATE=$(BAUDRATE)
PUNCOVER_PROGRAM = puncover_riscv
cmake_generator = "Unix Makefiles"
# The command to remove a file.
RM = $(CMAKE) -E remove_directory
CPU_ID ?=
CONFIG_USB_HS ?=y
CONFIG_ROMAPI ?=y
CONFIG_DEBUG ?=y
CONFIG_TLSF ?=y
COMX ?=/dev/ttyUSB0
BAUDRATE ?=2000000
BOARD_DIR ?=
#cmake definition config
cmake_definition+= -DCROSS_COMPILE=${CROSS_COMPILE}
cmake_definition+= -DCHIP=$(CHIP)
cmake_definition+= -DCPU_ID=$(CPU_ID)
cmake_definition+= -DBOARD=$(BOARD)
cmake_definition+= -DBOARD_DIR=$(BOARD_DIR)
cmake_definition+= -DCONFIG_DEBUG=$(CONFIG_DEBUG)
cmake_definition+= -DCONFIG_ROMAPI=$(CONFIG_ROMAPI)
cmake_definition+= -DCONFIG_USB_HS=$(CONFIG_USB_HS)
cmake_definition+= -DCONFIG_COMX=$(COMX)
cmake_definition+= -DCMAKE_EXPORT_COMPILE_COMMANDS=OFF
cmake_definition+= -DCONFIG_TLSF=$(CONFIG_TLSF)
这里我删掉了一部分判断语句,只保留了WSL环境所需的,其他平台同理。
PS_PROGRAM
指定了当前烧录要使用的终端工具,接着下面设置一些参数,而符号 ?=
代表如果该变量设置过了就不再设置,接着是指定了cmake编译环境的参数信息。
build:Makefile
$(CMAKE) -S . -B build -G $(cmake_generator) $(cmake_definition)
make -C build -j8
make -C build combine
cp $(BL_SDK_BASE)/bsp/board/bl616dk/config/edata.bin build/build_out
cp $(BL_SDK_BASE)/bsp/board/bl616dk/config/Rx_boot2_m61.bin build/build_out
make会默认执行遇到的第一个目标,即build,这里build依赖于Makefile文件是否存在,即引用该文件的目录下必须包含Makefile文件。
接着执行下面的命令语句,调用cmake和make开始编译工程。
这里默认调用8核编译,其实建议官方修改为查询CPU核心数
make -j$(nproc)
2.2 CMake阶段
调用cmake会默认的执行脚本是项目子目录中的CMakeLists.txt文件,即和前面Makefile同一级目录的文件。
要看懂这个文件需要一些cmake的基础知识,这里简单介绍一下,其实学习后一目了然。
cmake_minimum_required(VERSION 3.15)
include(proj.conf)
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
# #############################################################
# 搜集所有的C文件( Collect source files)
file(GLOB_RECURSE sources "${CMAKE_CURRENT_SOURCE_DIR}/components/*.c")
# 添加头文件的引用路径(Add .h include directories)
sdk_add_include_directories(main config components/wifi)
# 把C文件添加到工程里(Add .c file to the project)
target_sources(app PRIVATE ${sources})
# 设置main.c 的文件(Set the document source for main. c)
# 注意:不能和file(GLOB_RECURSE sources "${CMAKE_CURRENT_SOURCE_DIR}/components/*.c") 冲突(Note: Cannot conflict with “file(GLOB_RECURSE sources "${CMAKE_CURRENT_SOURCE_DIR}/components/*.c")”)
sdk_set_main_file(main/main.c)
# 设置工程名称,这个配置决定了编译出来的文件名。(Set the project name, which determines the compiled file name)
get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
project(${PROJECT_NAME})
最开始要求了cmake的最低版本,其次引入了配置文件,用于配置cmake编译过程中的模块是否开启。
之后找到博流智能的二次开发SDK包的cmake包
然后设置当前项目目录内的所有源文件以及头文件路径
之后会设置该项目的main函数文件主入口
最后根据当前项目文件夹名字生成最后编译出来的目标文件名以及工程名。
2.3 SDKCMake阶段
命令 find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
根据 HINTS
指定搜索路径参数为 ../aithinker_Ai-M6X_SDK
,在此目录下搜索cmake文件夹以及 buffalo_sdk-config.cmake
文件。
打开该文件有如下语句:
set(BL_SDK_BASE $ENV{BL_SDK_BASE})
set(build_dir ${CMAKE_CURRENT_BINARY_DIR}/build_out)
set(PROJECT_SOURCE_DIR ${BL_SDK_BASE})
set(PROJECT_BINARY_DIR ${build_dir})
set(EXECUTABLE_OUTPUT_PATH ${build_dir})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
add_library(sdk_intf_lib INTERFACE)
add_library(app STATIC)
target_link_libraries(app sdk_intf_lib)
include(${BL_SDK_BASE}/cmake/toolchain.cmake)
include(${BL_SDK_BASE}/cmake/extension.cmake)
include(${BL_SDK_BASE}/cmake/compiler_flags.cmake)
enable_language(C CXX ASM)
add_subdirectory(${BL_SDK_BASE} ${build_dir})
首先除了设置了一些环境变量意外,还指定了两个库。
之后在这里引入了项目子目录,就是 aithinker_Ai-M6X_SDK
目录,联系上 aithinker_Ai-M6X_SDK
目录下的 CMakeLists.txt
文件。
在这个文件中又增加了多个子目录:
cmake_minimum_required(VERSION 3.15)
add_subdirectory(bsp)
add_subdirectory(components)
add_subdirectory(drivers/lhal)
add_subdirectory(drivers/soc/${CHIP}/std)
if("${CHIP}" STREQUAL "bl616")
sdk_add_subdirectory_ifdef(CONFIG_PM drivers/pm)
endif()
sdk_add_subdirectory_ifdef(CONFIG_RF drivers/soc/${CHIP}/rf)
if("${CHIP}" STREQUAL "bl616")
sdk_add_subdirectory_ifdef(CONFIG_RF drivers/rfparam)
endif()
由此我们可知整个系统的层级关系为:
bsp
、components
和 drivers
目录作为项目的库文件存在
进一步细节就跟随add_subdirectory和sdk_add_subdirectory_ifdef语句进入各个子模块,会添加各个模块所需的源文件和头文件路径。
具体内容需要花更多时间分析
2.4 再次回到Makefile阶段
在 build
命令的#2,#3行,执行make指令编译整个工程
最后拷贝输出文件到当前项目的build目录中。
打完收工