前言
-
RT-Thread 默认使用 scons 进行工程的构建,虽然 RT-Thread BSP 中的 hello world 例程比较简单,实际项目开发,可能源码的工程会由多级目录,如何让多级的目录参与构建?
-
scons 构建时,除了依赖工程的根目录
rtconfig.py
、SConstruct
、SConscript
,也会依赖 Kconfig 进行配置,哪些 代码文件参与构建,哪些文件不参与构建
多级目录
- 工程根目录下的
SConscript
内容如下
# RT-Thread scons bridge
import os
from building import *
cwd = GetCurrentDir()
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')
-
其实发现,这个
SConscript
文件就是个 python 脚本文件, scons 构建其实是基于 python 脚本的,只是最终编译依旧是额外的编译工具链,如gcc
armcc
等 -
顶层目录的
SConscript
其实是变量当前所有目录list = os.listdir(cwd)
,然后 确认各个目录下是否包含
SConscript
文件,如果包含,就参与构建。 -
因此,如果是多级目录,只需要每级目录下提供
SConscript
文件,就可以让本级目录与下级各个目录参与构建
SConscript
包含多级目录的写法
- 比如
SConscript
from building import *
import os
cwd = GetCurrentDir()
CPPPATH = [cwd]
src = ['main.c']
if GetDepend(['PKG_USING_RTDUINO']) and not GetDepend(['RTDUINO_NO_SETUP_LOOP']):
src += ['arduino_main.cpp']
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
group = group + SConscript(os.path.join(item, 'SConscript'))
Return('group')
-
这个
SConscript
文件中,group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
定义了 本级目录下参与构建的文件。 -
条件 构建:通过配置选择是否参与构建
if GetDepend(['PKG_USING_RTDUINO']) and not GetDepend(['RTDUINO_NO_SETUP_LOOP']):
src += ['arduino_main.cpp']
- 各个子目录下的
SConscript
搜索
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
group = group + SConscript(os.path.join(item, 'SConscript'))
-
最终返回最终的构建目标:
Return('group')
-
注意事项:如果没有下级目录,这个带层级目录构建的
SConscript
脚本依旧适用,原因就是list = os.listdir(cwd)
这里为空,因此 直接返回了Return('group')
-
因此多级目录下的构建,只需要每级目录下,均创建
SConscript
脚本即可,如果一个目录下,只有子目录,没有需要构建的文件,SConscript
脚本 可以简单的写为:
# for module compiling
import os
from building import *
cwd = GetCurrentDir()
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')
- 这说明本目录下没有参与构建的文件
objs = []
,只需要遍历下级目录即可。
构建目录
- 使用
DefineGroup
创建 构建的目标,这里的 src 其实是个构建文件的列表,而构建文件的列表,是个 python 的列表,可以为空,可以为多个构建文件,由于SConscript
脚本是 Python 脚本,可以打一下参与构建的文件列表
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
小结
-
灵活的设计
SConscript
脚本,就像是设计 Makefile 文件,可以实现大工程的构建 -
由于
scons
只是构建工具,编译链接还是需要额外的编译工具链,如gcc
armcc
armclang
等 -
windows 下或者 Linux 环境下,需要配置一些环境变量,这些可以在 Kconfig 与 rtconfig.py 中进行配置