SCons:防止构造变量中的 $TEXT 扩展
当我调用构建器 Program(Target, Source, CXXFLAGS=CompileFlags)
时,CompileFlags 字符串的值包含 -Wl,-rpath,lib:$ORIGIN/../lib
导致 $ORIGIN 扩展为空字符串,而它应该按原样保留。
我尝试转义美元符号,在里面添加单引号,但没有任何帮助。
env['RPATH'] = Literal('lib:$ORIGIN/../lib')
也不起作用:它会生成
g++ -o main -Wl,-rpath=lib: /../lib
在命令行中,即使手册页说“添加到 RPATH 的路径不会以任何方式被 scons 转换”,所以即使没有 Literal() 它也应该工作,我猜。
那么如何添加包含 $TEXT 的编译器标志而不需要 SCons 尝试将其扩展为变量呢?
谢谢。
When I call a builder Program(Target, Source, CXXFLAGS=CompileFlags)
the value of CompileFlags string contains -Wl,-rpath,lib:$ORIGIN/../lib
causing $ORIGIN to be expanded to empty string, while it should be preserved as is.
I tried escaping the dollar sign, adding single quotes inside, nothing helps.
env['RPATH'] = Literal('lib:$ORIGIN/../lib')
also does not work: it produces
g++ -o main -Wl,-rpath=lib:/../lib
in command line even though the man page says "the paths added to RPATH are not transformed by scons in any way" so it supposed to work even without Literal(), I guess.
So how can I add a compiler flag containing $TEXT without SCons trying to expand it as a variable?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用双美元,如下所示:
You can use double dollars, like this:
我发现这可以解决扩展问题
如果您知道更合适/优雅的解决方案,请告诉我。
I found this can solve the expansion problem
Please, let me know if you aware of more proper/elegant solution without.
这个答案扩展了 jackhab 的答案,展示了如何在不同的上下文中执行字面上的美元符号,然后解释“黑魔法”的工作原理。我想分享我在一个小时的反复试验中学到的东西。
我的问题是如何将“$p”作为非常神秘的命令行的一部分发送到 Inno Setup,以自动让 Inno Setup 签署创建的安装程序(请参阅 https://stackoverflow.com/a/73045226/831520(如果您对此感兴趣)。我能让它工作的唯一方法是使用 jackhab 的双环境/文字技巧。这是我的 scons 代码:
现在的问题是,这实际上是如何工作的,为什么需要 $DOLLARP 和 $MYARGS?
其中很多都归结为 Literal() 的工作原理。 scons 文档非常简短:“指定的字符串将按原样保留,并且不会扩展构造变量。”所以人们会认为你可以做这样的事情:
但是这些都不起作用! env.Literal() 显然不会创建普通字符串,并且 scons 文档没有给出任何示例。那么,唯一的上下文似乎是 jackhab 和 mcinek 提供的上下文,它是对环境变量的赋值。
另一个问题是字符串替换不会立即完成(即 python 不会这样做);仅当 scons 以某种方式“处理”字符串时才会完成。 env.Literal() 确实保留了美元符号,但如果您随后在其他地方使用环境变量,则 scons 会再次“处理”该字符串并进行正常替换!
让我们看一下:
这将“$p”分配给$DOLLARP,但我们需要 env.Literal(),因此 scons 不认为 $p 是环境变量查找。
好吧,为什么我们需要第二次 env.Literal() 呢?因为scons又在“处理”了。如果没有它,args 中的“$DOLLARP”将立即被翻译为 $p,这意味着一旦我们第三次“处理”,scons 将尝试解释 $p。如果这听起来令人困惑,那么一旦我们查看第三个 scons 调用,就会更加清楚:
正如我之前所说, env.Execute(env.Literal(...)) 不起作用,因此我们传递 $MYARGS 代替。 scons 确实替换了我们创建的 $MYARGS 字符串,然后显然它通过在其中查找 $DOLLARP 并替换 $p 来进行第二次替换。值得庆幸的是, scons 不会进行第三遍,这就是 jackhab 的技巧。
我不知道为什么 scons 不只是实现 $$ ,而其他软件包似乎都是这样做的,而且会容易得多。但即使你不明白这个解释,只要尝试一下,它就会像魔术一样对你起作用。
This answer expand's jackhab's answer by showing how to do a literal dollar sign in a different context, and then explaining how the "black magic" works. I want to share what I learned in an hour of trial and error.
My problem was how to send "$p" to Inno Setup as part of a very cryptic command line to automate having Inno Setup sign the created setup program (see https://stackoverflow.com/a/73045226/831520 if you are interested in that). The only way I could get it to work was by using jackhab's double env/Literal trick. Here's my scons code:
Now the question is, how does this actually work, and why are $DOLLARP and $MYARGS necessary?
A lot of it boils down to how Literal() works. The scons documentation is very brief: "The specified string will be preserved as-is and not have construction variables expanded." So one would think you could do things like this:
But neither of these work! env.Literal() apparently doesn't create a normal string, and the scons documentation doesn't give any example. The only context, then, seems to be the context that jackhab and mcinek provide, which is an assignment to an environment variable.
Another issue is that the string substitution isn't done immediately (i.e., python doesn't do it); it's only done when scons "processes" the string in some way. env.Literal() DOES preserve a dollar sign, but if you then use the environment variable somewhere else, scons "processes" the string a second time and does its normal substitution!
So let's walk through it:
This assigns "$p" to $DOLLARP, but we need env.Literal() so scons doesn't think $p is an environment variable lookup.
Okay why do we need env.Literal() a second time? Because scons is "processing" again. Without it, the "$DOLLARP" inside args will immediately be translated into $p, which means once we "process" a 3rd time, scons will try to interpret $p. If this sounds confusing, this will be more clear once we look at the third scons invoke:
As I said before, env.Execute(env.Literal(...)) does NOT work, so we pass $MYARGS instead. scons DOES substitute our created $MYARGS string for that, then apparently it does a SECOND substitution pass by finding $DOLLARP in that and substituting $p. Thankfully, scons does NOT do a third pass, and therein lies jackhab's trick.
I have NO idea why scons didn't just implement $$ which is what every other software package seems to do and would be a ton easier. But even if you don't understand the explanation, just try it, and it should work like magic for you.