Scons和Kconfig快速入门
SifliSDK提供了一个Env配置工具,这个工具里就已经带有SCons和Python,因此在Windows平台使用SCons并不需要安装。SifliSDK在scons基础上添加了一些脚本库函数,简化用户的项目配置。
1. 项目文件结构
SCons使用SConscript和SConstruct文件来组织源码结构,通常来说一个项目只有一 SConstruct,在项目根目录中,但是会有多个SConscript。一般情况下,每个存放有源代码的子目录下都会放置一个SConscript。用户可以参考 example\uart\project\ec-lbxxx ,看到项目文件结构。
SifliSDK 为每个项目单独创建了一个名为 rtconfig.py 的文件。因此每一个项目目录下都会存在下面三个文件:rtconfig.py ,SConstruct 和 SConscript ,它们控制项目的编译。一个项目中只有一个 SConstruct 文件,但是却可能会有多个 SConscript 文件,可以说 SConscript 文件是组织源码的主力军。
SifliSDK使用menuconfig来配置项目,每个项目有一个Kconfig,在项目根目录中,作为配置选项的起点,配置完成后会在项目根目录生成 .config 和 rtconfig.h ,分别用于Scons脚本和c文件。
SifliSDK大部分源码文件夹下也存在 SConscript 文件,这些文件会被项目根目录下的 SConscript 文件 “找到” 从而将 .config/rtconfig.h 中定义的宏对应的源代码加入到编译器中来。
SCons编译项目首先执行的是 SConstruct. 在用户项目的 Sconstruct 可以配置一些项目的选项,和menuconfig工具生成的项目配置.config配合, SifliEnv()
函数会设置相应的默认编译选项。用户如果需要强制修改相关编译/链接的选项,可以改变Environment
()函数中相应的参数。
3. SCons的基本功能
在Env工具中直接输入scons
命令直接编译项目,默认使用ARM CLANG编译器。SifliSDK根目录有 set_env.bat , 里面会设定编译器目录。
如果需要自己制定编译器,可以在修改 set_env.bat 里面的命令指定:
set RTT_CC = keil
set RTT_EXEC = C:/Keilv5
scons命令 该命令不仅可以完成基本的编译,还可以生成MDK/IAR/VS 工程,在后边增加不同参数可以实现不同效果。
-s
参数,不会打印具体的内部命令。-c
参数,清除编译目标,清除临时文件和目标文件。--target=XXX
参数,如果使用mdk/iar来进行项目开发,当修改了 rtconfig.h 打开或者关闭某些组件时,需要使用该参数来重新生成对应的定制化工程。然后在mdk/iar中进行编译下载。
警告
注意:要生成MDK或者IAR的工程文件,前提条件是项目目录存在一个工程模版文件,然后scons
才会根据这份模版文件加入相关的源码,头文件搜索路径,编译参数,链接参数等。而至于这个工程是针对哪颗芯片的,则直接由这份工程模版文件指定。所以大多数情况下,这个模版文件是一份空的工程文件,用于辅助 SCons 生成 project.uvprojx 或者 project.eww 。为了方便客户,如果没有找到 project.uvprojx , SiFliSDK会使用一份默认的模板用于生成 project.uvprojx ,用户如果不想使用默认的模板(例如添加自己的编译选项),可以将 SifliSDK\tools\build\template 下面的 template.uvprojx 拷贝到项目目录,作为自己的项目模板,添加自己特定的改变。
-jN
参数,多线程编译目标,在多核计算机上可以使用此命令加快编译速度。一般来说一颗 cpu 核心可以支持 2 个线程。双核机器上使用scons -j4
命令即可。--verbose
参数,默认情况下,使用scons
命令编译的输出不会显示编译参数,使用该参数,会显示编译参数。
4. SCons 内置函数
如果想要将自己的一些源代码加入到 SCons 编译环境中,一般可以创建或修改已有 SConscript 文件。
SConscript 文件可以控制源码文件的加入,并且可以指定文件的Group(与MDK/IAR等IDE中的Group的概念类似)。
SCons提供了很多内置函数可以帮助我们快速添加源码程序,利用这些函数,再配合一些简单的Python语句我们就能随心所欲向项目中添加或者删除源码。下面将简单介绍一些常用函数。实际上每个 SConscript 文件就是一个python文件。
GetCurrentDir()
函数,获取当前路径。Glob('*.c')
函数,获取当前目录下所有C文件。修改参数中的后缀,可以匹配当前目录下的所有某类型的文件。GetDepend(macro)
函数,该函数定义在tools目录下的脚本文件中,它会从 rtconfig.h 文件读取配置信息,其参数为 rtconfig.h 中的宏名。如果 rtconfig.h 打开了某个宏,则这个方法(函数)返回真,否则返回假。Split(str)
函数,将字符串str分割成一个列表list。DefineGroup(name, src, depend,**parameters)
函数,这是基于 SCons 扩展的一个方法(函数)。DefineGroup用于定义一个组件。组件可以是一个目录(下的文件或子目录),也是后续一些IDE工程文件中的一个Group或文件夹。parameter可以添加:LIBS=<some.lib> 将特定lib链接进入项目
LIBPATH=<some path> 在特定目录中放入.lib
LIBRARY=<some.lib> 将所有group 中源代码编译链接,生成 .lib
INSTALL_PATH=<some path> 将生成的.lib安装到特定目录中
CCFLAGS=<more CC flags> 添加编译选项
CPPPATH=<some folder> 添加C语言头文件搜索目录
CPPDEFINES=<more macro> 添加C语言宏定义
LINKFLAGS=<more link flags> 添加链接选项
ASFLAGS=<more assembly flags> 添加汇编选项