Scons 二
依赖性:
和makefile一样,scons再次编译是取决于编译文件是否发生了变化。如果编译文件没有发生变化,那么scons是不会继续编译的。会出现如下打印: is up to date。就代表编译文件没有更新。
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.
在scons中我们可以指定相应的依赖规则,可以设置依赖 1 MD5签名是否改变,2 文件的操作时间是否改变:Decider(‘MD5’)和Decider(‘timestamp-match’) 或者两种Decider(‘'MD5-timestamp’)
AlwaysBuild:
如果我们想让一个目标文件不管有没有改动,每次执行scons的时候都必须build一次。那么可以采用AlwaysBuild的方法。
test=Program('test.c')
AlwaysBuild(test)
当采用上面的方法的时候,每次执行scons的时候都会执行一次对test的编译
scons: Reading SConscript files ...
cc=gcc
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的时候,可以看到不会再次编译test.o但是会编译test
scons: Reading SConscript files ...
cc=gcc
scons: done reading SConscript files.
scons: Building targets ...
gcc -o test test.o
scons: done building targets.
Environment:
在scons脚本中,通过设置environment来达到不同的编译效果。Scons与三种不同的环境类型可以影响scons的脚本行为
1 External Environment:
外部环境是用户运行SCons时用户环境中的变量集。这些变量可以通过Python os.environ字典在SConscript文件中找到
比如我们在Sconstruct中可以import os来导入python的os模块,然后调用os模块中的函数和功能。
2 Construction Environment:
构建环境是在SConscript文件中创建的一个不同的对象,它包含影响SCons如何决定使用什么操作来构建目标,甚至定义应该使用哪个目标的值。从哪个来源建造的。SCons最强大的特性之一是能够创建多个构造环境,包括从现有的构建环境克隆新的自定义构造环境的能力
创建方法如下:
env = Environment()
可以在创建的时候设置编译的参数。、
env = Environment(CC = 'gcc',CCFLAGS = '-O2')
如下例子:
scon=env.Program('scon_test.c',LIBS=['func'],CPPPATH=['./inc'],CCFLAGS='-O2')
scons: Reading SConscript files ...
cc=gcc
scons: done reading SConscript files.
scons: Building targets ...
gcc -o scon_test.o -c -O2 -Iinc scon_test.c
gcc -o scon_test scon_test.o -Lsrc -lfunc
scons: done building targets.
也可以从通过字典的方式来查看Environment中的配置
env = Environment()
print("cc=%s" % env['CC'])
通过Dictionary的方式可以得到所有Environment的字典集合。
env = Environment(FOO='foo', BAR='bar')
cvars = env.Dictionary()
for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']:
print("key = %s, value = %s" % (key, cvars[key]))
还可以通过subst的方式,并且访问的关键字前需要加上$符号。
env = Environment()
print("CC is: %s"%env.subst('$CC'))
默认配置:
所有的Builder, Program和Library功能都有一个默认的配置进行编译构建,这个默认配置就是DefaultEnvironment,通过调用和改写DefaultEnvironment中的配置可以达到修改默认配置的目的。比如下面的方式就可以使CC采用/usr/local/bin/gcc 来进行编译
DefaultEnvironment(CC='/usr/local/bin/gcc')
多个构建环境:
在一个工程下,可能我们需要对不同的文件进行不同方式的编译,比如有些文件需要带-O2的方式编译,有些文件需要带-g(debug)的方式编译。我们可以设定多个不同的Envrionment对象来达标此目的
opt = Environment(CCFLAGS = '-O2')
dbg = Environment(CCFLAGS = '-g')
opt.Program('foo', 'foo.c')
dbg.Program('bar', 'bar.c')
这样编译的时候就可以根据不同的Environment设置来进行编译
cc -o bar.o -c -g bar.c
cc -o bar bar.o
cc -o foo.o -c -O2 foo.c
cc -o foo foo.o
克隆环境:
前面讲到多个构建环境,每个环境的配置是独立的。但是如果我想在之前的一个环境上做扩展,那么就可以用到clone的功能。比如下面的方式。
env = Environment(CC = 'gcc')
opt = env.Clone(CCFLAGS = '-O2')
dbg = env.Clone(CCFLAGS = '-g')
env.Program('foo', 'foo.c')
o = opt.Object('foo-opt', 'foo.c')
opt.Program(o)
d = dbg.Object('foo-dbg', 'foo.c')
dbg.Program(d)
输出如下:通过在env上做克隆,并且加入自己的CCFLAGS变量,那么env, opt,dbg都采用的是gcc方式,但是编译参数完全不一样。
gcc -o foo.o -c foo.c
gcc -o foo foo.o
gcc -o foo-dbg.o -c -g foo.c
gcc -o foo-dbg foo-dbg.o
gcc -o foo-opt.o -c -O2 foo.c
gcc -o foo-opt foo-opt.o
Replace方法:
当需要修改Environment的配置的时候,可以用replace的方法
env = Environment(CCFLAGS = '-DDEFINE1')
env.Replace(CCFLAGS = '-DDEFINE2')
env.Program('foo.c')
也可以用replace方法去添加一个不在Environment中存在的配置
env = Environment()
env.Replace(NEW_VARIABLE = 'xyzzy')
print("NEW_VARIABLE = %s"%env['NEW_VARIABLE'])
Append方法:
想要在已有的配置里面添加选项可以用到append方法
env = Environment(CCFLAGS = ['-DMY_VALUE'])
env.Append(CCFLAGS = ['-DLAST'])
env.Program('foo.c')
这样在编译的时候就有多个编译选项出来
cc -o foo.o -c -DMY_VALUE -DLAST foo.c
cc -o foo foo.o
执行环境是在执行外部命令(例如编译器或链接器)以生成一个或多个目标
还有AppendUnique的方法可以保证每次的添加不重复,比如下面的-g,如果CCFLAGS中没有-g的选项,则可以添加进去
env.AppendUnique(CCFLAGS=['-g'])
如果想将某个配置放在最前面,则要采用Prepend
env = Environment(CCFLAGS = ['-DMY_VALUE'])
env.Prepend(CCFLAGS = ['-DFIRST'])
env.Program('foo.c')
-DFIRST将会在-DMY_VALUE的前面
cc -o foo.o -c -DFIRST -DMY_VALUE foo.c
cc -o foo foo.o
3 Execution Environment
执行环境中,参数都保存在$ENV变量中,这里面最重要的就是PATH变量。PATH变量在LINUX中的默认值为 /usr/local/bin:/bin:/usr/bin. 如果想扩展我们自己的PATH值,可以采用下面的方法对ENV值进行配置
path = ['/usr/local/bin', '/bin', '/usr/bin']
env = Environment(ENV = {'PATH' : path})
env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin']
也可以采用PrependENVPath和 AppendENVPath的方式添加
env.PrependENVPath('PATH','/home/maple/scons_prj')
env.AppendENVPath('LIB', '/usr/local/lib')
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2018-04-28 linux c编程:系统数据文件和信息