01. Intro_Qmk_A_Makefile_Framework_For_TencentOS.md 15.1 KB
Newer Older
J
Jimmy 已提交
1 2 3 4 5 6
# Qmk(Quick Makefile)

## 1. 介绍

### Qmk 是什么

7
[qmk](../../qmk), 是TencentOS的一个Makefile编译框架。
J
Jimmy 已提交
8 9

### Qmk 的特点
J
Jimmy 已提交
10 11 12 13 14
- 使用简单,任意目录均可make,支持帮助`make help`
- 支持Makefile调试,任何 目录`make BP= dm`打印Makefile 的所有变量值。
- 支持编译调试, `make V=1``Make V=2`
- 支持宏扩展调试。`make E=1`
- 目录分离。源码,编译产物目录分离。
J
Jimmy 已提交
15
- 入门简单,新源码目录 Makefile 拷贝即可使用;
J
Jimmy 已提交
16 17 18 19 20 21
- 多架构支持。支持多种 MCU ARCH、多种CC工具链;
- 模板化。多种场景的Makefile拷贝即用;
- 配置化。board-pack提供mcu/arch/bsp等编译时参数、目录的配置;
- 耦合低。跟源码目录结构的耦合低;
- 子目录单独make支持。支持子目录编译.a静态库;

J
Jimmy 已提交
22 23 24 25 26

## TencentOS的make编译
### TencentOS的整体make
```shell
# 进入board目录支持qmk的board
J
Jimmy 已提交
27
cd board/TencentOS_tiny_EVB_MX_Plus/GCC-QMK
J
Jimmy 已提交
28 29 30 31 32 33 34 35

# 本目录编译
make

# 查看帮助
make help
```
TencentOS的整体编译过程是:
J
Jimmy 已提交
36 37 38 39 40 41 42 43
- 先编译静态库

3.`board/`下的顶级Makefile开始,该Makefile 确定了BP 。
3. Makefile 通过 `make -C BP=`访问各个目录,BP用于选择`qmk/board-pack`下的一个`bp.xxx`作为编译参数集合。
3. `make -C BP=` 进入 `arch/` `kernel/` `platform/vendor_bsp`等需要的目录。 
3. make进入各个目录,根据`BP`,生成对应的`.a`静态库,如访问 `arch/`, 生成`libarch.a`,具备编译哪些arch/下的源码文件由`board-pack`确定。
3. make递归访问其他源码目录,目录的`节点Makefile`通过BP渲染`include Make.tpl`模板生成。
3. 依据目录的`节点Makefile`,生成`libxxx.a`
J
Jimmy 已提交
44
3. 各个源码目录节点,依次生成`.a`静态库文件,均位于 `build/`目录下 。
J
Jimmy 已提交
45 46 47 48 49 50 51

- 再链接
3. make 回到 `board/`的顶级Makefile。
3. 需要链接生成`elf`的目录通过`include Make.exec`
3. 编译本目录及其子目录下所有源文件,生成`.o`文件。
3. 根据 `LD_A_FILES``LD_L_LISTS`进行链接。
3. 整体链接完成,生成文件位于`build/`目录下。
J
Jimmy 已提交
52 53 54 55

### TecentOS的子目录make
```shell
# 进入某包含Makefile的目录
J
Jimmy 已提交
56
cd kernel/
J
Jimmy 已提交
57

J
Jimmy 已提交
58
# 本目录编译,使用Linux_Posix作为Board-Pack 
J
Jimmy 已提交
59
make BP=Linux_Posix
J
Jimmy 已提交
60 61
# 本目录编译,使用TencentOS_tiny_EVB_MX_Plus作为Board-Pack 
make BP=TencentOS_tiny_EVB_MX_Plus
J
Jimmy 已提交
62 63 64 65 66 67

# 查看帮助
make help
```
单目录的编译过程是:
3. make访问本目录,读取本目录Makefile,根据命令行`make BP=xxx`的BP,选择`mk/board-pack`
J
Jimmy 已提交
68
3. 根据BP选择的构建参数。
J
Jimmy 已提交
69 70 71 72 73
3. 使用ar进行打包,.a 文件放在`build/`目录。
3. 构建完成。

## Qmk 的概念
### generic-Makefile(mk/generic)
J
Jimmy 已提交
74
`qmk/generic/Make.tpl` 属于这类。
J
Jimmy 已提交
75 76
又称全局通用型Makefile模板。位于 `mk/generic)`

J
Jimmy 已提交
77 78
要求对所有board、所有gcc-toolchain、cpu、arch、bsp适用。
所以一般只包含通用的规则。
J
Jimmy 已提交
79

J
Jimmy 已提交
80 81 82 83 84 85 86 87 88 89
| 模板文件     |说明| 
| :--------   |:------|
|[Make.tpl](../../qmk/generic/Make.tpl)      | 一个目录或者多个目录编译成`.a`的通用模板 | 
|[Make.exec](../../qmk/generic/Make.exec)     | 多个`.a`链接成 `elf`,生成`.bin`的通用模板 | 
|[Make.lib](../../qmk/generic/Make.lib)      | 处理多个`.o`生成`.a`的通用模板| 
|[Make.subdirs](../../qmk/generic/Make.subdirs)  | 处理 make递归进入多个subdir make的通用模板| 
|[Make.depend](../../qmk/generic/Make.depend)   | 处理 一个`.o`依赖多个`.h`,的规则模板 | 
|[Make.debug](../../qmk/generic/Make.debug)    | 用于调试Makefile的模板| 
|[Make.tools](../../qmk/generic/Make.debug)   | 用于屏蔽在多种OS使用qmk,sed、等基础shell/cli命令路径不同 | 

J
Jimmy 已提交
90

J
Jimmy 已提交
91 92
### boardpack-Makefile(mk/board-pack)
`board-pack/bp.TencentOS_tiny_EVB_MX_Plus` 属于这类。
J
Jimmy 已提交
93

J
Jimmy 已提交
94
又称板级Makefile模板。是一个硬件产品工程开发过程中在编译时的参数抽象文件。
J
Jimmy 已提交
95

J
Jimmy 已提交
96
位于mk/board-pack 的 bp.${BP},属于board配置型Makefile,需要确定工具链,mcu,arch、board、bsp等方面的编译时参数集合。
J
Jimmy 已提交
97 98 99
嵌入式应用开发工程师主要修改这部分Makefile。


J
Jimmy 已提交
100 101 102
### srctree-Makefile
`kernel/Makefile` `arch/Makefile` 都属于这类。
又称节点Makefile,位于各个源码目录的 Makefile。多个board都适用的Makefile,属于源码节点配置型Makefile。
J
Jimmy 已提交
103 104 105 106



不能包含arch,board级别的编译参数。
J
Jimmy 已提交
107 108
### link-Makefile
`board/TencentOS_tiny_EVB_MX_Plus/GCC-QMK/app_tencent_os_mqtt/Makefile` 属于这类。
J
Jimmy 已提交
109 110 111 112 113 114



## Qmk 的使用

### 当前目录所有.c,编译成一个.a库
J
Jimmy 已提交
115
`这类Makefile编写参考 osal/posix/Makefile`
J
Jimmy 已提交
116 117 118 119 120 121
复制粘贴 以下 Makefile 内容到源码目录 Makefile。
无需修改。
>
>3. 注意`TREE_LIB_ENABLE=0`,,cc和ar时,只搜索当前目录源码,不包含子目录;
>
>3. 注意`lib=`,表示链接后的库名使用目录名;
J
Jimmy 已提交
122
>3. 有特别的CFLAG请根据情况配置 `CFGFLAGS`。
J
Jimmy 已提交
123 124
>3. 注意板级的编译参数请配置到pack-Makefile,否则会导致其他pack编译报错.

J
Jimmy 已提交
125

J
Jimmy 已提交
126 127 128
```Makefile
###################################################################
#automatic detection QTOP and LOCALDIR
J
Jimmy 已提交
129
CUR_DIR := $(patsubst %/,%,$(dir $(realpath $(firstword $(MAKEFILE_LIST)))))
J
Jimmy 已提交
130 131 132
TRYQTOP := $(shell if [ -n "$$QTOP" ] ; then\
        echo $$QTOP;\
        else\
J
Jimmy 已提交
133
        cd $(CUR_DIR); while /usr/bin/test ! -d qmk ; do \
J
Jimmy 已提交
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
        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=

J
Jimmy 已提交
157
CFGFLAGS += -I$(CUR_DIR)/include
J
Jimmy 已提交
158

J
Jimmy 已提交
159
include ${QTOP}/qmk/generic/Make.tpl
J
Jimmy 已提交
160 161 162 163

```

### 某目录及其子目录的所有.c,编译成一个.a库
J
Jimmy 已提交
164
`这类Makefile编写参考 kernel/Makefile`
J
Jimmy 已提交
165 166 167 168 169 170 171 172 173 174
复制粘贴 以下 Makefile 内容到源码目录 Makefile。
无需修改。
有特别的CFLAG请根据情况配置 `CFGFLAGS`
>
>3. 注意`TREE_LIB_ENABLE=1`,cc和ar时,会递归搜索源码,包含当前目录及其子目录。
>
>3. 注意`lib=`,表示链接后的库名使用目录名;
>3. 注意板级的编译参数请配置到pack-Makefile,否则会导致其他pack编译报错.
>

J
Jimmy 已提交
175

J
Jimmy 已提交
176 177 178
```Makefile
###################################################################
#automatic detection QTOP and LOCALDIR
J
Jimmy 已提交
179
CUR_DIR := $(patsubst %/,%,$(dir $(realpath $(firstword $(MAKEFILE_LIST)))))
J
Jimmy 已提交
180 181 182
TRYQTOP := $(shell if [ -n "$$QTOP" ] ; then\
        echo $$QTOP;\
        else\
J
Jimmy 已提交
183
        cd $(CUR_DIR); while /usr/bin/test ! -d qmk ; do \
J
Jimmy 已提交
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
        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
J
Jimmy 已提交
209 210
CFGFLAGS += -I${QTOP}/kernel/hal/include
CFGFLAGS += -I${QTOP}/kernel/pm/include
J
Jimmy 已提交
211

J
Jimmy 已提交
212
include ${QTOP}/qmk/generic/Make.tpl
J
Jimmy 已提交
213 214 215 216
```


### 当前目录进入所有子目录、进入指定目录编译
J
Jimmy 已提交
217
`这类Makefile编写参考 platform/Makefile`
J
Jimmy 已提交
218 219 220 221 222 223 224 225 226 227
复制粘贴 以下 Makefile 内容到源码目录 Makefile。
无需修改。
有特别的CFLAG请根据情况配置 `CFGFLAGS`
>注意` subdirs=`为空,默认会进入所有子目录。
> 如果需要指定子目录请给`subdirs`赋值。
>

```Makefile
###################################################################
#automatic detection QTOP and LOCALDIR
J
Jimmy 已提交
228
CUR_DIR := $(patsubst %/,%,$(dir $(realpath $(firstword $(MAKEFILE_LIST)))))
J
Jimmy 已提交
229 230 231
TRYQTOP := $(shell if [ -n "$$QTOP" ] ; then\
        echo $$QTOP;\
        else\
J
Jimmy 已提交
232
        cd $(CUR_DIR); while /usr/bin/test ! -e qmk ; do \
J
Jimmy 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
        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=


J
Jimmy 已提交
256
include ${QTOP}/qmk/generic/Make.tpl
J
Jimmy 已提交
257

J
Jimmy 已提交
258
```
J
Jimmy 已提交
259

J
Jimmy 已提交
260
### 新增一个 board-pack,支持新的board
J
Jimmy 已提交
261

J
Jimmy 已提交
262
参考 `mk/board-pack/`下的各个文件。
J
Jimmy 已提交
263

J
Jimmy 已提交
264
参考 `qmk/board-pack/bp.TencentOS_tiny_EVB_MX_Plus`
J
Jimmy 已提交
265

J
Jimmy 已提交
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
board-pack 是对 board 在编译时的一个抽象。
一个board 确定了 MCU、 arch、工具链,把这些编译时参数写成一个bp.xxx。

新整一个board-pack的步骤:
- qmk/board-pack/目录下,新建一个bp.xxx.
- 在bp.xxx定义以下变量:

     注意 CFGFLAGS 需要包括 cpu、arch、board 等类型的FLAG。  
     赋值建议用`+=`,不允许用 `:=`。注意 可以引用`QTOP`,`BLDROOT`变量,不建议引用其他`qmk/generic/`模板的变量。

| Makefile变量名     | 变量赋值举例    | 变量说明           | 
| :--------  | ------ | :--------------------- | 
| CROSS_COMPILE  | CROSS_COMPILE =arm-none-eabi-   | 工具链前缀         | 
| CC             | CC       = $(CROSS_COMPILE)gcc  | 工具链             | 
| CXX            | CXX      = $(CROSS_COMPILE)g++  | 工具链             | 
| LD             | LD       = $(CROSS_COMPILE)ld   | 工具链             | 
| ARFLAGS        | ARFLAGS  = -rc                  | 工具链             | 
| STRIP          | STRIP    = $(CROSS_COMPILE)strip| 工具链             | 
| CFGFLAGS   | 参考`bp.TencentOS_tiny_EVB_MX_Plus` | 对CFLAGS、CXXFLAGS 进行增加             | 
| ARCH_LSRCS | 参考`bp.TencentOS_tiny_EVB_MX_Plus` | board-pack对应的arch/源码,`make -C arch/时需要编译的源码,绝对路径,或相对于QTOP的相对路径 | 
| BSP_LSRCS  | 参考`bp.TencentOS_tiny_EVB_MX_Plus` | board-pack对应的board/bsp源码           | 
| PLATFORM_VENDOR_BSP_LSRCS | 参考`bp.TencentOS_tiny_EVB_MX_Plus` | board-pack对应的vendor_bsp 源码,`make -C platform/vendor_bsp时需要编译的源码              | 
| PLATFORM_VENDOR_BSP_LSRCS | 参考`bp.TencentOS_tiny_EVB_MX_Plus` | board-pack对应的vendor_bsp 源码,`make -C platform/vendor_bsp时需要编译的源码              | 
| PLATFORM_HAL_LSRCS | 参考`bp.TencentOS_tiny_EVB_MX_Plus` |  board-pack对应的 hal 源码,`make -C platform/hal时             | 

## Qmk 的模板的内置变量

| 变量名     |赋值| 变量值说明   | 值举例   |
| :-------- |:------|:------ |:------- |
|AR     |bp中赋值| 工具链 | "arm-none-eabi-ar"|
|ARCH_LSRCS|bp中赋值| 进入arch/需要编译的源码,绝对路径或相对于QTOP的源码路径 | "/root/democode/TencentOS-tiny/arch/arm/arm-v7m/cortex-m4/gcc/port_c.c  /root/democode/TencentOS-tiny/arch/arm/arm-v7m/cortex-m4/gcc/port_s.S /root/democode/TencentOS-tiny/arch/arm/arm-v7m/common/tos_fault.c /root/democode/TencentOS-tiny/arch/arm/arm-v7m/common/tos_cpu.c   /root/democode/TencentOS-tiny/arch/arm/arm-v7m/cortex-m4/gcc/port_c.c  /root/democode/TencentOS-tiny/arch/arm/arm-v7m/cortex-m4/gcc/port_s.S /root/democode/TencentOS-tiny/arch/arm/arm-v7m/common/tos_fault.c /root/democode/TencentOS-tiny/arch/arm/arm-v7m/common/tos_cpu.c  "|
|ARFLAGS   |bp中赋值  | 工具链参数|ar 参数,含义见`ar --help`| "-rc"|
|BLDDIR    |禁止赋值|标识.o等编译产物所在的目录,跟源码LOCALDIR有关| "/root/democode/TencentOS-tiny/build/TencentOS_tiny_EVB_MX_Plus.arm-none-eabi-gcc.tos/arch"|
|BLDROOT   |禁止赋值  | 标识编译产物位置目录。| "/root/democode/TencentOS-tiny/build/TencentOS_tiny_EVB_MX_Plus.arm-none-eabi-gcc.tos"|
|BLD_SUFFIX|禁止赋值 |编译产物位置目录的后缀名 | | ".tos"|
|BOBJS     |禁止赋值 | 所有OBJ集合,绝对路径 | "/root/democode/TencentOS-tiny/build/TencentOS_tiny_EVB_MX_Plus.arm-none-eabi-gcc.tos/arch/arm/arm-v7m/cortex-m4/gcc/port_c.o /root/democode/TencentOS-tiny/build/TencentOS_tiny_EVB_MX_Plus.arm-none-eabi-gcc.tos/arch/arm/arm-v7m/cortex-m4/gcc/port_s.o /root/democode/TencentOS-tiny/build/TencentOS_tiny_EVB_MX_Plus.arm-none-eabi-gcc.tos/arch/arm/arm-v7m/common/tos_fault.o /root/democode/TencentOS-tiny/build/TencentOS_tiny_EVB_MX_Plus.arm-none-eabi-gcc.tos/arch/arm/arm-v7m/common/tos_cpu.o"|
|CC     | bp中赋值 |"arm-none-eabi-gcc"|
|CROSS_COMPILE     | 工具链 | "arm-none-eabi-"|
|CURDIR     |禁止赋值|标识当前Makefile 所在的目录  | "/root/democode/TencentOS-tiny/arch"|
|CUR_DIR    |禁止赋值|标识当前Makefile 所在的目录  | "/root/democode/TencentOS-tiny/arch"|
|CUR_MK_NODE_DIR |禁止赋值|标识当前Makefile 所在的目录  | "/root/democode/TencentOS-tiny/arch"|
|CXX     |bp中赋值| "arm-none-eabi-g++"|
|LD     |bp中赋值| "arm-none-eabi-ld"|
|LDFLAGS    |bp中赋值 | "    "|
|LOBJS     |禁止赋值|OBJ文件集合,相对路径,相对于当前Makefile目录 | "arm/arm-v7m/cortex-m4/gcc/port_c.o arm/arm-v7m/cortex-m4/gcc/port_s.o arm/arm-v7m/common/tos_fault.o arm/arm-v7m/common/tos_cpu.o"|
|LOCALDIR  |禁止赋值|源码目录位置,相对路径,相对于QTOP  | "arch"|
|LSRCS    |禁止在bp中赋值,可以在src-Makefile赋值|编译源代码文件集合,相对路径,相对于当前Makefile目录,或者绝对路径 | "arm/arm-v7m/cortex-m4/gcc/port_c.c  arm/arm-v7m/cortex-m4/gcc/port_s.S arm/arm-v7m/common/tos_fault.c arm/arm-v7m/common/tos_cpu.c  "|
|QTOP     |禁止赋值|源码一级目录| "/root/democode/TencentOS-tiny"|
|RANLIB    |bp中赋值 | "arm-none-eabi-ranlib"|
|STRIP     |bp中赋值| "arm-none-eabi-strip"|
|TREE_LIB_ENABLE |src-Makefile赋值,非0 表示编译所有子目录源码| LSRCS是否把子目录源码    | "0"|
|lib     |不建议赋值|`.a`库名变量,默认目录名| "libarch"|
|targetlib |禁止赋值| "/root/democode/TencentOS-tiny/build/TencentOS_tiny_EVB_MX_Plus.arm-none-eabi-gcc.tos/libarch.a"|


## qmk的 make 命令行参数
J
Jimmy 已提交
322
```shell
J
Jimmy 已提交
323 324 325
make help
```
### make V=1 E=1
J
Jimmy 已提交
326
```shell
J
Jimmy 已提交
327 328 329 330 331
# verbose打印编译时的命令
make V=1 
# 调试头文件包含,宏扩展时很有用,会在生成`.o`文件的同时生成`.i`预处理文件
make E=1
```
J
Jimmy 已提交
332
```shell
J
Jimmy 已提交
333 334 335 336
# verbose打印链接时的库搜索过程
make V=2
make V=3
```
J
Jimmy 已提交
337
## 调试Makefile 
J
Jimmy 已提交
338
```shell
J
Jimmy 已提交
339 340 341
#进入含Makefile的目录
make BP=TencentOS_tiny_EVB_MX_Plus dm
```
J
Jimmy 已提交
342

J
Jimmy 已提交
343

J
Jimmy 已提交
344
## Qmk 后续