qmk build system

This commit is contained in:
Jimmy
2020-07-14 13:48:10 +08:00
parent f31e2d4a6d
commit 2c7390deb3
56 changed files with 2638 additions and 1 deletions

View File

@@ -0,0 +1,285 @@
# QmkQuick Makefile
## 1. 介绍
### Qmk 是什么
qmk 是TecentOS的一个Makefile编译框架。
### Qmk 的特点
- 多架构支持,支持多种 MCU ARCH、多种CC工具链
- 使用简单任意目录均可make
- 入门简单,新源码目录 Makefile 拷贝即可使用;
- 扩展性简单的修改即可支持新MCU、新的board、新CC工具链的支持
- 模板化多种场景的Makefile拷贝即用;
- 耦合低,跟源码目录结构的耦合低;
- 子目录单独make支持支持子目录编译.a静态库
## TencentOS的make编译
### TencentOS的整体make
```shell
# 进入board目录支持qmk的board
cd board/TencentOS_tiny_EVB_MX_Plus
# 本目录编译
make
# 查看帮助
make help
```
TencentOS的整体编译过程是
3.`board/`下的顶级Makefile开始该Makefile 确定BP 。
3. make访问 `arch/`, 生成`libarch.a`
3. make递归访问其他源码目录节点各Makefile生成`libxxx.a`
3. 各个源码目录节点,依次生成`.a`静态库文件,均位于 `build/`目录下 。
3. make 回到 `board/`的顶级Makefile使用`.a`静态库文件以及链接参数,进行链接。
3. 整体构建完成。
### TecentOS的子目录make
```shell
# 进入某包含Makefile的目录
cd kernel/core
# 本目录编译
make BP=Linux_Posix
# 查看帮助
make help
```
单目录的编译过程是:
3. make访问本目录读取本目录Makefile根据命令行`make BP=xxx`的BP选择`mk/board-pack`
3. 根据BP选择的构建参数以及`TREE_LIB_ENABLE``lib`进行编译。
3. 使用ar进行打包.a 文件放在`build/`目录。
3. 构建完成。
## Qmk 的概念
### generic-Makefile(mk/generic)
又称全局通用型Makefile模板。位于 `mk/generic)`
要求对所有board、所有mcu arch适用。
### board-Makefile(mk/board-pack)
又称板级Makefile模板。位于mk/board-pack 的 bp.${BP}属于board配置型Makefile。
一般只对某一个board适用。
是一个硬件产品工程开发过程中在编译时工具链arch、board等参数的抽象。
嵌入式应用开发工程师主要修改这部分Makefile。
### arch-Makefile(mk/arch-pack)
又称 mcu arch 级别Makefile模板。位于mk/arch-pack 的 ap.xx属于arch配置型Makefile。
要求对同一类arch 的所有board适用。
### src-Makefile节点
又称节点Makefile位于各个源码目录的 Makefile。
所有board都适用属于源码节点配置型Makefile。
不能包含archboard级别的编译参数。
## Qmk 的使用
### 当前目录所有.c编译成一个.a库
复制粘贴 以下 Makefile 内容到源码目录 Makefile。
无需修改。
有特别的CFLAG请根据情况配置 `CFGFLAGS`
>
>3. 注意`TREE_LIB_ENABLE=0`,cc和ar时只搜索当前目录源码不包含子目录
>
>3. 注意`lib=`,表示链接后的库名使用目录名;
>3. 注意板级的编译参数请配置到pack-Makefile否则会导致其他pack编译报错.
```Makefile
###################################################################
#automatic detection QTOP and LOCALDIR
CUR_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
TRYQTOP := $(shell if [ -n "$$QTOP" ] ; then\
echo $$QTOP;\
else\
cd $(CUR_DIR); while /usr/bin/test ! -d mk ; do \
dir=`cd ../;pwd`; \
if [ "$$dir" = "/" ] ; then \
echo Cannot find QTOP in $(firstword $(MAKEFILE_LIST)) 1>&2; \
exit 1; \
fi ; \
cd $$dir; \
done ; \
pwd; \
fi)
QTOP ?= $(realpath ${TRYQTOP})
ifeq ($(QTOP),)
$(error Please run this in a tree)
endif
LOCALDIR = $(patsubst %/,%,$(subst $(realpath $(QTOP))/,,$(CUR_DIR)))
####################################################################
TREE_LIB_ENABLE=0
lib=
subdirs=
CFGFLAGS += -I${QTOP}/kernel/core/include
CFGFLAGS += -I${QTOP}/kernel/evtdrv/include
CFGFLAGS += -I${QTOP}/kernel/hal/include
CFGFLAGS += -I${QTOP}/kernel/pm/include
include ${QTOP}/mk/generic/Make.tpl
```
### 某目录及其子目录的所有.c编译成一个.a库
复制粘贴 以下 Makefile 内容到源码目录 Makefile。
无需修改。
有特别的CFLAG请根据情况配置 `CFGFLAGS`
>
>3. 注意`TREE_LIB_ENABLE=1`,cc和ar时会递归搜索源码包含当前目录及其子目录。
>
>3. 注意`lib=`,表示链接后的库名使用目录名;
>3. 注意板级的编译参数请配置到pack-Makefile否则会导致其他pack编译报错.
>
```Makefile
###################################################################
#automatic detection QTOP and LOCALDIR
CUR_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
TRYQTOP := $(shell if [ -n "$$QTOP" ] ; then\
echo $$QTOP;\
else\
cd $(CUR_DIR); while /usr/bin/test ! -d mk ; do \
dir=`cd ../;pwd`; \
if [ "$$dir" = "/" ] ; then \
echo Cannot find QTOP in $(firstword $(MAKEFILE_LIST)) 1>&2; \
exit 1; \
fi ; \
cd $$dir; \
done ; \
pwd; \
fi)
QTOP ?= $(realpath ${TRYQTOP})
ifeq ($(QTOP),)
$(error Please run this in a tree)
endif
LOCALDIR = $(patsubst %/,%,$(subst $(realpath $(QTOP))/,,$(CUR_DIR)))
####################################################################
TREE_LIB_ENABLE=1
lib=
subdirs=
CFGFLAGS += -I${QTOP}/kernel/core/include
CFGFLAGS += -I${QTOP}/kernel/evtdrv/include
include ${QTOP}/mk/generic/Make.tpl
```
### 当前目录进入所有子目录、进入指定目录编译
复制粘贴 以下 Makefile 内容到源码目录 Makefile。
无需修改。
有特别的CFLAG请根据情况配置 `CFGFLAGS`
>注意` subdirs=`为空,默认会进入所有子目录。
> 如果需要指定子目录请给`subdirs`赋值。
>
```Makefile
###################################################################
#automatic detection QTOP and LOCALDIR
CUR_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
TRYQTOP := $(shell if [ -n "$$QTOP" ] ; then\
echo $$QTOP;\
else\
cd $(CUR_DIR); while /usr/bin/test ! -d mk ; do \
dir=`cd ../;pwd`; \
if [ "$$dir" = "/" ] ; then \
echo Cannot find QTOP in $(firstword $(MAKEFILE_LIST)) 1>&2; \
exit 1; \
fi ; \
cd $$dir; \
done ; \
pwd; \
fi)
QTOP ?= $(realpath ${TRYQTOP})
ifeq ($(QTOP),)
$(error Please run this in a tree)
endif
LOCALDIR = $(patsubst %/,%,$(subst $(realpath $(QTOP))/,,$(CUR_DIR)))
####################################################################
TREE_LIB_ENABLE=0
lib=
subdirs=
subdirs= subdir-a subdir-b
include ${QTOP}/mk/generic/Make.tpl
```
### 新增一个 board-pack
参考 `mk/board-pack/`下的各个文件。
board-pack 是对 board 在编译时的一个抽象。
一个board 确定了 MCU arch、工具链、appmain入口把这些编译时参数写成一个bp.xxx。
可以对同一个board 编写多个不同的board-pack以满足同一个board下
选用不通的工具链,编译参数不通,等需求。
## Qmk 的变量
### QTOP 全局变量
标识TencentOS 源码Toplevel目录绝对路径。
命令`git rev-parse --show-toplevel`可以显示。
所有的Makefile都需要QTOP去寻找mk/下的Makefile模板。
### BP 全局变量
选取board-pack`make BP=Linux_Posix`会选取`mk/board-pack/bp.Linux_Posix`
board-pack 确定CC工具链、确定MCU的arch确定board的app源码目录。
### V 调试变量
VERBOSE 输出。编译时,`make V=1` 会打印命令行,用于调试编译过程。
### EEEE 调试变量
CC 编译 .o 文件前,保存预处理文件.i。用于调试宏、头文件包含问题。
## Makefile 节点的关键变量
### TREE_LIB_ENABLE
控制编译时源码的范围。
`TREE_LIB_ENABLE=1`会处理当前目录及其所有子目录的源码。
`TREE_LIB_ENABLE=`只处理当前目录源码。
可以参考`kernel/Makefile`,把整个`kernel/`编译成`libkernel.a`
### CFGFLAGS
给当前目录编译时补充CFLAGS。
会变成CFLAGS的一部分传递给编译器。
### subdirs
`subdirs`控制make 递归进入哪些子目录。
默认值为本目录下所有存在Makefile的子目录集合。
需要进入指定子目录,请给`subdirs`赋值。
### lib
控制.a静态库的名称。默认值为本目录的名称。
## Qmk 后续
3. Kbuild 方向参考Linux-Kernel的Kbuild以及busybox的`Kbuild`