2017-09-14 144 views
0

根据scons documentationsubst方法将递归插值构造变量。然而,这似乎并没有递归:递归变量替换env.subst

e = Environment(CPPDEFINES = ["FOOBAR=${foobar}"]) 

e["foo"] = 1 
e["bar"] = "${foo + 1}" 
e["foobar"] = "$${foo + ${bar}}" 

# I want this to print "foobar: 3" 
print "foobar:", e.subst("${foobar}") 

e.Program("test.c") 

打印:

scons: Reading SConscript files ... 
foobar: ${foo + 2} 
scons: done reading SConscript files. 
scons: Building targets ... 
gcc -o test.o -c -DFOOBAR=3 test.c 
gcc -o test test.o 
scons: done building targets. 

foobar编译为CPPDEFINES的一部分时被正确评估,而不是在print语句。我怎样才能让subst完全评估foobar?

+0

我目前无法对其进行测试,并且我无法在文档中找到它,因此我无法发布完整答案,但我认为$$已被转移到非易失性存储器中,评估$。尝试使用相同的代码,但使用e [“foobar”] =“$ {foo + $ {bar}}” –

回答

0

使用表达

e["foobar"] = "${foo + ${bar}}" 

,由肯尼·奥斯特罗姆建议,也没有帮助。它会产生语法错误,因为subst方法并没有真正处理嵌套大括号。

实际的问题是:为什么我们直接在SConstruct中使用subst,以及何时在构建命令中使用它时,会看到不同的输出?

如果再加

print "CPPDEFINES:", e.subst("$CPPDEFINES") 

SConstruct,我们看到了相同的输出${foo + 2}FOOBAR。在生成时不同的是,该内部变量$_CPPDEFFLAGS_defines方法方面宣称:

'_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}' 

(从print e.Dump())。例如,这个_defines方法第二次通过subst_path运行所有变量,例如,可以在包含路径中使用变量。

所以subst方法做正确的事,你就必须重新评估:

print "foobar:", e.subst(e.subst("${foobar}")) 

得到相同的输出。

+0

谢谢!所以我想手册中的_recursive_单词是错的? – Andak

+0

那么,我认为它仍然适用于变量的简单*文本替换*,这可能是在这种情况下单词* interpolated *的预期含义。但是单个Python表达式的'eval'有点特别......如果您有关于使差异更明显的想法,请随时提交我们文档的拉取请求。 – dirkbaechle

+0

很抱歉,如果这是粗鲁的。我的意思是,对我来说,使用_recursive_提示我可以有任意的复杂表达式,它将通过'subst'进行_recursively_求值,直到不再有替换。但是你说什么也是有道理的。我猜这里的关键是“递归_interpolates_”。 – Andak

0

只是为了说清楚dirkbaechle说了些什么;我们可以通过 来实现这一点,只需在两个单独的步骤中进行插值和评估(通过调用subst两次)。这让我们不得不任意复杂的表达式:

# Notice how we wrap foobar in $$ 
e = Environment(CPPDEFINES = ["FOOBARBAZ=$${${foobarbaz}}"]) 

e["foo"] = 1 
e["bar"] = "($foo + 1)" 
e["foobar"] = "($foo + $bar)" 
e["foobarbaz"] = "($foobar + $foobar)" 

print "foobarbaz after substituting once:", e.subst("$${${foobarbaz}}") 
print "foobarbaz after substituting twice:", e.subst(e.subst("$${${foobarbaz}}")) 

e.Program("test.c") 

打印:

scons: Reading SConscript files ... 
foobarbaz after substituting once: ${((1 + (1 + 1)) + (1 + (1 + 1)))} 
foobarbaz after substituting twice: 6 
scons: done reading SConscript files. 
scons: Building targets ... 
gcc -o test.o -c -DFOOBARBAZ=6 test.c 
gcc -o test test.o 
scons: done building targets. 

再次感谢,dirkbaechle!