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不会干扰,因此条件编译指令不应出现任何问题.
解决此问题的最简单方法是为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中正常编译,因为别名处理将映射Actions到System.在XE7中你也很好,因为没有别名,并且IDE对Actions单元的存在感到满意,因此没有强迫修改uses子句.