2017-09-14 3 views
0

Selon le scons documentation, la méthode subst va interpoler récursivement les variables de construction. Cependant, il ne semble pas être récursive:Substitution de variable récursive avec 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") 

Prints:

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 est évaluée correctement lors de la compilation comme une partie de CPPDEFINES, mais pas dans la déclaration d'impression. Comment puis-je obtenir subst pour évaluer pleinement foobar?

+0

Je ne suis pas en mesure de le tester en ce moment, et je ne peux pas le trouver dans les documents, donc je ne peux pas poster une réponse complète, mais je pense que le $$ est échappé à un non évalué $. Essayez le même code, sauf avec e ["foobar"] = "$ {foo + $ {bar}}" –

Répondre

0

En utilisant l'expression

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

, comme suggéré par Kenny Ostrom, ne contribue pas non plus. Il génère une erreur de syntaxe car la méthode subst ne gère pas vraiment les accolades imbriquées. La vraie question est: Pourquoi voyons-nous différentes sorties lorsque nous utilisons subst directement dans le SConstruct, et quand il est utilisé dans une commande de construction?

Si l'on ajoute

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

au SConstruct, nous voyons la même sortie ${foo + 2} pour FOOBAR. La différence au moment de la construction est que la variable interne $_CPPDEFFLAGS est déclarée en fonction de la méthode _defines:

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

(à partir d'un print e.Dump()). Cette méthode _defines exécute toutes les variables par subst_path une seconde fois, de sorte que l'on peut utiliser des variables dans les chemins d'inclusion, par exemple.

Ainsi, la méthode subst fait la bonne chose, il vous suffit d'évaluer à nouveau:

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

pour obtenir la même sortie.

+0

Merci! Donc, je suppose que le mot _recursive_ dans le manuel est tout simplement faux? – Andak

+0

Eh bien, je dirais que cela vaut toujours pour le simple * remplacement textuel * des variables, ce qui est probablement la signification voulue du mot * interpolé * dans ce contexte. Mais le 'eval' des expressions uniques de Python est quelque peu spécial ...Si vous avez des idées pour rendre la différence plus évidente, n'hésitez pas à soumettre une demande d'extraction pour notre documentation. – dirkbaechle

+0

Désolé si cela est apparu comme impoli. Ce que je voulais dire, c'est que, pour moi, l'utilisation de _recursive_ suggère que je peux avoir des expressions complexes arbitraires qui seront évaluées _recursively_ par subst jusqu'à ce qu'il n'y ait plus de substitutions à faire. Mais ce que vous dites a aussi un sens. Je suppose que la clé ici est "récursivement _interpolates_". – Andak

0

Juste pour clarifier ce que dit dirkbaechle; nous pouvons y parvenir en simplement en procédant à l'interpolation et à l'évaluation en deux étapes distinctes (en appelant deux fois subst). Cela nous permet d'avoir des expressions complexes arbitraires:

# 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") 

Prints:

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. 

Merci encore, dirkbaechle!