构建对接
阅读对象:
- 需要添加新的平台或芯片构建相关支持的移植开发者。
前置知识:
- 了解 xfusion 的构建命令及其参数的作用。
- 会使用 python
- 简单了解 jinja 用法
- 对将要对接的平台构建流程较为熟悉
对接流程
新增目标对象名
在 xfusion/boards 下新增一个目录,再在其下创建一个名为 “target.json” 的文件,此时,该目录名则为平台环境激活以及构建时可以被选定的目标对象名。
原因:xfusion 在进行环境激活时(. ./export.sh xxx),递归检索并收集 boards 目录下的存在 “target.json” 文件的目录的名字,将其所在的目录名加入到可激活、可构建的目标对象列表中。
如:将要新加 星闪芯片 ws63
可以在 boards 下递归创建目录 nearlink/ws63
其后在 boards/nearlink/ws63 下创建 “target.json” 文件
此时不指定目标平台去执行环境激活命令(. ./export.sh),即可看到提示需要传入目标名,其后紧跟着当前支持的目标名,就能看的 “ws63” 在支持列表中了,如下:
Bashuser@host:. ./export.sh user@host:You need to specify a target: ws63 esp32
对接构建方法
在 xfusion/plugins 下 新增一个目录,目录名需要与步骤 ① 中最终包含“target.json” 文件的目录的名字一致(或者说与执行构建命令时,传入的目标对象名一致)。
原因:xfusion 在进行构建时,会通过执行构建命令时传入的目标对象名在 xfusion/plugins 下 搜寻同名目录,执行其下的构建插件脚本。
在 xfusion/plugins/[new_target]/ 下,创建 “init.py”文件,其内容如下:
Pythonfrom .build import *
在 xfusion/plugins/[new_target]/ 下,创建 “build.py”文件并按要求及需要实现各个回调方法, 其模板内容及注解如下:
Python""" 导入此处构建可能能用的方法: exec_cmd:命令执行( menuconfiig 命令不能使用该方法) apply_template:普通模板解析方法 apply_components_template:组件模板解析方法 get_define:(?待) cd_to_root:跳转至 xf 根目录 cd_to_target:跳转至编译目标(平台侧工程)所在的目录(?待) cd_to_project:跳转至 xf 工程目录 """ import xf_build from xf_build import api """ 为了兼容多开放平台(win、linux等)的目录路径, **常见目录操作请使用 pathlib 方法而不是 os.path 下的方法**, 这是一种面向对象的方法,构建好目录对象后就可以执行对象下的目录操作方法。 如: 路径对象构建:my_nepath:Path = dir_path / "filename.cmake" 检查路径存在与否:my_nepath.exists() 更多方法及说明参考 pathlib 相关文档或源码 """ from pathlib import Path hookimpl = xf_build.get_hookimpl() class **[new_target]**(): # [new_target] 为新增的目标名 # 执行 xf build 时会调用的钩子(回调)函数 # 对接编译方法。 @hookimpl def build(self, args): """ 对接工作通常只需: 1、提供模板文件(*.j2,普通模板与组件模板)(基于 jinja 模板引擎) 2、调用模版系统解析方法,配合模板文件(*.j2), 解析 xf 侧工程的编译信息,生成平台侧可用的构建信息文件 (如xx.mk、CMakeLists.txt、xx.cmake等) 3、将生成的构建信息文件(平台侧可用的)加入到平台侧工程进行编译 在 xf 工程目录下执行 xf build 时的执行流程: 1、xf 构建系统会收集 xf 侧的编译相关信息 (参与编译的文件、includepath、编译选项、CFLAGS、组件信息等), 并生成至工程目录下的 build 目录下 build_environ.json 文件中。 2、xf 构建系统执行此插件文件的 build 方法,一般为以下步骤(需由移植开发者编写): 模板文件编写参考 jinja 文档或参考已存在的其他平台的模板文件 A、根据需要调用对应的模版解析方法及传入对应的模板文件, 对 xf 工程 build 目录下的 build_environ.json 文件进行解析, 方法目前有两种: 普通模板解析方法 def apply_template(temp, save, replace=None): temp:普通模板文件 save:解析完后保存的文件路径(包含名字) replace(可选): 1、读取 build_environ.json 文件 2、jinja 模板引擎加载传入的模板文件进行解析 3、接收解析结果,转存至指定的文件(传入的 save 参数) 组件模板解析方法(非必须,也可自行通过 普通模板解析方法 实现组件解析) def apply_components_template(temp, suffix): temp:组件模板文件 suffix:解析完后保存的文件的名字或后缀。 1、读取 build_environ.json 文件 2、jinja 模板引擎加载传入的组件模板文进行解析, 具体表现为: 遍历 public_components、user_components 组件集合 下的各组件项,每项单独根据组件模板进行解析生成单独的文件, 存储的位置会根据 build_environ.json 中的层次结构进行目录创建, 文件名会根据传入参数 suffix 进行生成: 如果是 suffix 是类似 “xxx” 的文件名形式,则会生成 “xxx” 的文件 如果是 suffix 是类似 “.xxx” 的后缀形式,则会生成组件名(又或者说是所在目录名) 同名的后缀是 “.xxx” 的文件。 例如:public_components 下有组件 xf_hal, 解析生成文件后会 xf 工程 build 目录下, 会出现 build/public_components/xf_hal/ 的目录结构, 在 xf_hal 下: 如果传入 suffix 是 “CMakeLists.txt”,则会生成 CMakeLists.txt 文件; 如果传入 suffix 是 “.mk”,则会生成 xf_hal.mk 文件; B、将步骤 A 中生成的平台侧可用的构建信息文件加入到平台侧工程进行编译。 """ pass # 执行 xf clean 时会调用的钩子(回调)函数 # 对接清除方法 @hookimpl def clean(self, args): pass # 执行 xf flash 时会调用的钩子(回调)函数 # 对接下载方法 @hookimpl def flash(self, args): pass # 执行 xf export 时会调用的钩子(回调)函数 # 对接工程导出方法 @hookimpl def export(self, args): pass # 执行 xf update 时会调用的钩子(回调)函数 # 对接(导出的)工程更新方法 @hookimpl def update(self, args): pass # 执行 xf menuconfig sub 时会调用的钩子(回调)函数 # 对接目标平台的 menuconfig @hookimpl def menuconfig(self, args): # 注意,执行目标平台的 menuconfig 命令时,不要使用 api.exec_cmd 进行执行, # 需要使用 os.system 执行 pass