qmk build system
This commit is contained in:
285
doc/qmk/01. Intro_Qmk_A_Makefile_Framework_For_TencentOS.md
Normal file
285
doc/qmk/01. Intro_Qmk_A_Makefile_Framework_For_TencentOS.md
Normal file
@@ -0,0 +1,285 @@
|
||||
# Qmk(Quick 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。
|
||||
|
||||
不能包含arch,board级别的编译参数。
|
||||
|
||||
|
||||
|
||||
|
||||
## 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、工具链、app(main入口),把这些编译时参数写成一个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`
|
Reference in New Issue
Block a user