SCON生成可变数量的目标

2024-04-25 21:48:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图让SCons生成多个目标(在SConscript中直接未知的数量)。在

我有这样的目录:

headers/
  Header1.h
  Header2.h
  Header3.h
  Header4.h
meta/
  headers_list.txt

现在我想让SConscript读取headers_list.txt,根据它的内容从headers/目录中选择文件(即它可能只包含Header1和{}),对于我想使用某个函数生成源代码的每个文件。在

我一直在尝试使用env.Command来实现这一点,但问题是它要求调用者指定targets list,这在调用env.Command时显然是未知的。在

我唯一能想到的就是跑步:

^{pr2}$

但这意味着每次调用parse( headers_file ),我都会运行parse( headers_file )。 如果解析成本很高,而且文件不经常更改,则可以轻松缓存此步骤。在

我缺少什么SConsc构造/类/技术来实现缓存?在

编辑:

我的问题似乎与Build-time determination of SCons targets相似,但是有没有没有没有人工虚拟文件的技术呢?在

而且,即使使用临时文件,我也不知道如何将生成可变数量目标的target变量传递给第二个将迭代这些目标的目标。在

编辑2:

This看起来很有前途。在


Tags: 文件目录envtxt目标数量parsescons
1条回答
网友
1楼 · 发布于 2024-04-25 21:48:43

我发现我能做到这一点的唯一方法是使用emitter。 以下示例由3个文件组成:

./
|-SConstruct
|-src/
| |-SConscript
| |-source.txt
|-build/

SConstruct

^{pr2}$

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.

还有一件事我不太喜欢,那就是每次执行scons时对headers_list.txt进行解析。我觉得应该有一种方法来解析它,只有当文件改变了。我可以手动缓存,但我仍然希望有一些技巧可以让SCons为我处理缓存。在

我找不到一个不复制文件的方法(a和{}是相同的)。 一种方法是在我的操作中生成库而不是源代码(这是我在最终解决方案中使用的方法)。在

相关问题 更多 >