条件编译的“else”

28
在AS3中,你可以将常量传递给编译器。
-define+=CONFIG::DEBUG,true

并且可以像下面这样将其用于条件编译:

CONFIG::DEBUG {
   trace("This only gets compiled when debug is true.");
}

我正在寻找类似于 #ifndef 的东西,以便否定 debug 的值并将其用于有条件地添加 release 代码。到目前为止,我找到的唯一解决方案是在 adobe 的条件编译文档中,由于我的调试和发布配置是互斥的,所以我不喜欢同时拥有 DEBUG 和 RELEASE 常量的想法。

此外,这种格式可以工作,但我假设它在运行时运行检查,这不是我想要的:

if (CONFIG::DEBUG) {
   //debug stuff
}
else {
   //release stuff
}

我也考虑过像这样做,但这仍然不是我所希望的优雅解决方案:

-define+=CONFIG::DEBUG,true -define+=CONFIG::RELEASE,!CONFIG::DEBUG

提前感谢您 :)

4个回答

22

这个很好用,并且会删除不能运行的代码:

if (CONFIG::DEBUG) {
   //debug stuff
}
else {
   //release stuff
}

但是这将在运行时评估:

if (!CONFIG::DEBUG) {
   //release stuff
}
else {
   //debug stuff
}

mxmlc 显然只能评估文字字面量的布尔值,而不能评估任何表达式,包括简单的not表达式。


请问您能否提供一份文档报价? - tzuchien.chiu
随着2020年AIR 33的推出,这两个示例都在运行时进行评估 - 在if和else块中引用的类将被编译,无论常量是true还是false。克里斯的答案(没有IF语句的CONFIG :: DEBUG)在编译时进行评估。 - Sarah Northway

8

1
看起来很合理。另一方面,Flash/Flex编译器可能会非常愚蠢,所以像你说的那样,如果性能真的很重要,我会在使用之前进行检查。 - aaaidan
3
-1. if/else语句结构无法正常工作。简单的测试可证明:将一个较大的文件[嵌入]在if/else块中,如果输出文件大小相应发生变化,则说明它有效,否则无效。此外,这样的if/else块在函数外使用会产生语法错误,这导致代码块不会被剥离! - bummzack
是的,我认为这种技术太过于依赖优化器的副作用。条件编译要好得多。如果您需要类似#ifndef的东西,请参见我的下面的答案。 - Chris Hill
似乎我的回答没有被很好地理解,它使用的是在问题中提到的 if (CONFIG::DEBUG) {.. 而不是任意的 if 构造。这是根据编译器标志的条件编译,完全和获得赞同的答案一样,只是没有 if (! CONFIG:: DEBUG) 部分。 - Patrick

6
虽然Patrick的回答符合问题的要求,但它并不能涵盖所有的使用情况。如果你在一个允许使用if/else语句的代码区域中,则这是一个很好的答案,但是如果你所处的地方不允许使用if/else语句,则你需要一个更好的解决方案。例如,你可能想要像这样在一个类中声明常量:
private var server:String = "http://localhost/mystagingenvironment";

或者进行实时发布:
private var server:String = "http://productionserver.com";

(这只是一个示例,我并不主张将其用作生产代码。)
我使用xml配置文件,并使用loadConfig+="myconfig.xml"来进行配置,而不是传递大量的命令行参数。因此,在您的xml配置文件的部分中:
<define>
    <name>CONFIG::debug</name>
    <value>false</value>
  </define>
<define>
    <name>CONFIG::release</name>
    <value>!CONFIG::debug</value>
</define>

这适用于所有的使用情况:

CONFIG::debug
{
    private var server:String = "http://localhost/mystagingenvironment";
}
CONFIG::release
{
    private var server:String = "http://productionserver.com";
}

这样做的额外好处是在应用程序之间保持一致性。与帕特里克的答案不同,它也不依赖于“优化”标志为真(尽管我认为可以假定99.999999%的所有swf都具有optimize = true,但当优化器破坏我的AS3时,我只将其设置为false)。
它的缺点是它并没有编译所有的代码路径,仅包括已包含的那些。因此,如果您不使用构建服务器创建发布版本并在出现错误时通知您,请准备好在进行发布构建时遇到意外错误(“但在调试中它已经编译了!该死,我现在需要启动它!”)。

这似乎是最优雅的解决方案。较少的编译器参数,以及在外部XML文件中进行良好的分离。 为了使其工作,XML文件应包含一个额外的“flex-config”根元素,如此处所示:http://help.adobe.com/en_US/air/build/WSfffb011ac560372f2012b5a4128cca83a39-8000.html。我还发现了这个:http://www.flashdevelop.org/community/viewtopic.php?f=13&t=9696 它使用了一个'append=true'属性。 我尝试了所有这些方法,但我的应用程序仍然不能像没有xml参数时那样工作。虽然它确实编译了。有人遇到类似的问题吗? - Michahell
我似乎无法编辑我的先前评论,但是:重新阅读缺点后,它有意义了。我正在为我的项目使用其他源路径,包括一个库项目。另外要补充的是:不仅发布版本会出问题,常规调试版本也会出问题:(这完全是糟糕的,因为这是一种很好且干净的条件编译方式。唉,那就快速、肮脏、有效吧。 - Michahell
很抱歉听到你遇到了问题。我在使用XML文件方面运气不错,当你在处理大型项目时,比如说有5个开发环境时,它们非常好用!这是一个我用于小型原型的Flex配置XML示例。这与我在大型项目中使用的相似:http://enemyhideout.com/example_flex_configs/game-flex-config.xml - Chris Hill
谢谢。我看到我没有在这里更新我的评论,但是我一段时间前就用ANT / Jenkins解决了这个问题。这确实是在所有地方进行条件编译的好方法(相同的代码库,不同的IOS / Android构建)。再次感谢! - Michahell

0

以下是关于Chris Hill答案的我的意见(这也是我经常使用的解决方案):似乎使用loadConfig+="myconfig.xml"选项会使编译器在Flex SDK目录中搜索myconfig.xml文件,而-load-config+=myconfig.xml选项会使它在项目目录中搜索myconfig.xml文件,这是我强烈偏好的行为,因为你可以很容易地将该文件与项目源代码一起分发...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接