介绍
XWOS的构建系统:
- 支持纯命令行方式编译,可用于持续集成环境中,例如jenkins;
- 目前可跨平台,同时在linux、Windows上运行;
- 支持基于Eclipse的IDE:
- NXP S32DS IDE
- STM32CubeIDE
- NXP MCUXpressoIDE
- 为了方便集成第三方软件,XWOS参考了Android的构建系统的
Android.mk
设计出xwmo.mk
。 - 构建系统源码路径:
xwbs
编译环境设置
xwtc
XWOS提供了各平台的gcc和llvm编译工具链,可从百度网盘下载:
linux
安装必要的工具
sudo dpkg-reconfigure dash # 选择“否”
sudo apt install build-essential
sudo apt-add-repository ppa:kelleyk/emacs
sudo apt-get update
sudo apt install emacs27 # 如果是服务器,安装emacs27-nox即可
工具链
XWOS的工具链可从百度网盘下载:
- 路径:xwtc/linux
- 解压命令:
# 注意带上选项p,否则解压后脚本可能丢失执行权限
tar xvfJp M.m.r~linux-x86_64.tar.xz
- 文件列表
<安装路径>
├── 60-openocd.rules
├── 80-gdlink.rules
├── 81-daplink.rules
├── 安装说明.md
├── install.sh
├── xwtc
│ ├── armgcc
│ ├── armllvm
│ ├── openocd
│ ├── ppcvlegcc
│ ├── riscvgcc
│ └── xwtcwd
└── xwtc.sh
- 安装:参考
安装说明.md
windows
工具链
XWOS的工具链可从百度网盘下载:
- 路径:xwtc/windows
- 文件列表
<安装路径>
├── 安装说明.md
└── xwtc
├── armgcc
├── armllvm
└── xwtcwd
- 安装:参考
安装说明.md
编译器
XWOS对不同SOC的编译器支持情况不同,主要取决于上游以及官方的支持情况:
-
ARM-M
- SOC
- STM32
- NXP S32K
- I.MX.RT
- GD32
- 工具链
- gcc
- std: gnu11
- libc: newlib
- g++
- std: gnu++17
- C++STL: libstdc++, libsupc++
- llvm(clang)
- std: gnu11
- libc: newlib
- llvm(clang++)
- std: gnu++14
- C++STL: libc++.a, libc++abi.a
- gcc
- SOC
-
芯莱RISC-V
- SOC
- GD32V
- 工具链
- gcc
- std: gnu11
- libc: newlib
- g++
- std: gnu++17
- C++STL: libstdc++, libsupc++
- llvm
- gcc
- SOC
-
PowerPC
- SOC
- MPC560x
- 工具链
- gcc
- std: gnu11
- libc: newlib
- g++
- llvm
- gcc
- SOC
构建流程
开始
XWOS的构建是从电路板
目录下执行命令make
开始的,以$(XuanWuOS_BRD_DIR)
代表此目录。
执行make
时,可传递参数:
WKSPC=output-dir
:配置输出文件的路径,可为相对路径,也可为绝对路径,
默认路径为$(XuanWuOS_BRD_DIR)/wkspc
,后续用$(XuanWuOS_WKSPC_DIR)
表示;XWOS=topdir
:配置XWOS的根路径,默认为../..
;TARGET=target
:配置输出文件的前缀,默认为XWOS
。
生成配置
构建系统调用脚本xwbs/util/el/mkcfg.el
处理$(XuanWuOS_BRD_DIR)/cfg
下的所有配置文件,
将它们转化成三个文件:
$(XuanWuOS_WKSPC_DIR)/XuanWuOS.cfg
,makefile环境变量,之后被makefile引入。- 其中包含一些关键的路径信息,不同的SOC通过这些路径找到各自的编译配置:
$(XuanWuOS_ARCH_DIR)
:架构相关的源码路径;$(XuanWuOS_CPU_DIR)
:CPU相关的源码路径;$(XuanWuOS_SOC_DIR)
:SOC相关的源码路径;$(XuanWuOS_BRD_DIR)
:电路板相关的源码路径,此路经也是最开始执行make
的地方;$(XuanWuOS_BM_DIR)
:电路板相关的玄武模块路径;$(XuanWuOS_OEM_DIR)
:OEM相关的玄武模块路径,通常为私有代码;$(XuanWuOS_OBJ_DIR)
:$(XuanWuOS_WKSPC_DIR)/obj
,编译输出的目录;
- 其中包含一些关键的路径信息,不同的SOC通过这些路径找到各自的编译配置:
$(XuanWuOS_WKSPC_DIR)/autogen.h
,自动生成的头文件,被顶级头文件xwos/standard.h
包含$(XuanWuOS_WKSPC_DIR)/env.rc
,shell环境变量脚本,可通过source
命令引入这个文件,
使得辅助功能生效。
编译arch.a
构建系统会根据编译规则$(XuanWuOS_ARCH_DIR)/arch.mk
编译
架构描述层(Arch Description Layer)的源码,
并输出静态库$(XuanWuOS_OBJ_DIR)/$(XuanWuOS_ARCH_DIR)/arch.a
。
编译cpu.a
构建系统会根据编译规则$(XuanWuOS_CPU_DIR)/arch.mk
编译
CPU描述层(CPU Description Layer)的源码,
并输出静态库$(XuanWuOS_OBJ_DIR)/$(XuanWuOS_CPU_DIR)/cpu.a
。
编译soc.a
构建系统会根据编译规则$(XuanWuOS_SOC_DIR)/soc.mk
编译
SOC描述层(SOC Description Layer)的源码,
并输出静态库$(XuanWuOS_OBJ_DIR)/$(XuanWuOS_SOC_DIR)/soc.a
。
编译brd.a
构建系统会根据编译规则$(XuanWuOS_BRD_DIR)/brd.mk
编译
电路板描述层(Board Description Layer)的源码,
并输出静态库$(XuanWuOS_OBJ_DIR)/$(XuanWuOS_BRD_DIR)/brd.a
。
编译XWOS内核
构建系统会根据编译规则xwos/xwos.mk
编译XWOS内核的源码,
并输出静态库$(XuanWuOS_OBJ_DIR)/$(XuanWuOS_XWOS_DIR)/xwos.a
。
编译中间件模块
- 构建系统会递归扫描
xwmd/
文件夹以及子文件下的所有xwmo.mk
文件,生成模块列表,
依次将它们编译成.a
静态库,输出到$(XuanWuOS_OBJ_DIR)
目录下。 - 每个
xwmo.mk
文件代表了一个模块,构建系统会另启一个子进程make
对其进行编译,
其中定义了的参数:源代码列表、附加编译选项、头文件路径等对每个编译模块的子进程都是相互独立。 - 每个中间件模块在
$(XuanWuOS_BRD_DIR)/cfg/xwmd.h
中都有一个编译开关的宏定义:1
时表示编译这个模块;0
或未定义表示排除这个模块。- 编译开关的命名规则参考模块编译开关的命名规则。
编译设备模块
- 构建系统会递归扫描
xwcd/
文件夹以及子文件下的所有xwmo.mk
文件,生成模块列表,
依次将它们编译成.a
静态库,输出到$(XuanWuOS_OBJ_DIR)
目录下。 - 每个
xwmo.mk
文件代表了一个模块,构建系统会另启一个子进程make
对其进行编译,
其中定义了的参数:源代码列表、附加编译选项、头文件路径等对每个编译模块的子进程都是相互独立。 - 每个中间件模块在
$(XuanWuOS_BRD_DIR)/cfg/xwcd.h
中都有一个编译开关的宏定义:1
时表示编译这个模块;0
或未定义表示排除这个模块。- 编译开关的命名规则参考模块编译开关的命名规则。
编译电路板模块
- 构建系统会递归扫描
$(XuanWuOS_BM_DIR)
文件夹以及子文件下的所有xwmo.mk
文件,生成模块列表,
依次将它们编译成.a
静态库,输出到$(XuanWuOS_OBJ_DIR)
目录下。 - 每个
xwmo.mk
文件代表了一个模块,构建系统会另启一个子进程make
对其进行编译,
其中定义了的参数:源代码列表、附加编译选项、头文件路径等对每个编译模块的子进程都是相互独立。 - 每个中间件模块在
$(XuanWuOS_BRD_DIR)/cfg/board.h
中都有一个编译开关的宏定义:1
时表示编译这个模块;0
或未定义表示排除这个模块。- 编译开关的命名规则参考模块编译开关的命名规则。
编译第三方软件模块
- 构建系统会递归扫描
xwem/
文件夹以及子文件下的所有xwmo.mk
文件,生成模块列表,
依次将它们编译成.a
静态库,输出到$(XuanWuOS_OBJ_DIR)
目录下。 - 每个
xwmo.mk
文件代表了一个模块,构建系统会另启一个子进程make
对其进行编译,
其中定义了的参数:源代码列表、附加编译选项、头文件路径等对每个编译模块的子进程都是相互独立。 - 每个中间件模块在
$(XuanWuOS_BRD_DIR)/cfg/xwem.h
中都有一个编译开关的宏定义:1
时表示编译这个模块;0
或未定义表示排除这个模块。- 编译开关的命名规则参考模块编译开关的命名规则。
编译应用模块
- 构建系统会递归扫描
xwam/
文件夹以及子文件下的所有xwmo.mk
文件,生成模块列表,
依次将它们编译成.a
静态库,输出到$(XuanWuOS_OBJ_DIR)
目录下。 - 每个
xwmo.mk
文件代表了一个模块,构建系统会另启一个子进程make
对其进行编译,
其中定义了的参数:源代码列表、附加编译选项、头文件路径等对每个编译模块的子进程都是相互独立。 - 每个中间件模块在
$(XuanWuOS_BRD_DIR)/cfg/xwam.h
中都有一个编译开关的宏定义:1
时表示编译这个模块;0
或未定义表示排除这个模块。- 编译开关的命名规则参考模块编译开关的命名规则。
编译OEM模块
- OEM文件夹路径由位于配置文件
$(XuanWuOS_BRD_DIR)/cfg/XuanWuOS.h
中的
配置XuanWuOS_CFG_OEMPATH
指定:- 可以是相对于
$(XuanWuOS_BRD_DIR)
的相对路径; - 可以是绝对路径;
- 路径可指向XWOS根目录之外。
- 配置工具
xwbs/util/el/mkcfg.el
会根据此配置生成变量$(XuanWuOS_OEM_DIR)
;
- 可以是相对于
- 构建系统会递归扫描
$(XuanWuOS_OEM_DIR)
文件夹以及子文件下的所有xwmo.mk
文件,生成模块列表,
依次将它们编译成.a
静态库,输出到$(XuanWuOS_OBJ_DIR)/oem
目录下。 - 每个
xwmo.mk
文件代表了一个模块,构建系统会另启一个子进程make
对其进行编译,
其中定义了的参数:源代码列表、附加编译选项、头文件路径等对每个编译模块的子进程都是相互独立。 - 每个中间件模块在
$(XuanWuOS_BRD_DIR)/cfg/oem.h
中都有一个编译开关的宏定义:1
时表示编译这个模块;0
或未定义表示排除这个模块。- 编译开关的命名规则参考模块编译开关的命名规则。
链接ELF文件
构建系统最终会将以上生成的所有.a
静态库链接成XWOS.elf
文件,
连接脚本由位于配置文件$(XuanWuOS_BRD_DIR)/cfg/XuanWuOS.h
中的XuanWuOS_CFG_LDSCRIPT
指定。
生成bin文件
构建系统会将XWOS.elf文件转换成**.bin文件以及.hex**文件。
构建选项
~V
- 作用:输出完整的编译过程。
- 取值:
- 1: 开启选项
- 0: 关闭选项(默认值)
- 用法:
make ~V=1
~D
- 作用:优化编译,输出体积较小的二进制,但不利于调试。
- 取值:
- 1: 开启选项(默认值)
- 0: 关闭选项
- 用法:
make ~D=0
WKSPC=output-dir
- 作用:配置输出文件的路径,可为相对路径,也可为绝对路径,默认路径为
$(XuanWuOS_BRD_DIR)/wkspc
。
XWOS=topdir
- 作用:配置XWOS的根路径,默认为
../..
。
TARGET=target
- 作用:配置输出文件的前缀,默认为
XWOS
。
玄武模块
XWOS的设备模块、中间件模块、第三方软件模块、电路板模块、以及OEM模块,
都是使用xwmo.mk
来描述编译规则的,将它们统一称为玄武模块(XWMO)。
每个xwmo.mk
文件代表了一个模块,其原理类似于Android系统中的Android.mk
。
构建系统会另启一个子进程make
对其进行编译,
其中源代码列表、附加编译选项、头文件路径等对每个编译模块的子进程都是相互独立。
示例,xwam/example/cxx
的xwmo.mk
:
include $(XuanWuOS_WKSPC_DIR)/XuanWuOS.cfg # 包含环境变量
include $(XWBS_UTIL_MK_XWMO) # 包含一些辅助的Makefile函数
XWMO_CSRCS := mif.c # 指定C源文件
XWMO_CFLAGS := # 指定附加的C编译选项
XWMO_CXXSRCS := task.cxx # 指定C++源文件
XWMO_CXXSRCS += test/literal.cxx test/vector.cxx # 增加C++源文件
XWMO_CXXFLAGS := -Wno-unused-value # C++编译选项
XWMO_CXXFLAGS_llvm += -Wno-error=gnu-string-literal-operator-template # 当编译器为llvm时一增加的C++编译选项
XWMO_INCDIRS := $(call getXwmoDir) # 指定附加的头文件搜索路径,其中使用函数getXwmoDir获得当前xwmo的路径
include xwbs/$(XuanWuOS_CFG_XWMO_MK) # 引用编译Makefile执行编译
模块路径命名规则
由于模块路径需要对应于C语言中的一个宏定义作为编译开关,
因此模块路径需要符合C语言标识符的规则,但可以包含几个特殊符号:
- 路径各级目录命名要符合C语言命名规则;
- 路径中每级目录以
/
隔开; - 路径中可包含
.
,但不能出现../
和./
; - 路径中可包含
-
;
模块编译开关的命名规则
模块必须要有一个与路径对应的宏开关,并被配置为1
,才能被编译:
- 模块路径只需要转换相对路径部分:
- 中间件模块:取
xwmd/
(不含)之后的路径; - 设备驱动模块:取
xwcd/
(不含)之后的路径; - 电路板模块:取
$(XuanWuOS_BRD_DIR)/bm/
(不含)之后的路径; - 第三方软件模块:取
xwem/
(不含)之后的路径; - 应用模块:取
xwam/
(不含)之后的路径; - OEM模块:取
OEM文件夹/
(不含)之后的路径。
- 中间件模块:取
- 路径中的
_
,需要两个_
来表示; - 路径中的
/
被转换成_
; - 路径中的
.
被转换成_
; - 路径中的
-
被转换成_
; - 增加前缀:
- 中间件模块:
XWMDCFG
- 设备模块:
XWCDCFG
- 电路板模块:
BMCFG
- 第三方软件模块:
XWEMCFG
- 应用模块:
XWAMCFG
- OEM模块:
OEMCFG
- 中间件模块:
- 示例:
- 中间件模块:
xwmd/isc/xwpcp
–>XWMDCFG_isc_xwpcp
; - 设备驱动模块:
xwcd/perpheral/ds/i2c/eeprom
–> *XWCDCFG_perpheral_ds_i2c_eeprom
; - 电路板模块:
xwbd/WeActMiniStm32H750/bm/stm32_cube
–>BMCFG_stm32__cube
; - 第三方软件模块:
xwem/vm/l__u_a-5.4.4
–>XWEMCFG_vm_l____u__a_5_4_4
; - 应用模块:
xwam/example/cxx
–>XWAMCFG_example_cxx
; - OEM模块:
oem/app
–>OEMCFG_app
;
- 中间件模块:
- 可以借助辅助功能中的
xwmc
命令生成编译开关的宏标识符。
增加模块
- 中间件模块
- 模块位于
xwmd/
目录中; - 宏编译开关位于文件
$(XuanWuOS_BRD_DIR)/cfg/xwmd.h
,
定义为1
表示编译模块。
- 模块位于
- 设备驱动模块
- 模块位于
xwcd/
目录中; - 宏编译开关位于文件
$(XuanWuOS_BRD_DIR)/cfg/xwcd.h
,
定义为1
表示编译模块。
- 模块位于
- 电路板模块
- 模块位于
$(XuanWuOS_BRD_DIR)/bm/
目录中; - 宏编译开关位于文件
$(XuanWuOS_BRD_DIR)/cfg/board.h
,
定义为1
表示编译模块。
- 模块位于
- 第三方软件模块
- 模块位于
xwem/
目录中; - 宏编译开位于文件
$(XuanWuOS_BRD_DIR)/cfg/xwem.h
,
定义为1
表示编译模块。
- 模块位于
- 应用模块
- 模块位于
xwam/
目录中; - 宏编译开关位于文件
$(XuanWuOS_BRD_DIR)/cfg/xwam.h
,
定义为1
表示编译模块。
- 模块位于
- OEM模块
- 模块位于OEM文件夹内;
- 宏编译开关位于文件
$(XuanWuOS_BRD_DIR)/cfg/oem.h
,
定义为1
表示编译模块。
xwmo.mk
模板
C/C++
include $(XuanWuOS_WKSPC_DIR)/XuanWuOS.cfg # 包含配置文件
include $(XWBS_UTIL_MK_XWMO) # 包含一些预定义Makefile函数
XWMO_CSRCS := # C源文件
XWMO_CSRCS_gcc := # 只对gcc起作用的C源文件
XWMO_CSRCS_llvm := # 只对llvm起作用的C源文件
XWMO_CFLAGS := # C编译选项
XWMO_CFLAGS_gcc := # 只对gcc起作用的C编译选项
XWMO_CFLAGS_llvm := # 只对llvm起作用的C编译选项
XWMO_CXXSRCS := # C++源文件
XWMO_CXXSRCS_gcc := # 只对gcc起作用的C++源文件
XWMO_CXXSRCS_llvm := # 只对llvm起作用的C++源文件
XWMO_CXXFLAGS := # C++编译选项
XWMO_CXXFLAGS_gcc := # 只对gcc起作用的C++编译选项
XWMO_CXXFLAGS_llvm := # 只对llvm起作用的C++编译选项
XWMO_INCDIRS := $(call getXwmoDir) # 获取模块路径并附加到头文件搜索路径
XWMO_INCDIRS_gcc := $(call getXwmoDir) # 获取模块路径并附加到gcc头文件搜索路径
XWMO_INCDIRS_llvm := $(call getXwmoDir) # 获取模块路径并附加到llvm头文件搜索路径
XWMO_LUASRCS := # 转换为C语言数组的Lua脚本源文件
include xwbs/$(XuanWuOS_CFG_XWMO_MK) # 引用编译Makefile执行编译
RUST模块
include $(XuanWuOS_WKSPC_DIR)/XuanWuOS.cfg # 包含配置文件
include $(XWBS_UTIL_MK_XWMO) # 包含一些预定义Makefile函数
include xwbs/$(XuanWuOS_CFG_XWMO_RUST_MK) # 引用编译Makefile执行编译
预编译模块
include $(XuanWuOS_WKSPC_DIR)/XuanWuOS.cfg # 包含配置文件
include $(XWBS_UTIL_MK_XWMO) # 包含一些预定义Makefile函数
XWMO_PREBUILT := # 预先编译好的.a文件
include xwbs/$(XuanWuOS_CFG_XWMO_PREBUILT_MK) # 引用编译Makefile执行编译
辅助功能
为了方便开发,XWOS定义了一些与模块编译相关的辅助命令。
初始化环境
source xwbd/WeActMiniStm32H750/env.sh # 以电路板WeActMiniStm32H750为例
命令
xwmc
- 功能:获取模块编译开关的C语言宏标识符。
- 用法举例:
cd ${XWOS_PATH}/xwem/vm/lua # 进入到vm/lua模块中
xwmc
> XWEMCFG_vm_lua # 输出结果
xwmn
- 功能:获取模块的**.a**文件名。
- 用法举例:
cd ${XWOS_PATH}/xwem/vm/lua # 进入到vm/lua模块中
xwmn
> xwem_vm_lua.a # 输出
xwm
- 功能:编译整个XWOS工程,类似Android的m命令。
- 用法:
xwm [选项] [目标]
- 选项 -B:全部重新编译一次
- 目标:make的目标
- 用法举例:
xwm # 编译整个工程
xwm c # 清理
xwm d # 侧底清理
xwmm
- 功能:单独编译模块,类似Android的mm命令,使用当前路径作为模块的路径。
- 选项 -B:全部重新编译一次
- 用法举例:
cd ${XWOS_PATH}/xwem/vm/lua # 进入到vm/lua模块中
xwmm
xwmmm
- 功能:单独编译模块,类似Android的mmm命令,需要指定模块的路径。
- 选项 -B:全部重新编译一次
- 用法举例:
xwmmm xwem/vm/lua
-
xwcroot
- 功能:切换到XWOS的根目录,类似Android的croot命令。
-
xwcbd
- 功能:切换到电路板目录。