我想让SCons
生成多个目标(直接在SConscript
中编号未知)。
我的目录如下:
headers/
Header1.h
Header2.h
Header3.h
Header4.h
meta/
headers_list.txt
现在我希望SConscript阅读headers_list.txt
,根据其headers/
目录中的内容选择文件(即它可能只包含Header1
和Header3
),那些我想用某个函数生成源代码。
我一直在尝试使用env.Command
来做到这一点,但问题是需要调用者指定目标列表,在调用env.Command
时,由于显而易见的原因而无法知道。
我唯一能想到的就是跑步:
for header in parse( headers_file ):
source = mangle_source_name_for_header( header )
env.Command( source, header, generator_action )
但这意味着每次调用parse( headers_file )
时我都会运行scons
。
如果解析成本高昂且文件不经常更改,则可以轻松缓存此步骤。
我缺少哪些SConsc构造/类/技术来实现缓存?
修改
看来我的问题与Build-time determination of SCons targets类似,但是没有人工虚拟文件的技术吗?
此外,即使使用临时文件,我也看不出我应该如何将target
变量从Command
传递给生成可变数目的目标的第二个变量,而不是迭代它们。
编辑2:
This看起来很有希望。
答案 0 :(得分:3)
我找到的唯一方法就是使用emitter
。
下面的例子包含3个文件:
./
|-SConstruct
|-src/
| |-SConscript
| |-source.txt
|-build/
<强> SConstruct
强>
env = Environment()
dirname = 'build'
VariantDir(dirname, 'src', duplicate=0)
Export('env')
SConscript(dirname+'/SConscript')
<强> src/SConscript
强>
Import('env')
def my_emitter( env, target, source ):
data = str(source[0])
target = []
with open( data, 'r' ) as lines:
for line in lines:
line = line.strip()
name, contents = line.split(' ', 1)
if not name: continue
generated_source = env.Command( name, [], 'echo "{0}" > $TARGET'.format(contents) )
source.extend( generated_source )
target.append( name+'.c' )
return target, source
def my_action( env, target, source ):
for t,s in zip(target, source[1:]):
with open(t.abspath, 'w') as tf:
with open(s.abspath, 'r') as sf:
tf.write( sf.read() )
SourcesGenerator = env.Builder( action = my_action, emitter = my_emitter )
generated_sources = SourcesGenerator( env, source = 'source.txt' )
lib = env.Library( 'functions', generated_sources )
<强> src/source.txt
强>
a int a(){}
b int b(){}
c int c(){}
d int d(){}
g int g(){}
<强>输出强>:
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
echo "int a(){}" > build/a
echo "int b(){}" > build/b
echo "int c(){}" > build/c
echo "int d(){}" > build/d
echo "int g(){}" > build/g
my_action(["build/a.c", "build/b.c", "build/c.c", "build/d.c", "build/g.c"], ["src/source.txt", "build/a", "build/b", "build/c", "build/d", "build/g"])
gcc -o build/a.o -c build/a.c
gcc -o build/b.o -c build/b.c
gcc -o build/c.o -c build/c.c
gcc -o build/d.o -c build/d.c
gcc -o build/g.o -c build/g.c
ar rc build/libfunctions.a build/a.o build/b.o build/c.o build/d.o build/g.o
ranlib build/libfunctions.a
scons: done building targets.
此外还有一件我不喜欢的事情,即每次执行headers_list.txt
时解析scons
。我觉得应该有一种方法来解析它只有文件改变。我可以手动缓存它,但我仍然希望有一些技巧可以让SCons为我处理缓存。
我找不到不重复文件的方法(a
和a.c
相同)。
一种方法是简单地在my_action中生成库而不是源(这是我在最终解决方案中使用的方法)。