diff --git a/development-tools/_sidebar.md b/development-tools/_sidebar.md index 09dfd6d69f72b1f94811056b7bd32adc681d2209..701157fe56cf43492db85eafa152e8a846672fa6 100644 --- a/development-tools/_sidebar.md +++ b/development-tools/_sidebar.md @@ -25,10 +25,10 @@ - [精彩博客推荐](/development-tools/rtthread-studio/applications/user-blog/user-blog.md) - [常见问题](/development-tools/rtthread-studio/faq/studio-faq.md) - [更新日志](/development-tools/rtthread-studio/changelog/changelog.md) - + +- RT-Thread构建与配置系统 + - [简述](/development-tools/build-config-system/summary.md) + - [Kconfig](/development-tools/build-config-system/Kconfig.md) + - [SCons](/development-tools/build-config-system/SCons.md) - Env 开发工具 - - [Env 用户手册](/development-tools/env/env.md) -- Scons 介绍 - - [Scons 构建工具](/development-tools/scons/scons.md) -- Kconfig 介绍 - - [Kconfig 语法](/development-tools/kconfig/kconfig.md) + - [Env 用户手册](/development-tools/env/env.md) \ No newline at end of file diff --git a/development-tools/kconfig/kconfig.md b/development-tools/build-config-system/Kconfig.md similarity index 72% rename from development-tools/kconfig/kconfig.md rename to development-tools/build-config-system/Kconfig.md index 9ff186c20e1d62f944eea2be3c2975ec51fab3a1..520b8ee22320aba68ab6944fc84f27cbba1aad1f 100644 --- a/development-tools/kconfig/kconfig.md +++ b/development-tools/build-config-system/Kconfig.md @@ -1,30 +1,56 @@ -# Kconfig 语法 +# Kconfig -## Kconfig 简介 +## Kconfig在RT-Thread中的工作机制 -RT-Thread 借助 Kconfig 文件生成的配置文件 rtconfig.h 来配置系统,Kconfig 文件是各种配置界面的源文件。当在 bsp 目录下使用 env 工具执行 menuconfig 命令时会出现 RT-Thread 系统的配置界面,所有配置工具都是通过读取当前 bsp 目录下的 Kconfig 文件来生成配置界面的,这个文件就是所有配置的总入口,它会包含其他目录的 Kconfig 文件。配置工具读取各个 Kconfig 文件,生成配置界面供开发人员配置系统,最终生成 RT-Thread 系统的配置文件 rtconfig.h。 +C语言项目的裁剪配置本质上通过条件编译和宏的展开来实现的,RT-Thread借助Kconfig这套机制更方便的实现了这一功能。当前以Windows下Env工具中的使用为例,简述Kconfig在RT-Thread的工作机制。 -## Kconfig 基本语法 +Kconfig机制包括了Kconfig文件和配置UI界面(如menuconfig,pyconfig等)。Kconfig机制有如下特点: -### 如何学习 Kconfig +- Kconfig文件中的配置项会映射至rtconfig.h中 +- Kconfig文件可以随源码分散至各级子目录,便于灵活修改。 -Kconfig 是 Linux 使用的一种配置系统,可以参见[Kconfig 官方文档](https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt)。也可以在搜索引擎搜索 Kconfig 相关知识,这个是通用的。学习时,不必追求把 Kconfig 从头到尾学一遍,用到哪个学哪个即可。下面列举了在 RT-Thread 中常用的一些 Kconfig 语法结构。 +```Ini +# .config片段 +CONFIG_RT_USING_TIMER_SOFT=y +CONFIG_RT_TIMER_THREAD_PRIO=4 +CONFIG_RT_TIMER_THREAD_STACK_SIZE=512 +CONFIG_RT_DEBUG=y + +``` + +```C +// 相对应的rtconfig.h片段 +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 512 +#define RT_DEBUG +``` + +![构建配置系统](./figures/buildconfig2.png) + +Kconfig文件在源码中呈现树形结构,需要**在工程的根目录下存在一份顶层Kconfig文件**,顶层Kconfig文件在文件中通过source语句显示地调用各子目录下的Kconfig文件。Env在根目录下执行menuconfig命令后会递归解析各级Kconfig文件,然后提供如下配置界面,完成相应的配置后并保存,根目录下会存在一份.config文件保存当前选择的配置项,并将.config文件转为RT-Thread的系统配置文件rtconfig.h。 + +![构建配置系统](./figures/buildconfig3.png) + +## Kconfig语法及示例 + +Kconfig源于[Linux内核的配置构建系统](https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html#),当前只介绍RT-Thread中的常用语法。 ### 注释 Kconfig 采用 `#` 作为注释标记符,例如: -```Kconfig +```C # This is a comment ``` -### config 语句 +### config语句 config 定义了一组新的配置选项 以下为 RT-Thread 系统中 config 语句的示例 -```c +```C config BSP_USING_GPIO bool "Enable GPIO" select RT_USING_PIN @@ -35,66 +61,66 @@ config BSP_USING_GPIO 以上代码对应的配置界面如下所示 -![config](figures/config.png) +![构建配置系统](./figures/buildconfig4.png) 对应的帮助信息界面如下所示 -![help](figures/help.png) +![构建配置系统](./figures/buildconfig5.png) 语句分析: -- config 表示一个配置选项的开始,紧跟着的 BSP_USING_GPIO 是配置选项的名称,config 下面几行定义了该配置选项的属性。属性可以是该配置选项的 - - 类型 - - 输入提示 - - 依赖关系 - - 默认值 - - 帮助信息 +- config 表示一个配置选项的开始,紧跟着的 BSP_USING_GPIO 是配置选项的名称,config 下面几行定义了该配置选项的属性。属性可以是该配置选项的 + - 类型 + - 输入提示 + - 依赖关系 + - 默认值 + - 帮助信息 - bool 表示配置选项的类型,每个 config 菜单项都要有类型定义,变量有5种类型 - - bool 布尔类型 - - tristate 三态类型 - - string 字符串 - - hex 十六进制 - - int 整型 + - bool 布尔类型 + - tristate 三态类型 + - string 字符串 + - hex 十六进制 + - int 整型 - select 是反向依赖关系的意思,即当前配置选项被选中,则 RT_USING_PIN 就会被选中。 - default 表示配置选项的默认值,bool 类型的默认值可以是 y/n。 - help 帮助信息。 通过 env 选中以上配置界面的选项后,最终可在 rtconfig.h 文件中生成如下两个宏 -```c +```C #define RT_USING_PIN #define BSP_USING_GPIO ``` ### 变量类型 -#### bool 类型 +#### bool类型 布尔类型变量的取值范围是 y/n ,其使用示例如下 -```c + +```C config BSP_USING_WDT bool "Enable Watchdog Timer" select RT_USING_WDT default n ``` - 上述语句对应的配置界面如下所示 -![bool](figures/bool.png) +![构建配置系统](./figures/buildconfig6.png) 以上配置项在 rtconfig.h 文件中生成的宏如下所示 -```c +```C #define BSP_USING_WDT #define RT_USING_WDT ``` -#### string 类型 +#### string类型 字符串变量的默认值是一个字符串,其使用示例如下 -```c +```C config RT_CONSOLE_DEVICE_NAME string "the device name for console" default "uart1" @@ -102,19 +128,19 @@ config RT_CONSOLE_DEVICE_NAME 上述语句对应的配置界面如下所示 -![string](figures/string.png) +![构建配置系统](./figures/buildconfig7.png) 以上配置项在 rtconfig.h 文件中生成的宏如下所示 -```c +```C #define RT_CONSOLE_DEVICE_NAME "uart1" ``` -#### int 类型 +#### int类型 整型变量的取值范围是一个整型的数,其使用示例如下 -```c +```C config BSP_I2C1_SCL_PIN int "I2C1 scl pin number" range 1 176 @@ -123,32 +149,29 @@ config BSP_I2C1_SCL_PIN 上述语句对应的配置界面如下所示 -![int](figures/int.png) +![构建配置系统](./figures/buildconfig8.png) 以上配置项在 rtconfig.h 文件中生成的宏如下所示 -```c +```C #define BSP_I2C1_SCL_PIN 116 ``` - -#### hex 类型 +#### hex类型 十六进制类型变量的取值范围是一个十六进制的数,其使用方法和整型变量用法一致,整型变量生成的是十进制的数,而十六进制生成的是十六进制的数。 - -#### tristate 类型 +#### tristate类型 三态类型变量的取值范围是 y、n 和 m。tristate 代表在内核中有三种状态,一种是不选中,一种是选中直接编译进内核,还有一种是 m 手动添加驱动,而布尔类型变量只有两种状态,即选中和不选中。其使用方法和布尔类型变量类似。 - -### menu/endmenu 语句 +### menu/endmenu语句 menu 语句用于生成菜单。 以下为 RT-Thread 系统中 menu/endmenu 语句的示例 -```c +```C menu "Hardware Drivers Config" config BSP_USING_COM2 bool "Enable COM2 (uart2 pin conflict with Ethernet and PWM)" @@ -160,20 +183,19 @@ menu "Hardware Drivers Config" select BSP_USING_UART3 default n endmenu - ``` + menu 之后的字符串是菜单名。menu 和 endmenu 间有很多 config 语句,以上代码对应的配置界面如下所示 -![menu1](figures/menu1.png) +![构建配置系统](./figures/buildconfig9.png) 其中 Hardware Drivers Config 就是菜单名,然后进入这个菜单有 Enable COM2、Enable COM3 等选项,如下图所示 -![menu](figures/menu.png) - +![构建配置系统](./figures/buildconfig10.png) 通过 env 选中以上配置界面的所有选项后,最终可在 rtconfig.h 文件中生成如下五个宏 -```c +```C #define BSP_USING_UART #define BSP_USING_UART2 #define BSP_USING_UART3 @@ -181,11 +203,11 @@ menu 之后的字符串是菜单名。menu 和 endmenu 间有很多 config 语 #define BSP_USING_COM3 ``` -### if/endif 语句 +### if/endif语句 if/endif 语句是一个条件判断,定义了一个 if 结构,示例代码如下 -```c +```C menu "Hardware Drivers Config" menuconfig BSP_USING_CAN bool "Enable CAN" @@ -201,22 +223,23 @@ endmenu 当没有选中 "Enable CAN" 选项时,下面通过 if 判断的 Enable CAN1 选项并不会显示出来,如下图所示 -![if0](figures/if0.png) -![if1](figures/if1.png) +![构建配置系统](./figures/buildconfig11.png) -当上一级菜单选中 "Enable CAN" 时 +![构建配置系统](./figures/buildconfig12.png) +当上一级菜单选中 "Enable CAN" 时 -![if11](figures/if11.png) -![if2](figures/if2.png) +![构建配置系统](./figures/buildconfig13.png) +![构建配置系统](./figures/buildconfig14.png) -### menuconfig 语句 +### menuconfig语句 menuconfig 语句表示带菜单的配置项 以下为 RT-Thread 系统 menuconfig 语句的示例 -```c + +```C menu "Hardware Drivers Config" menuconfig BSP_USING_UART bool "Enable UART" @@ -237,19 +260,20 @@ endmenu 当没有打开串口 DMA 配置时,以上代码对应的界面为 -![menuconfig1](figures/menuconfig1.png) +![构建配置系统](./figures/buildconfig15.png) 当打开串口 DMA 配置时,以上代码对应的界面为 -![menuconfig2](figures/menuconfig2.png) +![构建配置系统](./figures/buildconfig16.png) 语句分析: + - menuconfig 这个语句和 config 语句很相似,但它在 config 的基础上要求所有的子选项作为独立的行显示。 - depends on 表示依赖某个配置选项,`depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA` 表示只有当 BSP_USING_UART1 和 RT_SERIAL_USING_DMA 配置选项同时被选中时,当前配置选项的提示信息才会出现,才能设置当前配置选项 通过 env 选中以上配置界面的所有选项后,最终可在 rtconfig.h 文件中生成如下五个宏 -```c +```C #define RT_USING_SERIAL #define BSP_USING_UART #define BSP_USING_UART1 @@ -257,12 +281,13 @@ endmenu #define BSP_UART1_RX_USING_DMA ``` -### choice/endchoice 语句 +### choice/endchoice语句 choice 语句将多个类似的配置选项组合在一起,供用户选择一组配置项 RT-Thread Kconfig 文件中 choice 代码示例如下 -```c + +```C menu "Hardware Drivers Config" menuconfig BSP_USING_ONCHIP_RTC bool "Enable RTC" @@ -283,29 +308,30 @@ menu "Hardware Drivers Config" endif endmenu ``` + 以上代码对应的配置界面为 -![choice](figures/choice.png) +![构建配置系统](./figures/buildconfig17.png) 语句解析: + - choice/endchoice 给出选择项,中间可以定义多个配置项供选择,但是在配置界面只能选择一个配置项; - prompt 给出提示信息,光标选中后回车进入就可以看到多个 config 条目定义的配置选项,所以下面的两个例子是等价的: - ``` Kconfig - bool "Networking support" - ``` - - ``` Kconfig - bool - prompt "Networking support" - ``` +```C +bool "Networking support" + +bool +prompt "Networking support" +``` -### comment 语句 +### comment语句 comment 语句出现在界面的第一行,用于定义一些提示信息。 comment 代码示例如下 -```c + +```C menu "Hardware Drivers Config" comment "uart2 pin conflict with Ethernet and PWM" config BSP_USING_COM2 @@ -318,34 +344,36 @@ endmenu 以上代码对应的配置界面为 -![comment](figures/comment.png) +![构建配置系统](./figures/buildconfig18.png) -### source 语句 +### source语句 source 语句用于读取另一个文件中的 Kconfig 文件,如: -```c +```C source "../libraries/HAL_Drivers/Kconfig" + ``` 上述语句用于读取当前 Kconfig 文件所在路径的上一级文件夹 libraries/HAL_Drivers 下的 Kconfig 文件。 ## FAQ -### 如何在 menuconfig 隐藏一些 config +### 如何在menuconfig隐藏一些config Kconfig中有个特殊的用法,在制作大型软件包的时候会遇到,就是有一些宏定义是不愿意让客户在 menuconfig 中进行修改的,但是又是相关开源软件包中必须要包含的,而且数目也比较众多的,对 Kconfig 一些选项有一些依赖的,也就是不希望该配置选项出现在 menuconfig 中。 下面以 Kconfig 举例说明: -```c +```C config BSP_USING_GPIO bool "Enable GPIO" default y ``` 将上述语句中的 `bool` 后面的注释去掉。 -```c + +```C config BSP_USING_GPIO bool default y @@ -353,11 +381,11 @@ config BSP_USING_GPIO 这个时候在 menuconfig 中就不会出现该宏定义,但是宏定义还是会有 -### depends on 和 select 语句的区别 +### depends on和select语句的区别 例如,如下配置 -```c +```C config BSP_USING_UART3 bool "UART3 config" depends on BSP_USING_UART @@ -374,13 +402,13 @@ depends和select都需要注意的是:depends 和 select 后面的宏定义必 - select:开启 BSP_USING_UART3 需要依赖 RT_USING_SERIAL,RT_USING_SERIAL 功能会被自动选定; - depends on:在 BSP_USING_UART 已经选定的情况下,系统会**显示** BSP_USING_UART3 的配置菜单选项,至于 BSP_USING_UART3 默认是否被选定,取决于 default 。 -### depends on 高级用法 +### [depends on 高级用法](https://download.rt-thread.org/ci-agent/artifacts/113728/309584/artifacts/docs-online/#/development-tools/kconfig/kconfig?id=depends-on-高级用法) depends on可以以一定的逻辑 “depends” 多个条件,具体写法如下: -```c +```C config BSP_USING_UART3 depends on RT_USNING_A || !RT_USNING_B ``` -这句话表示的是UART3串口会在 RT_USNING_A 选定或者 RT_USNING_B 不选定的情况下,显示 BSP_USING_UART3 的配置菜单选项,默认为不选状态。 +这句话表示的是UART3串口会在 RT_USNING_A 选定或者 RT_USNING_B 不选定的情况下,显示 BSP_USING_UART3 的配置菜单选项,默认为不选状态。 \ No newline at end of file diff --git a/development-tools/build-config-system/SCons.md b/development-tools/build-config-system/SCons.md new file mode 100644 index 0000000000000000000000000000000000000000..f63d6d40fd6b0915d494d36a1cd28ddcb9d10dc9 --- /dev/null +++ b/development-tools/build-config-system/SCons.md @@ -0,0 +1,143 @@ +# SCons + +## 什么是构建工具 + +构建工具 (software construction tool) 是一种软件,它根据脚本中的规则和指令,将源文件构建成为目标文件。著名的构建工具如:GNU Make,CMake, SCons等。由于Make存在一些已知的问题,如跨平台不友好等,RT-Thread选择了SCons作为构建工具。 + +## RT-Thread 构建工具 + +RT-Thread 早期使用 Make/Makefile 构建。从 0.3.x 开始,RT-Thread 开发团队逐渐引入了 SCons 构建系统,引入 SCons 唯一的目是:使大家从复杂的 Makefile 配置、IDE 配置中脱离出来,把精力集中在 RT-Thread 功能开发上。 + +有些读者可能会有些疑惑,这里介绍的构建工具与 IDE 有什么不同呢?IDE 通过图形化界面的操作来完成构建。大部分 IDE 会根据用户所添加的源码生成类似 Makefile 或 SConscript 的脚本文件,在底层调用类似 Make 或 SCons 的工具来构建源码。 + +## SCons简介 + +SCons是一个用python编写的构建工具,使用python脚本作为软件构件的“配置文件”。与Fabric 等命令自动化工具不同(需要指定执行的操作),SCons在python脚本中指定构建的内容(如文件或目录),由SCons来确定需要执行哪些操作。 + +## SCons脚本指南 + +#### RT-Thread SCons 脚本结构 + +```Markdown +/ + -- rtconfig.py ---- 控制SCons构建的配置文件,存放了如工具链,构建参数等配置。 + -- SConscript + -- SConstruct ---- SCons的入口脚本,初始化了SCons构建rt-thread所需的必要环境 + -- Kconfig ---- 顶层Kconfig文件,menuconfig的入口Kconfig文件 + -- rt-thread/ + --- src/ + ---- SConscript ---- 各级源码的scons子脚本,控制当前级别下的源码构建行为 + ---- Kconfig ---- 各级源码的Kconfig子脚本,存放当前级别下的配置项 + ---- **.c + +``` + +如上图所示:为了方便开发者使用SCons,RT-Thread搭建了如图所示的构建框架,其中包括了一份SCons的入口脚本(SConstruct),以及分散在各级源码的SCons子脚本(SConscript),还有一份便于配置构建行为的配置脚本(rtconfig.py)同时,RT-Thread也在SCons标准接口的基础上,提供了一组用于组织源码工程的扩展接口。开发者在使用时,可以借助RT-Thread提供的扩展接口,更方便的完成源码的组织与配置。 + +![构建配置系统](./figures/buildconfig19.png) + +### SCons常用标准接口 + +|函数|作用| +|-|-| +|**Import**(vars)|导入其他脚本定义的vars| +|**Export**(vars)|导出vars,以供Import函数在其他scons脚本使用| +|**SConscript**(scripts, [exports, variant_dir, duplicate])|导入SConscript,返回此脚本指定的参与构建的对象
参数:
scripts:导入的SConscript,路径+名称
exports:导出一个变量(可选)
variant_dir:指定构建产物的生成路径(可选)
duplicate:执行构建的目录中是否拷贝源码(可选)| +|**Glob**(pattern)|返回参与构建的对象,对象满足pattern模式匹配的列表| +|**IsDefined**(depend)|判断宏是否被定义
参数:
depend:宏或宏列表
返回值:已定义为True,否则为False| +|**Split(str)**|将字符串 str 分割成一个列表。| + +### RT-Thread拓展函数 + +|函数|作用| +|-|-| +|SrcRemove(src, remove)|从构建列表中移除源文件
参数:
src:构建列表
remove:移除的源文件列表| +|DefineGroup(name, src, depend, **parameters)|定义一个参与构建的Group,并作为参与scons构建的对象返回。
参数:
name:Group的名字
src:group的源文件
depend:Group的依赖,具体为rtconfig.h中的宏,如:RT_USING_FINSH
parameters:构建参数| +|GetCurrentDir( )|获取当前脚本所在路径| + +### 构建参数 + +|构建参数|意义| +|-|-| +|CCFLAGS|C/CPP 源文件公共编译参数| +|CFLAGS|C 源文件独有编译参数| +|CXXFLAGS|CPP 源文件独有编译参数| +|CPPPATH|头文件路径| +|CPPDEFINES|编译时添加宏定义| +|LIBRARY|是否将Group构建为静态库| + +### SConscript最佳实践 + +### 构建组件 + +```Python +from building import * # 导入RT-Thread的自定义构建函数 + +cwd = GetCurrentDir() # 获取当前脚本的路径 +src = Split(''' +shell.c +msh.c +''') + +if GetDepend('MSH_USING_BUILT_IN_COMMANDS'): # 判断是否启用MSH的内建命令 + src += ['cmd.c'] + +if GetDepend('DFS_USING_POSIX'): # 判断是否启用POSIX接口 + src += ['msh_file.c'] + +CPPPATH = [cwd] # 将当前路径加入构建搜索的头文件路径 + +group = DefineGroup('Finsh', src, depend = ['RT_USING_FINSH'], CPPPATH = CPPPATH) +# 定义Finsh组件的group + +Return('group') # 将当前脚本指定的构建对象返回上级SCons脚本 +``` + +### 构建驱动 + +```Python +Import('RTT_ROOT') # 导入变量RTT_ROOT,即RT-Thread的根目录 +Import('rtconfig') # 导入rtconfig +from building import * # 导入RT-Thread的自定义构建函数 + +cwd = GetCurrentDir() # 获取当前脚本的路径 + +# add the general drivers. +src = Split(""" +""") + +if GetDepend(['RT_USING_PIN']): # 判断是否启用PING设备 + src += ['drv_gpio.c'] + +if GetDepend(['RT_USING_HWTIMER']): # 判断是否启用HWTIMER设备 + src += ['drv_hwtimer.c'] + +src += ['drv_common.c'] + +path = [cwd] +path += [cwd + '/config'] + +if GetDepend('BSP_USING_ON_CHIP_FLASH'): # 判断是否启用片上FLASH + path += [cwd + '/drv_flash'] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) +# 定义驱动的group + +Return('group') # 将当前脚本指定的构建对象返回上级SCons脚本 + +``` + +### 构建应用 + +```Python +from building import * # 导入RT-Thread的自定义构建函数 + +cwd = GetCurrentDir() # 获取当前脚本的路径 +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] # 加入构建搜索的头文件路径 + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH, LIBRARY=True) +# 定义应用的group 并构建为静态库,然后构建ELF,hex,bin。 + +Return('group') # 将当前脚本指定的构建对象返回上级SCons脚本 +``` diff --git a/development-tools/build-config-system/figures/buildconfig1.png b/development-tools/build-config-system/figures/buildconfig1.png new file mode 100644 index 0000000000000000000000000000000000000000..f85a903365f9c2b80188ec145ea62412c9d26620 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig1.png differ diff --git a/development-tools/build-config-system/figures/buildconfig10.png b/development-tools/build-config-system/figures/buildconfig10.png new file mode 100644 index 0000000000000000000000000000000000000000..2d00995450e8f3714c7aeed79bdf938bea8654e2 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig10.png differ diff --git a/development-tools/build-config-system/figures/buildconfig11.png b/development-tools/build-config-system/figures/buildconfig11.png new file mode 100644 index 0000000000000000000000000000000000000000..07c70af6b09167d45672e9c8078880e8609dc8b2 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig11.png differ diff --git a/development-tools/build-config-system/figures/buildconfig12.png b/development-tools/build-config-system/figures/buildconfig12.png new file mode 100644 index 0000000000000000000000000000000000000000..ecd5babe4b5ccc4da68d4c0d13bdb24ca22b3b67 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig12.png differ diff --git a/development-tools/build-config-system/figures/buildconfig13.png b/development-tools/build-config-system/figures/buildconfig13.png new file mode 100644 index 0000000000000000000000000000000000000000..5dfcd4233d2b10e4cd79dfa00a75014ef5d901a6 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig13.png differ diff --git a/development-tools/build-config-system/figures/buildconfig14.png b/development-tools/build-config-system/figures/buildconfig14.png new file mode 100644 index 0000000000000000000000000000000000000000..4b9733d74af4638c5359e4c190b0e6b321c8bee3 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig14.png differ diff --git a/development-tools/build-config-system/figures/buildconfig15.png b/development-tools/build-config-system/figures/buildconfig15.png new file mode 100644 index 0000000000000000000000000000000000000000..69d559c7b2b0271373f485f011f248ae7ffd7169 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig15.png differ diff --git a/development-tools/build-config-system/figures/buildconfig16.png b/development-tools/build-config-system/figures/buildconfig16.png new file mode 100644 index 0000000000000000000000000000000000000000..22a513edcad2d504ae47992d4db7a32f1a80b4be Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig16.png differ diff --git a/development-tools/build-config-system/figures/buildconfig17.png b/development-tools/build-config-system/figures/buildconfig17.png new file mode 100644 index 0000000000000000000000000000000000000000..1f62cc59afa881434525a89083bf3a7c698d1a79 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig17.png differ diff --git a/development-tools/build-config-system/figures/buildconfig18.png b/development-tools/build-config-system/figures/buildconfig18.png new file mode 100644 index 0000000000000000000000000000000000000000..86966d58861cf57321335d88ca12ab772ae27a95 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig18.png differ diff --git a/development-tools/build-config-system/figures/buildconfig19.png b/development-tools/build-config-system/figures/buildconfig19.png new file mode 100644 index 0000000000000000000000000000000000000000..614f4cf8e9c15de9303b59a160dcc86b0e6e176f Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig19.png differ diff --git a/development-tools/build-config-system/figures/buildconfig2.png b/development-tools/build-config-system/figures/buildconfig2.png new file mode 100644 index 0000000000000000000000000000000000000000..fdc769b145a9badcfab391f55db234a3ad70b278 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig2.png differ diff --git a/development-tools/build-config-system/figures/buildconfig3.png b/development-tools/build-config-system/figures/buildconfig3.png new file mode 100644 index 0000000000000000000000000000000000000000..158e7ee519815cf5955c92add35798ffe5ad79f6 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig3.png differ diff --git a/development-tools/build-config-system/figures/buildconfig4.png b/development-tools/build-config-system/figures/buildconfig4.png new file mode 100644 index 0000000000000000000000000000000000000000..1b7a4f2fbdb89f2b6e7d4e444a1a2ff333935d5a Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig4.png differ diff --git a/development-tools/build-config-system/figures/buildconfig5.png b/development-tools/build-config-system/figures/buildconfig5.png new file mode 100644 index 0000000000000000000000000000000000000000..5a2d6bdb763a2f7b3be389ea7ce9866644c63ce1 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig5.png differ diff --git a/development-tools/build-config-system/figures/buildconfig6.png b/development-tools/build-config-system/figures/buildconfig6.png new file mode 100644 index 0000000000000000000000000000000000000000..186edc8f20ef61cafab0019239225c19e4e1e852 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig6.png differ diff --git a/development-tools/build-config-system/figures/buildconfig7.png b/development-tools/build-config-system/figures/buildconfig7.png new file mode 100644 index 0000000000000000000000000000000000000000..ff69d5c8cafb837afdc5e53d54e8c7a382ab1058 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig7.png differ diff --git a/development-tools/build-config-system/figures/buildconfig8.png b/development-tools/build-config-system/figures/buildconfig8.png new file mode 100644 index 0000000000000000000000000000000000000000..0c3a5e8700461f5501474817205f7c8ecf958755 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig8.png differ diff --git a/development-tools/build-config-system/figures/buildconfig9.png b/development-tools/build-config-system/figures/buildconfig9.png new file mode 100644 index 0000000000000000000000000000000000000000..4d29468da7ebc25d44e5b92a7824395bb10dd430 Binary files /dev/null and b/development-tools/build-config-system/figures/buildconfig9.png differ diff --git a/development-tools/build-config-system/summary.md b/development-tools/build-config-system/summary.md new file mode 100644 index 0000000000000000000000000000000000000000..287c76756d2870308aaa87b6fec551b1d2559640 --- /dev/null +++ b/development-tools/build-config-system/summary.md @@ -0,0 +1,5 @@ +# 简述 + +RT-Thread的构建与配置系统由以下几个部分组成 + +![构建配置系统](./figures/buildconfig1.png) \ No newline at end of file diff --git a/development-tools/kconfig/figures/bool.png b/development-tools/kconfig/figures/bool.png deleted file mode 100644 index 6ed985e78d7f395686cfb8883bcc9f1e19114bea..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/bool.png and /dev/null differ diff --git a/development-tools/kconfig/figures/choice.png b/development-tools/kconfig/figures/choice.png deleted file mode 100644 index 5d6ef18d9ad0723f6f4f2ff5c6b5c948bfa727e5..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/choice.png and /dev/null differ diff --git a/development-tools/kconfig/figures/comment.png b/development-tools/kconfig/figures/comment.png deleted file mode 100644 index b292a5e687e5e25baebeed5290a03af097070e2a..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/comment.png and /dev/null differ diff --git a/development-tools/kconfig/figures/config.png b/development-tools/kconfig/figures/config.png deleted file mode 100644 index 9b9c79b2bed3444a1b4452a06a13b8fdc0b1c330..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/config.png and /dev/null differ diff --git a/development-tools/kconfig/figures/help.png b/development-tools/kconfig/figures/help.png deleted file mode 100644 index 3c53605dd8e29c1c55a34a03a745c7e1cbeabce6..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/help.png and /dev/null differ diff --git a/development-tools/kconfig/figures/hex.png b/development-tools/kconfig/figures/hex.png deleted file mode 100644 index 83b1ec88efebaa4da6daedf0695348676a7aad39..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/hex.png and /dev/null differ diff --git a/development-tools/kconfig/figures/if0.png b/development-tools/kconfig/figures/if0.png deleted file mode 100644 index c0c11665936c8c0f98feb11763de51a75f52e0fe..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/if0.png and /dev/null differ diff --git a/development-tools/kconfig/figures/if1.png b/development-tools/kconfig/figures/if1.png deleted file mode 100644 index cc3a53c7ffadf66b244c21bd79c91d658ca49a70..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/if1.png and /dev/null differ diff --git a/development-tools/kconfig/figures/if11.png b/development-tools/kconfig/figures/if11.png deleted file mode 100644 index 671942c5600d7009d3e11493908403bd45fce650..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/if11.png and /dev/null differ diff --git a/development-tools/kconfig/figures/if2.png b/development-tools/kconfig/figures/if2.png deleted file mode 100644 index f24ebc83c4e0c8a059df593999eea6e6cc738cfd..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/if2.png and /dev/null differ diff --git a/development-tools/kconfig/figures/int.png b/development-tools/kconfig/figures/int.png deleted file mode 100644 index b415032659fb001e043d4ae80a3dd12610e11d07..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/int.png and /dev/null differ diff --git a/development-tools/kconfig/figures/menu.png b/development-tools/kconfig/figures/menu.png deleted file mode 100644 index e1be5a56f1e248bfc425117858762b28142d64bd..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/menu.png and /dev/null differ diff --git a/development-tools/kconfig/figures/menu1.png b/development-tools/kconfig/figures/menu1.png deleted file mode 100644 index 408c9dc2be787ba1d3bcfe256d79ba03c2128dd1..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/menu1.png and /dev/null differ diff --git a/development-tools/kconfig/figures/menuconfig1.png b/development-tools/kconfig/figures/menuconfig1.png deleted file mode 100644 index 08a540e06c3c59241b9e4803b125ccb933425fbf..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/menuconfig1.png and /dev/null differ diff --git a/development-tools/kconfig/figures/menuconfig2.png b/development-tools/kconfig/figures/menuconfig2.png deleted file mode 100644 index 63a54e76ca192fd7de050e7cacae62a3df2a6d57..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/menuconfig2.png and /dev/null differ diff --git a/development-tools/kconfig/figures/string.png b/development-tools/kconfig/figures/string.png deleted file mode 100644 index b2c88824f1272efa425ff2a9f02d6b290542fc98..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/string.png and /dev/null differ diff --git a/development-tools/kconfig/figures/tristate.png b/development-tools/kconfig/figures/tristate.png deleted file mode 100644 index a42eed73c318f2936a85327453c91ac7f90417ed..0000000000000000000000000000000000000000 Binary files a/development-tools/kconfig/figures/tristate.png and /dev/null differ diff --git a/development-tools/scons/figures/1149b400a917cdd7906affecf08503f6.png b/development-tools/scons/figures/1149b400a917cdd7906affecf08503f6.png deleted file mode 100644 index e1238809314a1fa21edd5c75c0837ccf04625b1b..0000000000000000000000000000000000000000 Binary files a/development-tools/scons/figures/1149b400a917cdd7906affecf08503f6.png and /dev/null differ diff --git a/development-tools/scons/figures/b1e0b39d090bfc4640958ffdb11d9741.png b/development-tools/scons/figures/b1e0b39d090bfc4640958ffdb11d9741.png deleted file mode 100644 index 1d533c22ff41fffadaf4f8cf54998aa0cd47100d..0000000000000000000000000000000000000000 Binary files a/development-tools/scons/figures/b1e0b39d090bfc4640958ffdb11d9741.png and /dev/null differ diff --git a/development-tools/scons/figures/caef0674c4a148411789c42f8f8b70b7.png b/development-tools/scons/figures/caef0674c4a148411789c42f8f8b70b7.png deleted file mode 100644 index 3a5e50fb07b24bd374a0aa5ac1d2a9c390bb8df5..0000000000000000000000000000000000000000 Binary files a/development-tools/scons/figures/caef0674c4a148411789c42f8f8b70b7.png and /dev/null differ diff --git a/development-tools/scons/figures/cb02d48b93098e73681818fd62f22f8b.png b/development-tools/scons/figures/cb02d48b93098e73681818fd62f22f8b.png deleted file mode 100644 index f3a0ba2726b7c9adb8df3434b96d49009ac6efc2..0000000000000000000000000000000000000000 Binary files a/development-tools/scons/figures/cb02d48b93098e73681818fd62f22f8b.png and /dev/null differ diff --git a/development-tools/scons/figures/f42ee8cdfd03c1782679c759f70f072f.png b/development-tools/scons/figures/f42ee8cdfd03c1782679c759f70f072f.png deleted file mode 100644 index 0842ada7755f50ec11bb0b9aee5455a71405124d..0000000000000000000000000000000000000000 Binary files a/development-tools/scons/figures/f42ee8cdfd03c1782679c759f70f072f.png and /dev/null differ diff --git a/development-tools/scons/figures/f96388acd1264b4ffcd391c3fd399a50.png b/development-tools/scons/figures/f96388acd1264b4ffcd391c3fd399a50.png deleted file mode 100644 index 40f592af35bc80eca619aec7c2f714319b813dff..0000000000000000000000000000000000000000 Binary files a/development-tools/scons/figures/f96388acd1264b4ffcd391c3fd399a50.png and /dev/null differ diff --git a/development-tools/scons/scons.md b/development-tools/scons/scons.md deleted file mode 100644 index 8aa5095a1b2d7b1e26985b4f3d5ad4b807625ebe..0000000000000000000000000000000000000000 --- a/development-tools/scons/scons.md +++ /dev/null @@ -1,619 +0,0 @@ -# SCons 构建工具 - -## SCons 简介 - -SCons 是一套由 Python 语言编写的开源构建系统,类似于 GNU Make。它采用不同于通常 Makefile 文件的方式,而是使用 SConstruct 和 SConscript 文件来替代。这些文件也是 Python 脚本,能够使用标准的 Python 语法来编写。所以在 SConstruct、SConscript 文件中可以调用 Python 标准库进行各类复杂的处理,而不局限于 Makefile 设定的规则。 - -在 [SCons](http://www.scons.org/doc/production/HTML/scons-user/index.html) 的网站上可以找到详细的 SCons 用户手册,本章节讲述 SCons 的基本用法,以及如何在 RT-Thread 中用好 SCons 工具。 - -### 什么是构建工具 - -构建工具 (software construction tool) 是一种软件,它可以根据一定的规则或指令,将源代码编译成可执行的二进制程序。这是构建工具最基本也是最重要的功能。实际上构建工具的功能不止于此,通常这些规则有一定的语法,并组织成文件。这些文件用来控制构建工具的行为,在完成软件构建之外,也可以做其他事情。 - -目前最流行的构建工具是 GNU Make。很多知名开源软件,如 Linux 内核就采用 Make 构建。Make 通过读取 Makefile 文件来检测文件的组织结构和依赖关系,并完成 Makefile 中所指定的命令。 - -由于历史原因,Makefile 的语法比较混乱,不利于初学者学习。此外在 Windows 平台上使用 Make 也不方便,需要安装 Cygwin 环境。为了克服 Make 的种种缺点,人们开发了其他构建工具,如 CMake 和 SCons 等。 - -### RT-Thread 构建工具 - -RT-Thread 早期使用 Make/Makefile 构建。从 0.3.x 开始,RT-Thread 开发团队逐渐引入了 SCons 构建系统,引入 SCons 唯一的目是:使大家从复杂的 Makefile 配置、IDE 配置中脱离出来,把精力集中在 RT-Thread 功能开发上。 - -有些读者可能会有些疑惑,这里介绍的构建工具与 IDE 有什么不同呢?IDE 通过图形化界面的操作来完成构建。大部分 IDE 会根据用户所添加的源码生成类似 Makefile 或 SConscript 的脚本文件,在底层调用类似 Make 或 SCons 的工具来构建源码。 - -### 安装 SCons - -在使用 SCons 系统前需要在 PC 主机中安装它,因为它是 Python 语言编写的,所以在使用 SCons 之前需要安装 Python 运行环境。 - -RT-Thread 提供的 Env 配置工具带有 SCons 和 Python,因此在 windows 平台使用 SCons 则不需要安装这两个软件。 - -在 Linux、BSD 环境中 Python 应该已经默认安装了,一般也是 2.x 版本系列的 Python 环境。这时只需要安装 SCons 即可,例如在 Ubuntu 中可以使用如下命令安装 SCons: - -`sudo apt-get install scons` - -## SCons 基本功能 - -RT-Thread 构建系统支持多种编译器。目前支持的编译器包括 ARM GCC、MDK、IAR、VisualStudio、Visual DSP。主流的 ARM Cortex M0、M3、M4 平台,基本上 ARM GCC、MDK、IAR 都是支持的。有一些 BSP 可能仅支持一种,读者可以阅读该 BSP 目录下的 rtconfig.py 里的 CROSS_TOOL 选项查看当前支持的编译器。 - -如果是 ARM 平台的芯片,则可以使用 Env 工具,输入 scons 命令直接编译 BSP,这时候默认使用的是 ARM GCC 编译器,因为 Env 工具带有 ARM GCC 编译器。 如下图所示使用 `scons` 命令编译 stm32f10x-HAL BSP,后文讲解 SCons 也将基于这个 BSP。 - -![使用 scons 命令编译 stm32f10x-HAL BSP](figures/b1e0b39d090bfc4640958ffdb11d9741.png) - -如果用户要使用其他的 BSP 已经支持的编译器编译工程,或者 BSP 为非 ARM 平台的芯片,那么不能直接使用 scons 命令编译工程,需要自己安装对应的编译器,并且指定使用的编译器路径。在编译工程前,可以在 Env 命令行界面使用下面的 2 个命令指定编译器为 MDK 和编译器路径为 MDK 的安装路径: - -```c -set RTT_CC=keil -set RTT_EXEC_PATH=C:/Keilv5 -``` - -再例如 - -``` -set RTT_CC=gcc -set RTT_EXEC_PATH=D:\software\RaspberryPi-Pico\gcc\2020-q4-major\bin -``` - -### SCons 基本命令 - -本节介绍 RT-Thread 中常用的 SCons 命令。SCons 不仅完成基本的编译,还可以生成 MDK/IAR/VS 工程。 - -#### scons - -在 Env 命令行窗口进入要编译的 BSP 工程目录,然后使用此命令可以直接编译工程。如果执行过 `scons` 命令后修改了一些源文件,再次执行 scons 命令时,则 SCons 会进行增量编译,仅编译修改过的源文件并链接。 - -如果在 Windows 上执行 `scons` 输出以下的警告信息: - -```c -scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly. -``` - -说明 scons 并没在你的机器上找到 Visual Studio 编译器,但实际上我们主要是针对设备开发,和 Windows 本地没什么关系,请直接忽略掉它。 - -`scons` 命令后面还可以增加一个 - s 参数,即命令 `scons -s`,和 scons 命令不同的是此命令不会打印具体的内部命令。 - -#### scons -c - -清除编译目标。这个命令会清除执行 scons 时生成的临时文件和目标文件。 - -#### scons --target=XXX - -如果使用 mdk/iar 来进行项目开发,当修改了 rtconfig.h 打开或者关闭某些组件时,需要使用以下命令中的其中一种重新生成对应的定制化的工程,然后在 mdk/iar 进行编译下载。 - -```c -scons --target=iar -scons --target=mdk4 -scons --target=mdk5 -``` - -在命令行窗口进入要编译的 BSP 工程目录,使用 `scons --target=mdk5` 命令后会在 BSP 目录生成一个新的 MDK 工程文件名为 project.uvprojx。双击它打开,就可以使用 MDK 来编译、调试。使用 `scons --target=iar` 命令后则会生成一个新的 IAR 工程文件名为 project.eww。不习惯 SCons 的用户可以使用这种方式。如果打开 project.uvproj 失败,请删除 project.uvopt 后,重新生成工程。 - -在 bsp/simulator 下,可以使用下面的命令生成 vs2012 的工程或 vs2005 的工程。 - -```c -scons --target=vs2012 -Scons --target=vs2005 -``` - -如果 BSP 目录下提供其他 IDE 工程的模板文件也可以使用此命令生成对应的新工程,比如 ua、vs、cb、cdk。 - -这个命令后面同样可以增加一个 -s 参数,如命令 `scons –target=mdk5 -s`,执行此命令时不会打印具体的内部命令。 - -> [!NOTE] -> 注:要生成 MDK 或者 IAR 的工程文件,前提条件是 BSP 目录存在一个工程模版文件,然后 scons 才会根据这份模版文件加入相关的源码,头文件搜索路径,编译参数,链接参数等。而至于这个工程是针对哪颗芯片的,则直接由这份工程模版文件指定。所以大多数情况下,这个模版文件是一份空的工程文件,用于辅助 SCons 生成 project.uvprojx 或者 project.eww。 - -#### scons -jN - -多线程编译目标,在多核计算机上可以使用此命令加快编译速度。一般来说一颗 cpu 核心可以支持 2 个线程。双核机器上使用 `scons -j4` 命令即可。 - -> [!NOTE] -> 注:如果你只是想看看编译错误或警告,最好是不使用 - j 参数,这样错误信息不会因为多个文件并行编译而导致出错信息夹杂在一起。 - -#### scons --dist - -搭建项目框架,使用此命令会在 BSP 目录下生成 dist 目录,这便是开发项目的目录结构,包含了RT-Thread源码及BSP相关工程,不相关的BSP文件夹及libcpu都会被移除,并且可以随意拷贝此工程到任何目录下使用。 - -#### scons --verbose - -默认情况下,使用 scons 命令编译的输出不会显示编译参数,如下所示: - -```c -D:\repository\rt-thread\bsp\stm32f10x>scons -scons: Reading SConscript files ... -scons: done reading SConscript files. -scons: Building targets ... -scons: building associated VariantDir targets: build -CC build\applications\application.o -CC build\applications\startup.o -CC build\components\drivers\serial\serial.o -... -``` - -使用 scons –verbose 命令的效果如下: - -```c -armcc -o build\src\mempool.o -c --device DARMSTM --apcs=interwork -ID:/Keil/ARM/ -RV31/INC -g -O0 -DUSE_STDPERIPH_DRIVER -DSTM32F10X_HD -Iapplications -IF:\Projec -t\git\rt-thread\applications -I. -IF:\Project\git\rt-thread -Idrivers -IF:\Proje -ct\git\rt-thread\drivers -ILibraries\STM32F10x_StdPeriph_Driver\inc -IF:\Project -\git\rt-thread\Libraries\STM32F10x_StdPeriph_Driver\inc -ILibraries\STM32_USB-FS --Device_Driver\inc -IF:\Project\git\rt-thread\Libraries\STM32_USB-FS-Device_Driv -er\inc -ILibraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x -IF:\Project\git\rt-thre -... -``` - -## SCons 进阶 - -SCons 使用 SConscript 和 SConstruct 文件来组织源码结构,通常来说一个项目只有一 SConstruct,但是会有多个 SConscript。一般情况下,每个存放有源代码的子目录下都会放置一个 SConscript。 - -为了使 RT-Thread 更好的支持多种编译器,以及方便的调整编译参数,RT-Thread 为每个 BSP 单独创建了一个名为 rtconfig.py 的文件。因此每一个 RT-Thread BSP 目录下都会存在下面三个文件:rtconfig.py、SConstruct 和 SConscript,它们控制 BSP 的编译。一个 BSP 中只有一个 SConstruct 文件,但是却会有多个 SConscript 文件,可以说 SConscript 文件是组织源码的主力军。 - -RT-Thread 大部分源码文件夹下也存在 SConscript 文件,这些文件会被 BSP 目录下的 SConscript 文件 “找到” 从而将 rtconfig.h 中定义的宏对应的源代码加入到编译器中来。后文将以 stm32f10x-HAL BSP 为例,讲解 SCons 是如何构建工程。 - -### SCons 内置函数 - -如果想要将自己的一些源代码加入到 SCons 编译环境中,一般可以创建或修改已有 SConscript 文件。SConscript 文件可以控制源码文件的加入,并且可以指定文件的 Group(与 MDK/IAR 等 IDE 中的 Group 的概念类似)。 - -SCons 提供了很多内置函数可以帮助我们快速添加源码程序,利用这些函数,再配合一些简单的 Python 语句我们就能随心所欲向项目中添加或者删除源码。下面将简单介绍一些常用函数。 - -#### GetCurrentDir() - -获取当前路径。 - -#### Glob('\*.c') - -获取当前目录下的所有 C 文件。修改参数的值为其他后缀就可以匹配当前目录下的所有某类型的文件。 - -#### GetDepend(macro) - -该函数定义在 tools 目录下的脚本文件中,它会从 rtconfig.h 文件读取配置信息,其参数为 rtconfig.h 中的宏名。如果 rtconfig.h 打开了某个宏,则这个方法(函数)返回真,否则返回假。 - -#### Split(str) - -将字符串 str 分割成一个列表 list。 - -#### DefineGroup(name, src, depend,**parameters) - -这是 RT-Thread 基于 SCons 扩展的一个方法(函数)。DefineGroup 用于定义一个组件。组件可以是一个目录(下的文件或子目录),也是后续一些 IDE 工程文件中的一个 Group 或文件夹。 - -`DefineGroup() ` 函数的参数描述: - -|**参数**|**描述** | -|-------|------------------------------------| -| 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 | 包含此参数,则会将组件生成的目标文件打包成库文件 | - -#### SConscript(dirs,variant_dir,duplicate) - -读取新的 SConscript 文件,SConscript() 函数的参数描述如下所示: - -|**参数** |**描述** | -|-------------|---------------------------------------| -| dirs | SConscript 文件路径 | -| variant_dir | 指定生成的目标文件的存放路径 | -| duiplicate | 设定是否拷贝或链接源文件到 variant_dir | - -## SConscript 示例 - -下面我们将以几个 SConscript 为例讲解 scons 构建工具的使用方法。 - -### SConscript 示例 1 - -我们先从 stm32f10x-HAL BSP 目录下的 SConcript 文件开始讲解,这个文件管理 BSP 下面的所有其他 SConscript 文件,内容如下所示。 - -```c -import os -cwd = str(Dir('#')) -objs = [] -list = os.listdir(cwd) -for d in list: - path = os.path.join(cwd, d) - if os.path.isfile(os.path.join(path, 'SConscript')): - objs = objs + SConscript(os.path.join(d, 'SConscript')) -Return('objs') -``` - -* `import os:` 导入 Python 系统编程 os 模块,可以调用 os 模块提供的函数用于处理文件和目录。 - -* `cwd = str(Dir('#')):` 获取工程的顶级目录并赋值给字符串变量 cwd,也就是工程的 SConstruct 所在的目录,在这里它的效果与 `cwd = GetCurrentDir()` 相同。 - -* `objs = []:` 定义了一个空的 list 型变量 objs。 - -* `list = os.listdir(cwd):` 得到当前目录下的所有子目录,并保存到变量 list 中。 - -* 随后是一个 python 的 for 循环,这个 for 循环会遍历一遍 BSP 的所有子目录并运行这些子目录的 SConscript 文件。具体操作是取出一个当前目录的子目录,利用 `os.path.join(cwd,d)` 拼接成一个完整路径,然后判断这个子目录是否存在一个名为 SConscript 的文件,若存在则执行 `objs = objs + SConscript(os.path.join(d,'SConscript'))。` 这一句中使用了 SCons 提供的一个内置函数 `SConscript()`,它可以读入一个新的 SConscript 文件,并将 SConscript 文件中所指明的源码加入到了源码编译列表 objs 中来。 - -通过这个 SConscript 文件,BSP 工程所需要的源代码就被加入了编译列表中。 - -### SConscript 示例 2 - -那么 stm32f10x-HAL BSP 其他的 SConcript 文件又是怎样的呢?我们再看一下 drivers 目录下 SConcript 文件,这个文件将管理 drivers 目录下面的源代码。drivers 目录用于存放根据 RT-Thread 提供的驱动框架实现的底层驱动代码。 - -```c -Import('rtconfig') -from building import * - -cwd = GetCurrentDir() - -# add the general drivers. -src = Split(""" -board.c -stm32f1xx_it.c -""") - -if GetDepend(['RT_USING_PIN']): - src += ['drv_gpio.c'] -if GetDepend(['RT_USING_SERIAL']): - src += ['drv_usart.c'] -if GetDepend(['RT_USING_SPI']): - src += ['drv_spi.c'] -if GetDepend(['RT_USING_USB_DEVICE']): - src += ['drv_usb.c'] -if GetDepend(['RT_USING_SDCARD']): - src += ['drv_sdcard.c'] - -if rtconfig.CROSS_TOOL == 'gcc': - src += ['gcc_startup.s'] - -CPPPATH = [cwd] - -group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) - -Return('group') - -``` - -* `Import('rtconfig'):` 导入 rtconfig 对象,后面用到的 rtconfig.CROSS_TOOL 定义在这个 rtconfig 模块。 - -* `from building import *:` 把 building 模块的所有内容全都导入到当前模块,后面用到的 DefineGroup 定义在这个模块。 - -* `cwd = GetCurrentDir():` 获得当前路径并保存到字符串变量 cwd 中。 - -后面一行使用 `Split()` 函数来将一个文件字符串分割成一个列表,其效果等价于 - -`src = ['board.c','stm32f1xx_it.c']` - -后面使用了 if 判断和 `GetDepend()` 检查 rtconfig.h 中的某个宏是否打开,如果打开,则使用 `src += [src_name]` 来往列表变量 src 中追加源代码文件。 - -* `CPPPATH = [cwd]:` 将当前路径保存到一个列表变量 CPPPATH 中。 - -最后一行使用 DefineGroup 创建一个名为 Drivers 的组,这个组也就对应 MDK 或者 IAR 中的分组。这个组的源代码文件为 src 指定的文件,depend 为空表示该组不依赖任何 rtconfig.h 的宏。 - -`CPPPATH =CPPPATH` 表示将当前路径添加到系统的头文件路径中。左边的 CPPPATH 是 DefineGroup 中内置参数,表示头文件路径。右边的 CPPPATH 是本文件上面一行定义的。这样我们就可以在其他源码中引用 drivers 目录下的头文件了。 - -### SConscript 示例 3 - -我们再看一下 applications 目录下的 SConcript 文件,这个文件将管理 applications 目录下面的源代码,用于存放用户自己的应用代码。 - -```c -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') -CPPPATH = [cwd, str(Dir('#'))] - -group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) - -Return('group') -``` - -`src = Glob('*.c'):` 得到当前目录下所有的 C 文件。 - -`CPPPATH = [cwd, str(Dir('#'))]:` 将当前路径和工程的 SConstruct 所在的路径保存到列表变量 CPPPATH 中。 - -最后一行使用 DefineGroup 创建一个名为 Applications 的组。这个组的源代码文件为 src 指定的文件,depend 为空表示该组不依赖任何 rtconfig.h 的宏,并将 CPPPATH 保存的路径添加到了系统头文件搜索路径中。这样 applications 目录和 stm32f10x-HAL BSP 目录里面的头文件在源代码的其他地方就可以引用了。 - -总结:这个源程序会将当前目录下的所有 c 程序加入到组 Applications 中,因此如果在这个目录下增加或者删除文件,就可以将文件加入工程或者从工程中删除。它适用于批量添加源码文件。 - -### SConscript 示例 4 - -下面是 RT-Thread 源代码 component/finsh/SConscript 文件的内容,这个文件将管理 finsh 目录下面的源代码。 - -```c -Import('rtconfig') -from building import * - -cwd = GetCurrentDir() -src = Split(''' -shell.c -symbol.c -cmd.c -''') - -fsh_src = Split(''' -finsh_compiler.c -finsh_error.c -finsh_heap.c -finsh_init.c -finsh_node.c -finsh_ops.c -finsh_parser.c -finsh_var.c -finsh_vm.c -finsh_token.c -''') - -msh_src = Split(''' -msh.c -msh_cmd.c -msh_file.c -''') - -CPPPATH = [cwd] -if rtconfig.CROSS_TOOL == 'keil': - LINKFLAGS = '--keep *.o(FSymTab)' - - if not GetDepend('FINSH_USING_MSH_ONLY'): - LINKFLAGS = LINKFLAGS + '--keep *.o(VSymTab)' -else: - LINKFLAGS = '' - -if GetDepend('FINSH_USING_MSH'): - src = src + msh_src -if not GetDepend('FINSH_USING_MSH_ONLY'): - src = src + fsh_src - -group = DefineGroup('finsh', src, depend = ['RT_USING_FINSH'], CPPPATH = CPPPATH, LINKFLAGS = LINKFLAGS) - -Return('group') -``` - -我们来看一下文件中第一个 Python 条件判断语句的内容,如果编译工具是 keil,则变量 `LINKFLAGS = '--keep *.o(FSymTab)'` 否则置空。 - -DefinGroup 同样将 finsh 目录下的 src 指定的文件创建为 finsh 组。`depend = ['RT_USING_FINSH']` 表示这个组依赖 rtconfig.h 中的宏 RT_USING_FINSH。当 rtconfig.h 中打开宏 RT_USING_FINSH 时,finsh 组内的源码才会被实际编译,否则 SCons 不会编译。 - -然后将 finsh 目录加入到系统头文件目录中,这样我们就可以在其他源码中引用 finsh 目录下的头文件。 - -`LINKFLAGS = LINKFLAGS` 的含义与 `CPPPATH = CPPPATH` 类似。左边的 LINKFLAGS 表示链接参数,右边的 LINKFLAGS 则是前面 if else 语句所定义的值。也就是给工程指定链接参数。 - -## 使用 SCons 管理工程 - -前面小节对 RT-Thread 源代码的相关 SConscript 做了详细讲解,大家也应该知道了 SConscript 文件的一些常见写法,本小节将指导大家如何使用 SCons 管理自己的工程。 - -### 添加应用代码 - -前文提到过 BSP 下的 Applications 文件夹用于存放用户自己的应用代码,目前只有一个 main.c 文件。如果用户的应用代码不是很多,建议相关源文件都放在这个文件夹下面。在 Applications 文件夹下新增了 2 个简单的文件 hello.c 和 hello.h,内容如下所示。 - -```c -/* file: hello.h */ - -#ifndef _HELLO_H_ -#define _HELLO_H_ - -int hello_world(void); - -#endif /* _HELLO_H_ */ - -/* file: hello.c */ -#include -#include -#include - -int hello_world(void) -{ - rt_kprintf("Hello, world!\n"); - - return 0; -} - -MSH_CMD_EXPORT(hello_world, Hello world!) -``` - -applications 目录下的 SConcript 文件会把当前目录下的所有源文件都添加到工程中。需要使用 `scons --target=xxx` 命令才会把新增的 2 个文件添加到工程项目中。注意每次新增文件都要重新生成工程。 - -### 添加模块 - -前文提到在自己源代码文件不多的情况下,建议所有源代码文件都放在 applications 文件夹里面。如果用户源代码很多了,并且想创建自己的工程模块,或者需要使用自己获取的其他模块,怎么做会比较合适呢? - -同样以上文提到的 hello.c 和 hello.h 为例,这两个文件将会放到一个单独的文件夹里管理,并且在 MDK 工程文件里有自己的分组,且可以通过 menuconfig 选择是否使用这个模块。在 BSP 下新增 hello 文件夹。 - -![新增 hello 文件夹](figures/f42ee8cdfd03c1782679c759f70f072f.png) - -大家注意到文件夹里多了一个 SConscript 文件,如果想要将自己的一些源代码加入到 SCons 编译环境中,一般可以创建或修改已有的 SConscript 文件。参考上文对 RT-Thread 源代码的一些对 SConscript 文件的分析,这个新增的 hello 模块 SConscript 文件内容如下所示: - -```c -from building import * - -cwd = GetCurrentDir() -include_path = [cwd] -src = [] - -if GetDepend(['RT_USING_HELLO']): - src += ['hello.c'] - -group = DefineGroup('hello', src, depend = [''], CPPPATH = include_path) - -Return('group') -``` - -通过上面几行简单的代码,就创建了一个新组 hello,并且可以通过宏定义控制要加入到组里面的源文件,还将这个组所在的目录添加到了系统头文件路径中。那么自定义宏 RT_USING_HELLO 又是通过怎样的方式定义呢?这里要介绍一个新的文件 Kconfig。Kconfig 用来配置内核,使用 Env 配置系统时使用的 menuconfig 命令生成的配置界面就依赖 Kconfig 文件。menuconfig 命令通过读取工程的各个 Kconfig 文件,生成配置界面供用户配置内核,最后所有配置相关的宏定义都会自动保存到 BSP 目录里的 rtconfig.h 文件中,每一个 BSP 都有一个 rtconfig.h 文件,也就是这个 BSP 的配置信息。 - -在 stm32f10x-HAL BSP 目录下已经有了关于这个 BSP 的 Kconfig 文件,我们可以基于这个文件添加自己需要的配置选项。关于 hello 模块添加了如下配置选项,# 号后面为注释。 - -![hello 模块相关配置选项](figures/caef0674c4a148411789c42f8f8b70b7.png) - -使用 Env 工具进入 stm32f10x-HAL BSP 目录后,使用 menuconfig 命令在主页面最下面就可以看到新增的 hello 模块的配置菜单,进入菜单后如下图所示。 - -![hello 模块配置菜单](figures/1149b400a917cdd7906affecf08503f6.png) - -还可以修改 hello value 的值。 - -![修改 hello value 的值](figures/f96388acd1264b4ffcd391c3fd399a50.png) - -保存配置后退出配置界面,打开 stm32f10x-HAL BSP 目录下的 rtconfig.h 文件可以看到 hello 模块的配置信息已经有了。 - -![hello 模块相关宏定义](figures/cb02d48b93098e73681818fd62f22f8b.png) - -**注意:每次 menuconfig 配置完成后都要使用 scons --target=XXX 命令生成新工程。** - -因为 rtconfig.h 中已经定义了 RT_USING_HELLO 宏,所以新生成工程时就会把 hello.c 的源文件添加到新工程中。 - -上面只是简单列举了在 Kconfig 文件中添加自己模块的配置选项,用户还可以参考[《Env 用户手册》](../env/env.md),里面也有对配置选项修改和添加的讲解,也可以自己百度查看 Kconfig 的相关文档,实现其他更复杂的配置选项。 - -### 添加库 - -如果要往工程中添加一个额外的库,需要注意不同的工具链对二进制库的命名。 - -- ARMCC 工具链下的库名称应该是 xxx.lib,一个以 .lib 为后缀的文件。 -- IAR 工具链下的库名称应该是 xxx.a,一个以 .a 为后缀的文件。 -- GCC 工具链下的库名称应该是 libxxx.a,一个以 .a 为后缀的文件,并且有 lib 前缀。 - -ARMCC / IAR 工具链下,若添加库名为 libabc.lib / libabc_iar.a 时,在指定库时指定全名 libabc。 - -GCC 工具链比较特殊,它识别的是 libxxx.a 这样的库名称,若添加库名为 libabc.a 时,在指定库时是指定 abc,而不是 libabc。 - -例如,`/libs` 下有以下库文件需要添加: - -``` -libabc_keil.lib -libabc_iar.a -libabc_gcc.a -``` - -则对应的 SConscript 如下: - -``` -Import('rtconfig') -from building import * - -cwd = GetCurrentDir() -src = Split(''' -''') - -LIBPATH = [cwd + '/libs'] # LIBPATH 指定库的路径,表示库的搜索路径是当前目录下的'libs'目录 - -if rtconfig.CROSS_TOOL == 'gcc': - LIBS = ['abc_gcc'] # GCC 下 LIBS 指定库的名称 -elif rtconfig.CROSS_TOOL == 'keil': - LIBS = ['libabc_keil'] # ARMCC 下 LIBS 指定库的名称 -else: - LIBS = ['libabc_iar'] # IAR 下 LIBS 指定库的名称 - -group = DefineGroup('ABC', src, depend = [''], LIBS = LIBS, LIBPATH=LIBPATH) - -Return('group') -``` - -### 编译器选项 - -rtconfig.py 是一个 RT-Thread 标准的编译器配置文件,控制了大部分编译选项,是一个使用 python 语言编写的脚本文件,主要用于完成以下工作: - -* 指定编译器(从支持的多个编译器中选择一个你现在使用的编译器)。 - -* 指定编译器参数,如编译选项、链接选项等。 - -当我们使用 scons 命令编译工程时,就会按照 rtconfig.py 的编译器配置选项编译工程。下面的代码为 stm32f10x-HAL BSP 目录下 rtconfig.py 的部分代码。 - -```c -import os - -# toolchains options -ARCH='arm' -CPU='cortex-m3' -CROSS_TOOL='gcc' - -if os.getenv('RTT_CC'): - CROSS_TOOL = os.getenv('RTT_CC') - -# cross_tool provides the cross compiler -# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR - -if CROSS_TOOL == 'gcc': - PLATFORM = 'gcc' - EXEC_PATH = '/usr/local/gcc-arm-none-eabi-5_4-2016q3/bin/' -elif CROSS_TOOL == 'keil': - PLATFORM = 'armcc' - EXEC_PATH = 'C:/Keilv5' -elif CROSS_TOOL == 'iar': - PLATFORM = 'iar' - EXEC_PATH = 'C:/Program Files/IAR Systems/Embedded Workbench 6.0 Evaluation' - -if os.getenv('RTT_EXEC_PATH'): - EXEC_PATH = os.getenv('RTT_EXEC_PATH') - -BUILD = 'debug' - -if PLATFORM == 'gcc': - # toolchains - PREFIX = 'arm-none-eabi-' - CC = PREFIX + 'gcc' - AS = PREFIX + 'gcc' - AR = PREFIX + 'ar' - LINK = PREFIX + 'gcc' - TARGET_EXT = 'elf' - SIZE = PREFIX + 'size' - OBJDUMP = PREFIX + 'objdump' - OBJCPY = PREFIX + 'objcopy' - - DEVICE = '-mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections' - CFLAGS = DEVICE - AFLAGS = '-c' + DEVICE + '-x assembler-with-cpp' - LFLAGS = DEVICE + '-Wl,--gc-sections,-Map=rtthread-stm32.map,-cref,-u,Reset_Handler -T stm32_rom.ld' -``` - -其中 CFLAGS 是 C 文件的编译选项,AFLAGS 则是汇编文件的编译选项,LFLAGS 是链接选项。BUILD 变量控制代码优化的级别。默认 BUILD 变量取值为'debug',即使用 debug 方式编译,优化级别 0。如果将这个变量修改为其他值,就会使用优化级别 2 编译。下面几种都是可行的写法(总之只要不是'debug'就可以了)。 - -```c -BUILD = '' -BUILD = 'release' -BUILD = 'hello, world' -``` - -建议在开发阶段都使用 debug 方式编译,不开优化,等产品稳定之后再考虑优化。 - -关于这些选项的具体含义需要参考编译器手册,如上面使用的 armcc 是 MDK 的底层编译器。其编译选项的含义在 MDK help 中有详细说明。 - -前文提到过如果用户执行 scons 命令时希望使用其他编译器编译工程,可以在 Env 的命令行端使用相关命令指定编译器和编译器路径。但是这样修改只对当前的 Env 进程有效,再次打开时又需要重新使用命令设置,我们可以直接修改 rtconfig.py 文件达到永久配置编译器的目的。一般来说,我们只需要修改 CROSS_TOOL 和下面的 EXEC_PATH 两个选项。 - -* CROSS_TOOL:指定编译器。可选的值有 keil、gcc、iar,浏览 rtconfig.py 可以查看当前 BSP 所支持的编译器。如果您的机器上安装了 MDK,那么可以将 CROSS_TOOL 修改为 keil,则使用 MDK 编译工程。 - -* EXEC_PATH:编译器的安装路径。这里有两点需要注意: - -安装编译器时(如 MDK、GNU GCC、IAR 等),不要安装到带有中文或者空格的路径中。否则,某些解析路径时会出现错误。有些程序默认会安装到 `C:\Program Files` 目录下,中间带有空格。建议安装时选择其他路径,养成良好的开发习惯。 - -修改 EXEC_PATH 时,需要注意路径的格式。在 windows 平台上,默认的路径分割符号是反斜杠 `“\”`,而这个符号在 C 语言以及 Python 中都是用于转义字符的。所以修改路径时,可以将`“\”` 改为 `“/”`,或者在前面加 r(python 特有的语法,表示原始数据)。 - -假如某编译器安装位置为 `D:\Dir1\Dir2` 下。下面几种是正确的写法: - -* EXEC_PATH = `r'D:\Dir1\Dir2'` 注意,字符串前带有 r,则可正常使用 `“\”`。 - -* EXEC_PATH = `'D:/Dir1/Dir2'` 注意,改用 `“/”`,前面没有 r。 - -* EXEC_PATH = `'D:\\Dir1\\Dir2'` 注意,这里使用 `“\”` 的转义性来转义 `“\”` 自己。 - -* 这是错误的写法:EXEC_PATH = `'D:\Dir1\Dir2'`。 - -如果 rtconfig.py 文件有以下代码,在配置自己的编译器时请将下列代码注释掉。 - -```c -if os.getenv('RTT_CC'): - CROSS_TOOL = os.getenv('RTT_CC') -... ... -if os.getenv('RTT_EXEC_PATH'): - EXEC_PATH = os.getenv('RTT_EXEC_PATH') -``` - -上面 2 个 if 判断会设置 CROSS_TOOL 和 EXEC_PATH 为 Env 的默认值。 - -编译器配置完成之后,我们就可以使用 SCons 来编译 RT-Thread 的 BSP 了。在 BSP 目录打开命令行窗口,执行 `scons` 命令就会启动编译过程。 - -### RT-Thread 辅助编译脚本 - -在 RT-Thread 源代码的 tools 目录下存放有 RT-Thread 自己定义的一些辅助编译的脚本,例如用于自动生成 RT-Thread 针对一些 IDE 集成开发环境的工程文件。其中最主要的是 building.py 脚本。 - -### SCons 更多使用 - -对于复杂、大型的系统,显然不仅仅是一个目录下的几个文件就可以搞定的,很可能是由数个文件夹一级一级组合而成。 - -在 SCons 中,可以编写 SConscript 脚本文件来编译这些相对独立目录中的文件,同时也可以使用 SCons 中的 Export 和 Import 函数在 SConstruct 与 SConscript 文件之间共享数据(也就是 Python 中的一个对象数据)。更多 SCons 的使用方法请参考 [SCons 官方文档](https://scons.org/documentation.html)。