SCons:防止构造变量中的 $TEXT 扩展

发布于 2024-12-01 02:36:15 字数 502 浏览 1 评论 0原文

当我调用构建器 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

橘亓 2024-12-08 02:36:15

您可以使用双美元,如下所示:

env['RPATH'] = Literal('lib:$ORIGIN/../lib')

You can use double dollars, like this:

env['RPATH'] = Literal('lib:$ORIGIN/../lib')
执妄 2024-12-08 02:36:15

我发现这可以解决扩展问题

    Env['ORIGIN'] = Literal('$ORIGIN')
    Env['RPATH'] = Literal('\'$ORIGIN/../lib:lib\'')

如果您知道更合适/优雅的解决方案,请告诉我。

I found this can solve the expansion problem

    Env['ORIGIN'] = Literal('$ORIGIN')
    Env['RPATH'] = Literal('\'$ORIGIN/../lib:lib\'')

Please, let me know if you aware of more proper/elegant solution without.

情绪少女 2024-12-08 02:36:15

这个答案扩展了 jackhab 的答案,展示了如何在不同的上下文中执行字面上的美元符号,然后解释“黑魔法”的工作原理。我想分享我在一个小时的反复试验中学到的东西。

我的问题是如何将“$p”作为非常神秘的命令行的一部分发送到 Inno Setup,以自动让 Inno Setup 签署创建的安装程序(请参阅 https://stackoverflow.com/a/73045226/831520(如果您对此感兴趣)。我能让它工作的唯一方法是使用 jackhab 的双环境/文字技巧。这是我的 scons 代码:

env['DOLLARP'] = env.Literal('$p')
args = '"/sStandard=' + getSignTool()
args += ' sign /a /f C:\Confidential\MyCompanysCertificate.p12 /p ' + password
args += ' /tr http://timestamp.sectigo.com/?td=sha256 /td sha256 /fd SHA256 $DOLLARP"'
args += ' "' + str(source[0]) + '"'
env['MYARGS'] = env.Literal(args)
env.Execute('iscc $MYARGS')

现在的问题是,这实际上是如何工作的,为什么需要 $DOLLARP 和 $MYARGS?

其中很多都归结为 Literal() 的工作原理。 scons 文档非常简短:“指定的字符串将按原样保留,并且不会扩展构造变量。”所以人们会认为你可以做这样的事情:

MyString = "iscc " + env.Literal("$p")
env.Execute(env.Literal("iscc $p"))

但是这些都不起作用! env.Literal() 显然不会创建普通字符串,并且 scons 文档没有给出任何示例。那么,唯一的上下文似乎是 jackhab 和 mcinek 提供的上下文,它是对环境变量的赋值。

另一个问题是字符串替换不会立即完成(即 python 不会这样做);仅当 scons 以某种方式“处理”字符串时才会完成。 env.Literal() 确实保留了美元符号,但如果您随后在其他地方使用环境变量,则 scons 会再次“处理”该字符串并进行正常替换!

让我们看一下:

env['DOLLARP'] = env.Literal('$p')

这将“$p”分配给$DOLLARP,但我们需要 env.Literal(),因此 scons 不认为 $p 是环境变量查找。

env['MYARGS'] = env.Literal(args)

好吧,为什么我们需要第二次 env.Literal() 呢?因为scons又在“处理”了。如果没有它,args 中的“$DOLLARP”将立即被翻译为 $p,这意味着一旦我们第三次“处理”,scons 将尝试解释 $p。如果这听起来令人困惑,那么一旦我们查看第三个 scons 调用,就会更加清楚:

env.Execute('iscc $MYARGS')

正如我之前所说, 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:

env['DOLLARP'] = env.Literal('$p')
args = '"/sStandard=' + getSignTool()
args += ' sign /a /f C:\Confidential\MyCompanysCertificate.p12 /p ' + password
args += ' /tr http://timestamp.sectigo.com/?td=sha256 /td sha256 /fd SHA256 $DOLLARP"'
args += ' "' + str(source[0]) + '"'
env['MYARGS'] = env.Literal(args)
env.Execute('iscc $MYARGS')

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:

MyString = "iscc " + env.Literal("$p")
env.Execute(env.Literal("iscc $p"))

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:

env['DOLLARP'] = env.Literal('$p')

This assigns "$p" to $DOLLARP, but we need env.Literal() so scons doesn't think $p is an environment variable lookup.

env['MYARGS'] = env.Literal(args)

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:

env.Execute('iscc $MYARGS')

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文