uses子句中的Delphi条件编译

uses子句中的Delphi条件编译,delphi,delphi-2010,conditional-compilation,delphi-xe7,Delphi,Delphi 2010,Conditional Compilation,Delphi Xe7,我试图修改我的Delphi2010代码以在XE7中编译(并希望保留在2010年编译它的能力)。因此,在容纳我的主窗体的单元中,我添加了条件指令。以下作品将于2010年问世 uses {$IF CompilerVersion >= 24}System.Actions, {$ELSE}Actnlist,{$IFEND} Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; 但是XE7会在

我试图修改我的Delphi2010代码以在XE7中编译(并希望保留在2010年编译它的能力)。因此,在容纳我的主窗体的单元中,我添加了条件指令。以下作品将于2010年问世

uses 
  {$IF CompilerVersion >= 24}System.Actions, {$ELSE}Actnlist,{$IFEND}
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,  Dialogs;
但是XE7会在末尾自动添加一个
System.Actions
,以创建一个uses子句,该子句现在声明了两次System.Actions(见下文),并给出一条错误消息
[dcc32 error]MyForm.pas(10):E2004标识符重新声明:“System.Actions”
。为什么XE7不接受条件指令中的单元

uses 
  {$IF CompilerVersion >= 24}System.Actions, {$ELSE}Actnlist,{$IFEND}
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,  Dialogs,
  System.Actions; // <- automatically added
使用
{$IF CompilerVersion>=24}System.Actions,{$ELSE}Actnlist,{$IFEND}
窗口、消息、系统工具、类、图形、控件、窗体、对话框、,

系统操作;// 正如Ken所说,interface uses子句将由IDE修改,而实现这一点的过程并不复杂(正如您所发现的)。同样的问题也会影响项目uses子句。不幸的是,在Form/datamoduleuses子句的情况下,这很难避免

您可以使用单元别名(参见David Heffernan的回答),但需要注意的是,如果您为IDE希望添加的单元创建了别名,那么IDE仍然会添加对所需单元的引用,因为它不会将别名识别为标识所需单元的别名。对系统单元使用别名可以避免这种情况,因为每个单元都已(隐式)使用它

另一种方法是从uses列表中删除所有此类条件,而是根据需要创建占位符单元,这样,您希望在项目中使用的不同编译器都可以通过每个IDE坚持要求的列表中组合的单一用法列表来满足(IDE不会从使用列表中删除未使用的单元,这通常是一种抱怨,但在这种情况下,实际上有助于解决您的问题)

在这种情况下,在Delphi 2010项目中创建一个空的操作单元:

 unit Actions;
 interface
 implementation
 end.
当然,您需要确保该单元不在XE7版本项目的项目路径中

实现这一点的一种方法是确保空的Actions.pas单元未明确列在DPR uses列表中,而是放在项目源的子文件夹中(例如“占位符”)。然后,您可以将此子文件夹添加到Delphi 2010版本的项目搜索路径中,而不是XE7版本:

 \Project Folder

     project2010.dpr
     project2010.dproj
     projectXE7.dpr
     projectXE7.dproj

     \placeholders
          Actions.pas
如果发现每个不同版本都需要占位符,则需要单独的占位符文件夹。您可以创建更多特定于版本的子文件夹,例如:

     \placeholders
          \2010
               Actions.pas
          \XE7
               D2010UnitNotPresentInXE7.pas
从创建自动/自记录组织的角度来看,这种结构可能是可取的


请注意,这仅用于处理表单(或框架等)的接口部分的使用子句中的单元引用。在非可视单元或实现部分中,IDE不会干扰,因此条件编译指令不会出现任何问题。

是否有问题

{$IF CompilerVersion < 24}Actnlist,{$IFEND}
{$IF compilervision<24}Actnlist,{$IFEND}
或者这是一个学术争论

附录

然后在2010编译路径中添加一个不包含任何内容的伪
System.Actions.dcu

我的理论是IDE会坚持插入
uses…System.Actions
,2010有它想要的,XE7有它想要的


但是我没有XE7,所以无法测试它。

解决此问题的最简单方法是在Delphi 2010项目中添加一个。对于不同的Delphi版本,您需要使用不同的.dproj文件,但无论如何都需要这样做

在Delphi 2010项目的单位别名设置中,添加以下内容:

Actions=System
我使用
System
作为别名目标,因为
System
单元自动包含在每个Delphi单元中,因此别名包含是良性的。这是我能想到的使编译器有效忽略uses子句中的条目的最简单方法

然后您可以像这样声明您的uses子句:

uses 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
  Actions, Actnlist;
这将在Delphi 2010中很好地编译,因为别名处理将映射到
系统
。在XE7中,您也很好,因为没有别名,IDE对
操作
单元的存在感到满意,因此没有修改uses子句的强制力。

我们也有同样的问题。。。 最简单的方法是这样做:

{$IF CompilerVersion < 24}{$ELSE}System.Actions,{$IFEND}
{$IF CompilerVersion >= 24}{$ELSE}Actnlist,{$IFEND}
{$IF compilervision<24}{$ELSE}System.Actions,{$IFEND}
{$IF CompilerVersion>=24}{$ELSE}Actnlist,{$IFEND}
如果在旧的IDE中打开该文件,您可能会看到一个错误,该错误表示未找到“unit X”,但它将编译良好,并且不会执行自动添加。 它看起来不太好,但它工作得很好

亲切问候,


Bernd

因为接口在表单相关单元中使用子句属于IDE本身,并且它将在当前版本中为放置在表单上的任何组件添加所需内容。克服这一问题的唯一方法是从表单中删除组件,将声明放在
private
部分,而不是默认的部分de>发布了一个,并在运行时创建组件。你是在和IDE战斗,你不会赢得这场战斗。但是我已经拥有了所有需要的单位,不是吗?Delphi正在处理
{$IF compilervision>=24}系统。Actions{$IFEND}
部分。如果我输入类似(`{$IF compilervision>=24}系统。Action*s{$IFEND}它会抱怨。因此,它知道接口中存在System。Action使用。可能是IDE和编译器不同步吗?IDE不知道条件定义。它只知道您有一个特定的组件