Scons是依赖于python写的编译脚本,相对makefile来说,用起来更简单一些,不需要记太多的makefile语法。
安装方法:
1 安装python3,
2 执行sudo python -m pip install scons。
和makefile需要一个Makefile文件一样,Scons同样需要一个 Sconstruct文件。里面用来写编译脚本,语法和python一样的。为了验证Scons是否安装正确,可以新建一个Sconstruct文件,里面什么都不用写。进入到和Sconstruct同目录的地方。打开终端执行scons
出现下面的打印代表Scons已经安装OK。
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.
来编写一个测试文件,test.c
int
main()
{
printf("Hello, world!\n");
return 1;
}
编译这么一个文件,在Sconstruct中只需要Program(‘test.c’)一条语句就可以了
执行scons命令。可以看到如下输出,其实执行过程和Makefile没什么差别。但是语法相对简单了很多
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o test.o -c test.c
gcc -o test test.o
scons: done building targets.
执行scons -c就可以清理掉所有的目标文件,效果等同于make clean.
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed test.o
Removed test
scons: done cleaning targets.
如果只想出.o文件,可以用命令Object(‘test.c’)
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o test.o -c test.c
scons: done building targets.
SConstruct中的语法虽然是python格式的。但是执行顺序和在代码中调用的顺序是不一样的。比如下面的SConstruct文件
print("Generate test.c")
Program('test.c')
print("Generate test1.c")
Program('test1.c')
下面是执行结果,可以看到首先是打印的print中的语句,然后是再执行Build的步骤。
scons: Reading SConscript files ...
Generate test.c
Generate test1.c
scons: done reading SConscript files.
scons: Building targets ...
gcc -o test.o -c test.c
gcc -o test test.o
gcc -o test1.o -c test1.c
gcc -o test1 test1.o
scons: done building targets.
链接library:
在代码开发中,经常会import其他团队或者是已经存在的模块中的函数。这就需要链接其他的目标文件。
在src中文件中有func.o文件。Func中代码如下:
#include <stdio.h>
void print_in()
{
printf("print_info\n");
}
在main.c中引用了print_in函数
#include <stdio.h>
void main()
{
print_in();
printf("hello world\n");
}
Sconstruct脚本如下
from SCons.Script import *
from scons.SCons import *
env = Environment()
env.Append(LIBPATH=['./src']) //设置LIBPATH,告诉scons去哪个路径找library
env.Program('scon_test.c',LIBS=['func']) //在设置要import的LIBS, 告诉scons找哪个library
执行脚本如下。在gcc中设置了-L和-l的配置
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o scon_test.o -c scon_test.c
scon_test.c: In function 'main':
scon_test.c:7:5: warning: implicit declaration of function 'print_in'; did you mean 'printf'? [-Wimplicit-function-declaration]
print_in();
^~~~~~~~
printf
gcc -o scon_test scon_test.o -Lsrc -lfunc
scons: done building targets.
同样的如果我们要去其他路径查找.h的头文件,也可以通过设置CPPATH参数。
Main.c中include了var.h
#include <stdio.h>
#include "var.h"
void main()
{
printf("var=%d\n",para);
printf("hello world\n");
}
var.h在inc路径下面
#ifndef __var_h__
#define para 3
#define __var_h__
#endif
Sconstruct文件,通过设置CPPPATH就可以告诉scons去哪查找头文件
from SCons.Script import *
from scons.SCons import *
env = Environment()
print("cc=%s" % env['CC'])
env.Program('scon_test.c', CPPPATH=['./inc'])
执行结果如下:可以看到添加了-I的配置
scons: Reading SConscript files ...
cc=gcc
scons: done reading SConscript files.
scons: Building targets ...
gcc -o scon_test.o -c -Iinc scon_test.c
gcc -o scon_test scon_test.o
scons: done building targets.