一、构建工具
构建系统也称为组件自动化,自动化构建等。通常需要通过脚本声明构建行为。
构建:源代码-->目标代码(库、可执行文件等)
常见的构建工具:
1. Make(GNU Make、Microsoft NMake、BSD Make): 是最早的构建系统,在类Unix系统上比较常用,但复杂且难以阅读,维护困难。语法类似shell。
2. GNU Autotool(GNU构建系统): GNU构建系统主要是指通过autoconf,automake,libtool构建软件的体系,通常与GNU Make,GCC一起配套使用,这个架构也是所有GNU项目的打包方式
- 使用./config && make && make install完成配置编译和安装
- 问题:基于Make,并没有解决Make本身的问题,复杂阅读困难
3. CMake: 属于元构建系统,用于生成如makefile其他构建系统的构建系统,因此可以跨平台,但本身并不执行构建工作 缺点是自己的一套语言
4. Ninja: 谷歌程序员推出的注重速度的构建工具 特点:简单,文件自动生成,增量构建特别快
二、 Rtthread构建配置系统
2.1 组成
- kconfig--kernel config配置文件(提供系统的配置剪裁功能)
- SCons--构建工具
- env工具--主要提供构建系统所需的各种环境变量以及软件包的管理
2.2 目录结构
lua
-- rtconfig.py ---- 控制SCons构建的配置文件,存放了如工具链,构建参数等配置。
-- SConscript
-- SConstruct ---- SCons的入口脚本,初始化了SCons构建rt-thread所需的必要环境
-- Kconfig ---- 顶层Kconfig文件,menuconfig的入口Kconfig文件
-- rt-thread/
--- src/
---- SConscript ---- 各级源码的scons子脚本,控制当前级别下的源码构建行为
---- Kconfig ---- 各级源码的Kconfig子脚本,存放当前级别下的配置项
---- **.c
三、kconfig:内核配置裁剪
工作机制:
menuconfig-----(遍历解析各级kconfig文件,并保存配置)-----.config-----rtconfig.h
.config文件路径以及内容示意:
rtconfig.h文件路径以及内容示意:
Kconfig文件在源码中呈现树形结构,需要在工程的根目录下存在一份顶层Kconfig文件,顶层Kconfig文件在文件中通过source语句显示地调用各子目录下的Kconfig文件。Env在根目录下执行menuconfig命令后会递归解析各级Kconfig文件,然后提供如下配置界面,完成相应的配置后并保存,根目录下会存在一份.config文件保存当前选择的配置项,并将.config文件转为RT-Thread的系统配置文件rtconfig.h。
脚本语法:
sql
menuconfig GRAVITYXR_MEMORY_BLOCK
select RT_USING_SLAB
bool "Memory Block"
default n
help
Add Memory block support for current system if selected
if GRAVITYXR_MEMORY_BLOCK
config GRAVITYXR_MEMORY_BLOCK_TEST
bool "test"
default n
endif
config语句
- config 表示一个配置选项的开始,紧跟着的 BSP_USING_GPIO 是配置选项的名称,config 下面几行定义了该配置选项的属性。属性可以是该配置选项的
-
- 类型
- 输入提示
- 依赖关系
- 默认值
- 帮助信息
- bool 表示配置选项的类型,每个 config 菜单项都要有类型定义,变量有5种类型
-
- bool 布尔类型
- tristate 三态类型
- string 字符串
- hex 十六进制
- int 整型
- select 是反向依赖关系的意思,即当前配置选项被选中,则 RT_USING_PIN 就会被选中。
- default 表示配置选项的默认值,bool 类型的默认值可以是 y/n。
- help 帮助信息。
menuconfig 语句:
表示带菜单的配置项
- menuconfig 这个语句和 config 语句很相似,但它在 config 的基础上要求所有的子选项作为独立的行显示。
- depends on 表示依赖某个配置选项,
depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA
表示只有当 BSP_USING_UART1 和 RT_SERIAL_USING_DMA 配置选项同时被选中时,当前配置选项的提示信息才会出现,才能设置当前配置选项
menu 语句用于生成菜单。
/gxr/board/Kconfig
csharp
config VEXPRESS_A9
select ARM_A9
default y
bool
menu "Board Support Package"
rsource "drivers/Kconfig"
endmenu #Legacy BSP
隐藏config,避免修改:bool后面空着,这个时候在 menuconfig 中就不会出现该宏定义,但是宏定义还是会有。
menu /endmenu 语句用于生成菜单(类似于生成一个文件夹)
rsourece:读取另一个文件中的 Kconfig 文件
我们找到drivers/kconfig
csharp
menu "Hardware Drivers Config"
config SOC_VEXPRESS_A9
bool
select ARCH_ARM_CORTEX_A9
select RT_USING_CACHE
select ARCH_ARM_MMU
select RT_USING_COMPONENTS_INIT
select RT_USING_USER_MAIN
select RT_USING_GIC_V2
default y
menu "Onboard Peripheral Drivers"
config RT_USING_UART0
bool "Enable UART0"
default y
config RT_USING_UART1
bool "Enable UART1"
default y
endmenu
endmenu
Scons
software construction tool
SCons 是一套由 Python 语言编写的开源构建系统,类似于 GNU Make。它采用不同于通常 Makefile 文件的方式,而是使用 SConstruct 和 SConscript 文件来替代。这些文件也是 Python 脚本,能够使用标准的 Python 语法来编写。所以在 SConstruct、SConscript 文件中可以调用 Python 标准库进行各类复杂的处理,而不局限于 Makefile 设定的规则。
- SConstruct是scons构建的主脚本
- SConscript存放在源代码的子目录下,通常放在项目的子目录,以达到分层构建的目的。一般情况下,每个存放有源代码的子目录下都会放置一个 SConscript。
- tools/building.py:自定义构建接口
特点:
- 自动扫描文件的依赖关系(隐式依赖)
- 使用MD5签名代替传统的文件时间戳
- 使用python脚本,方便使用
- 拓展性强
编译命令:
scons
打开 Env 工具,如果是 ARM 平台的芯片,输入 scons 命令直接编译 BSP,这时候默认使用的是 ARM GCC 编译器,因为 Env 工具带有 ARM GCC 编译器。 如下图所示使用 scons
命令编译 BSP。
非ARM,要自己安装编译器,并且制定路径,例如DSP,可以输入:
ini
set RTT_CC=keil
set RTT_EXEC_PATH=C:/Keilv5
ini
scons -c #清除编译目标。这个命令会清除执行 scons 时生成的临时文件和目标文件。
scons -s #此命令不会打印具体的内部命令。
scons --target=xxx
scons --target=project/evm/qemu-vexpress-a9 -j4 #使用目标路径的qemu编译,-jN表示4个线程同时运行
scons --target=project/evm/qemu-vexpress-a9 --run #运行
SCons官方文档: Current Documentation - SCons
SCons函数
ini
import os
from building import * #只有导入了building模块,才可以使用的RT-Thread自定义Scons函数
cwd = GetCurrentDir() # 获取当前脚本的路径
CPPPATH = [cwd]
src = Glob('*.c') #返回参与构建的对象,对象满足 pattern 模式匹配的列表。(获取当前 Sconscript 所在路径下的所有 .c 文件:)
if GetDepend('GRAVITYXR_MEMORY_BLOCK_TEST'): # 判断是否定义了宏依赖
src += Glob('test/*.c')#把utest也加进去
mb = DefineGroup('mb', src, depend = ['GRAVITYXR_MEMORY_BLOCK'], LOCAL_CPPPATH = CPPPATH)
Return('mb')
DefineGroup(name, src, depend, ** parameters)
定义一个参与构建的 Group ,并作为参与 Scons 构建的对象返回。Group 可以是一个目录(下的文件或子目录),也是后续一些 IDE 工程文件中的一个 Group 或文件夹。
参数 | 描述 |
---|---|
name | Group 的名字 |
src | Group 中包含的文件,一般指的是 C/C++ 源文件。方便起见,也能够通过 Glob 函数采用通配符的方式列出 SConscript 文件所在目录中匹配的文件 |
depend | Group 编译时所依赖的选项(例如 FinSH 组件依赖于 RT_USING_FINSH 宏定义)。编译选项一般指 rtconfig.h 中定义的 RT_USING_xxx 宏。当在 rtconfig.h 配置文件中定义了相应宏时,那么这个 Group 才会被加入到编译环境中进行编译。如果依赖的宏并没在 rtconfig.h 中被定义,那么这个 Group 将不会被加入编译。相类似的,在使用 scons 生成为 IDE 工程文件时,如果依赖的宏未被定义,相应的 Group 也不会在工程文件中出现 |
parameters | 配置其他参数,可取值见下表,实际使用时不需要配置所有参数 |
parameters 可加入的参数:
构建参数 | 意义 |
---|---|
CCFLAGS | C/CPP 源文件公共编译参数 |
CFLAGS | C 源文件独有编译参数 |
CXXFLAGS | CPP 源文件独有编译参数 |
CPPPATH | 头文件路径 |
CPPDEFINES | 编译时添加宏定义,即全局宏定义 |
LIBRARY | 是否将Group构建为静态库 |
env:软件包管理和构建环境
windows:
- ConEmu终端
- Cmeder,DOS系统仿真器,兼容dos原有指令
- pkgs,RT-Thread软件包的命令行工具
- python环境
- MinGW和GCC for ARM工具链等
运行成功: