Delphi条件编译中的uses子句

ss2*_*006 11 delphi conditional-compilation delphi-2010 delphi-xe7

我试图修改我的Delphi 2010代码以在XE7中编译(并希望保留在2010年编译它的能力).因此,在我的mainform的单元中,我添加了条件指令.以下工作在2010年正常

uses 
  {$IF CompilerVersion >= 24}System.Actions, {$ELSE}Actnlist,{$IFEND}
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,  Dialogs;
Run Code Online (Sandbox Code Playgroud)

但是XE7会自动System.Actions在最后添加一个用于创建一个uses子句,该子句现在已经声明了两次System.Actions(见下文),并给出了一条错误消息[dcc32 Error] MyForm.pas(10): E2004 Identifier redeclared: 'System.Actions'.为什么XE7不接受条件指令中的单位?

uses 
  {$IF CompilerVersion >= 24}System.Actions, {$ELSE}Actnlist,{$IFEND}
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,  Dialogs,
  System.Actions; // <- automatically added
Run Code Online (Sandbox Code Playgroud)

Del*_*ics 14

正如Ken所说,接口uses子句将由IDE修改,实现这一过程的过程有点不复杂(正如您所发现的那样).同样的问题会影响项目使用条款.不幸的是,在Form/DataModule使用子句的情况下,要避免这种情况要困难得多.

您可以使用Unit Alias(请参阅David Heffernan的回答),但需要注意的是,如果您为IDE希望添加的单元创建别名,则IDE仍会添加对所需单元的引用,因为它无法识别别名为标识所需单位.别名系统单元将避免这种情况,因为它已经(隐含地)被每个单元使用.

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

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

 unit Actions;
 interface
 implementation
 end.
Run Code Online (Sandbox Code Playgroud)

您当然需要确保此单元不在项目的XE7版本的项目路径中.

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

 \Project Folder

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

     \placeholders
          Actions.pas
Run Code Online (Sandbox Code Playgroud)

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

     \placeholders
          \2010
               Actions.pas
          \XE7
               D2010UnitNotPresentInXE7.pas
Run Code Online (Sandbox Code Playgroud)

从创建自动/自我记录组织的角度来看,这种结构可能是可取的.

请注意,这仅用于处理Forms(或Frames等)的interface部分的uses子句中的单元引用.在非可视单元或实现部分中,IDE不会干扰,因此条件编译指令不应出现任何问题.

  • 我在这里有点困惑 - @Deltics似乎在说别名不起作用 - '你甚至不能使用单位别名',大卫说你可以.Deltics,我在读你吗? (2认同)

Dav*_*nan 9

解决此问题的最简单方法是为Delphi 2010项目添加单元别名.您需要为不同的Delphi版本使用不同的.dproj文件,但无论如何都需要这样做.

在Delphi 2010项目的单元别名设置中添加:

Actions=System
Run Code Online (Sandbox Code Playgroud)

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

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

uses 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
  Actions, Actnlist;
Run Code Online (Sandbox Code Playgroud)

这将在Delphi 2010中正常编译,因为别名处理将映射ActionsSystem.在XE7中你也很好,因为没有别名,并且IDE对Actions单元的存在感到满意,因此没有强迫修改uses子句.