11

我正在尝试修改我的 Delphi 2010 代码以在 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 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
4

4 回答 4

14

正如 Ken 所说,IDE 将修改 interface uses 子句,实现这一点的过程并不复杂(正如您所发现的那样)。同样的问题会影响项目使用条款。不幸的是,在 Form/DataModule 使用子句的情况下,这很难避免。

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

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

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

 unit Actions;
 interface
 implementation
 end.

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

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

 \Project Folder

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

     \placeholders
          Actions.pas

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

     \placeholders
          \2010
               Actions.pas
          \XE7
               D2010UnitNotPresentInXE7.pas

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

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

于 2014-10-02T00:25:34.833 回答
9

解决此问题的最简单方法是为您的 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 中编译良好,因为别名处理将映射ActionsSystem. 在 XE7 中你也很好,因为没有别名,IDE 对Actions单元的存在感到满意,因此不会强迫修改 uses 子句。

于 2014-10-02T07:08:31.610 回答
1

会不会有什么问题

{$IF CompilerVersion < 24}Actnlist,{$IFEND}

或者这是一个学术论点?

附录...

System.Actions.dcu然后在您的 2010 编译路径中添加一个不包含任何内容的虚拟对象。

我推测IDE会坚持插入uses ... System.Actions,2010有它想要的,XE7有它想要的。

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

于 2014-10-02T00:40:04.257 回答
1

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

{$IF CompilerVersion < 24}{$ELSE}System.Actions,{$IFEND}
{$IF CompilerVersion >= 24}{$ELSE}Actnlist,{$IFEND}

如果您在旧的 IDE 中打开该文件,您可能会看到一个错误,上面写着“未找到单元 X”,但它可以正常编译并且不会执行自动添加。它看起来不太好,但它工作得很好......

亲切的问候,

伯恩德

于 2017-12-14T14:00:56.047 回答