现在的位置: 首页 > 综合 > 正文

SCons用户指南第八章:自动将命令行选项赋值给Construction变量

2012年01月05日 ⁄ 综合 ⁄ 共 3550字 ⁄ 字号 评论关闭

1、将选项合并到环境中:MergeFlags函数

SCons的construction环境有一个MergeFlags方法,此方法将一个值的字典合并到construction环境中。MergeFlags将字典中的每个值看做一个选项列表。如果一个选项已经在construction环境变量中存在了,MergeFlags将不会重复设置这个选项。

当合并选项到任何一个名字在PATH中的变量的时候,MergeFlags保持选项在最左端出现,应为目录路径列表中,第一个出现占主要地位。当合并选项到任何其他变量名的时候,MergeFlags保持选项在右端出现,因为在命令行选项列表中,最后出现的占主要地位。

env = Environment()

env.Append(CCFLAGS = '-option -O3 -O1')

flags = { 'CCFLAGS' : '-whatever -O3' }

env.MergeFlags(flags)

print env['CCFLAGS']

 

% scons -Q

['-option', '-O1', '-whatever', '-O3']

scons: `.' is up to date.

上面例子中$CCFLAGS的默认值是一个内部SCons对象,会自动将我们指定的选项转换成一个字符串加入到列表中。

env = Environment()

env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include'])

flags = { 'CPPPATH' : ['/usr/opt/include', '/usr/local/include'] }

env.MergeFlags(flags)

print env['CPPPATH']

  

% scons -Q

['/include', '/usr/local/include', '/usr/include', '/usr/opt/include']

scons: `.' is up to date.

上面例子中$CPPPATH的默认值是一个Python列表,所以我们必须在传递给MergeFlags函数的字典中将值指定为一个列表。

如果不是传递一个字典而是其他的东西,会调用ParseFlags方法将其转换为一个字典:

env = Environment()

env.Append(CCFLAGS = '-option -O3 -O1')

env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include'])

env.MergeFlags('-whatever -I/usr/opt/include -O3 -I/usr/local/include')

print env['CCFLAGS']

print env['CPPPATH']

 

% scons -Q

['-option', '-O1', '-whatever', '-O3']

['/include', '/usr/local/include', '/usr/include', '/usr/opt/include']

scons: `.' is up to date.

 在上面的例子中,ParseFlags方法已经将选项排序赋值给相对应的变量,然后返回一个字典给MergeFlags方法。


2、将编译参数分离成变量:ParseFlags函数

当编译程序的时候,对于不同类型的选项,SCons有一个令人迷惑的construction变量数组。对于一个特殊的选项,有时候你可能不知道该使用哪一个变量。

SCons construction环境有一个ParseFlags方法,该方法接受一个命令行选项集合,然后将他们分发给合适的construction变量。

ParseFlags返回一个包含了construction变量和值的字典。正常情况下,这个字典将会传递给MergeFlags方法,将选项合并到construction环境中去,但是如果想要提供额外的功能,这个字典可以被编辑。

env = Environment()

d = env.ParseFlags("-I/opt/include -L/opt/lib -lfoo")

for k,v in sorted(d.items()):

if v:

print k, v

env.MergeFlags(d)

env.Program('f1.c')

 

% scons -Q

CPPPATH ['/opt/include']

LIBPATH ['/opt/lib']

LIBS ['foo']

cc -o f1.o -c -I/opt/include f1.c

cc -o f1 f1.o -L/opt/lib -lfoo

因为假设flags是用于GCC的,那么不认别的flags会被放置到$CCFLAGS中,用于编译C和C++:

env = Environment()

d = env.ParseFlags("-whatever")

for k,v in sorted(d.items()):

if v:

print k, v

env.MergeFlags(d)

env.Program('f1.c')

 

% scons -Q

CCFLAGS -whatever

cc -o f1.o -c -whatever f1.c

cc -o f1 f1.o

ParseFlags也接受一个字符串列表作为输入:

env = Environment()

d = env.ParseFlags(["-I/opt/include", ["-L/opt/lib", "-lfoo"]])

for k,v in sorted(d.items()):

if v:

print k, v

env.MergeFlags(d)

env.Program('f1.c')

  

% scons -Q

CPPPATH ['/opt/include']

LIBPATH ['/opt/lib']

LIBS ['foo']

cc -o f1.o -c -I/opt/include f1.c

cc -o f1 f1.o -L/opt/lib -lfoo

如果一个字符串以!开始,这个字符串将被传递给shell执行。命令的输出然后被解析:

env = Environment()

d = env.ParseFlags(["!echo -I/opt/include", "!echo -L/opt/lib", "-lfoo"])

for k,v in sorted(d.items()):

if v:

print k, v

env.MergeFlags(d)

env.Program('f1.c')

 

% scons -Q

CPPPATH ['/opt/include']

LIBPATH ['/opt/lib']

LIBS ['foo']

cc -o f1.o -c -I/opt/include f1.c

cc -o f1 f1.o -L/opt/lib -lfoo

ParseFlags会定期更新新的选项。


3、查找已经安装的库信息:ParseConfig函数

配置正确的选项来编译引用了其他库的程序,尤其引用的是共享库,是非常复杂的。为了帮助解决这种情况,许多名字以config结尾的工具返回需要使用这些库的命令行选项;例如,使用一个名字为lib的库的命令行选项将会被叫做lib-config的工具找到。

最近的一个惯例是这些选项通过通用的pkg-config工具是可用的,此程序有通用的框架,错误处理,所以所有的包创建者需要做的就是为它的特殊的包提供字符串集合。

SCons construction环境有一个ParseConfig方法,此方法会执行*config工具并且基于特定命令返回的命令行选项配置合适的construction变量。

env = Environment()

env['CPPPATH'] = ['/lib/compat']

env.ParseConfig("pkg-config x11 --cflags --libs")

print env['CPPPATH']

SCons将会执行特定的命令字符串,解析结果flags,然后将flags增加到合适的环境变量: 

% scons -Q

['/lib/compat', '/usr/X11/include']

scons: `.' is up to date.

上面的例子中,SCons增加include目录到CPPPATH。

注意到,使用MergeFlags方法将选项同存在的选项合并,每一个选项在construction变量中仅仅出现一次:

env = Environment()

env.ParseConfig("pkg-config x11 --cflags --libs")

env.ParseConfig("pkg-config x11 --cflags --libs")

print env['CPPPATH']

 

% scons -Q

['/usr/X11/include']

scons: `.' is up to date.

 

【上篇】
【下篇】

抱歉!评论已关闭.