在gem5和NVMain中,都使用了scons工具进行编译。学习scons必须提上日程!
编译文件的基本步骤
在此之前,还需要复习一下编译文件的基本知识。编译文件大致可以分为预处理=>编译=>汇编=>链接四个步骤。
- 预处理:将给定的文件进行展开。展开宏定义以及include的文件。
- 编译过程:进行词法分析,语法分析,语义分析处理,生成中间代码,优化,然后生成汇编代码。
- 汇编:将汇编代码生成机器可执行的代码(即二进制),生成可重定位目标程序的.o文件。
- 链接:使用静态链接或者动态链接的方法加入程序执行需要依赖库的文件,最后生成一个可执行文件。
创建一个简单的helloworld.cpp文件。
使用g++ -E helloworld.cpp -o helloworld.ii
生成预处理文件(比源文件大非常多,因为iostream是一个非常大的header文件)。
使用g++ -S helloworld.ii -o helloworld.S
生成汇编代码。
-c
是执行汇编操作。
简单编译
创建一个Sconstruct文件,创建一个helloworld.cpp文件。对于scons工具来说,Sconstruct文件就相当于Makefile的作用一样,scons通过读取Sconstruct的内容来控制构建程序的流程。当然,Sconstruct与Makfile的区别在于前者使用的是Python脚本,而后者使用的是命令行。
使用Program函数能够生成可执行文件。
1 | Program('helloworld.cpp') |
在第三个示例中,相当于执行:
1 | scons |
当然,可以使用Glob函数指定规则匹配所有需要的文件。
在Program函数中可以指定target,source。
1 | src_files=Split('main.c file1.c file2.c') |
Program中还有LIBPATH,scons会从指定的目录中寻找库文件。
使用
1 | Object('helloworld.cpp') |
可以生成一个可重定位目标程序文件。
除了Program, Object,还有Library、StaticLibrary和SharedLibrary分别编译库文件、静态库以及动态库。
1 | C:\>scons |
可以看到,scons首先会读取所有的配置文件(主要指的是SConscript文件),然后执行它们,然后构建所有的target files。
节点对象
所有的builder方法都会返回一系列的node object,这些object可能是target file或者是file。
1 | Object('hello.cpp', CCFLAGS='-DHELLO') |
这样一般默认是在Linux系统下使用scons。
或者
1 | hello_list = Object('hello.cpp', CCFLAGS='-DHELLO') # 使用一个hello_list节点 |
hello_list
和goodbye_list
就是target object的节点。除了Object,还有File、Dir和Entry节点。
1 | object_list = Object('hello.c') |
可以使用该方法打印出相应的文件名。
环境
可以声明环境变量指定编译环境:
1 | import os |
有时候一个编译文件需要另一个文件构建的环境,这时候就需要使用Import
和Export
进行指定变量的输出。
编译选项
使用AddOption
函数进行选择。
1 | AddOption('--verbose', dest='verbose', action='store_true', |