将单元添加到项目是从项目源中删除编译器指令

时间:2013-10-16 18:30:55

标签: delphi compiler-directives

这应该以这种方式工作还是我做错了什么?

我在项目源代码中有这个代码:

  {$IFDEF DEBUG}
  ADebugUnit,
  {$ELSE}
  ARelaseUnit,
  {$ENDIF}

我希望在调试模式下使用ADebugUnit,但在发布模式下编译时要使用AReleaseUnit。当我选择向项目添加新单元时,这种方法效果很好。当我这样做时,它基本上将处理代码,并且只保留与项目当前设置的任何配置相关的单位。

例如,如果配置设置为Debug,那么在向项目添加新单元后,上面的代码将更改为:

ADebugUnit,

或者如果我的配置设置为Release,则在添加新单元后将更改为以下内容:

ARelaseUnit,

添加新单元后,我必须始终将其恢复为条件语句。有没有办法在没有添加新单元干扰的情况下实现这一目标?

3 个答案:

答案 0 :(得分:4)

问题是DPR在使用列表中不会尊重任何 $ ifdef ,并且当它在响应中重写用途列表时实际上会删除它们(如您所见)某些IDE操作。

一种选择是永远不要使用那些IDE操作,例如“添加/删除单元”等,并且只能手动管理DPR使用列表。

或者稍加谨慎,您可以使用单位别名来实现您想要的效果。

根据构建配置(调试或发布),考虑两个您希望在其中使用的单元:

  • DebugUnit.pas
  • ReleaseUnit.pas

在项目选项中为:

添加单位别名

DEBUG 配置:

  UnitToUse=DebugUnit

RELEASE 配置:

  UnitToUse=ReleaseUnit

在DPR中添加使用列表的条目:

  uses
    UnitToUse,

DPR中的此条目无法使用“in”语法识别文件名,而必须依赖于项目搜索路径中所需的实际单位。

您通常使用 DebugUnit ReleaseUnit 的任何地方,请转而使用 UnitToUse 。显然,别名的名称完全取决于你。

如果两个单元具有相同的“契约”接口,那么只需更改目标配置,您的构建将在这两个单元之间切换。

如果他们有不同的接口合同,那么您仍然可以在应用程序代码中使用 $ ifdef 指令来处理任何单位的内容 UnitToUse 酌情指,例如

uses
  UnitToUse;


procedure DoSomethingInvolvingAliasedUnit;
begin
  {$ifdef DEBUG}
    // code which relies on the debug unit
  {$else}
    // code which relies on the release unit
  {$endif}
end;

答案 1 :(得分:2)

IDE拥有大部分DPR文件。小心你对它做了什么,或者你确实冒了你所观察到的风险(或者更糟 - 根据改变的性质,IDE有时可能决定不允许编译文件!)。

除此之外,这意味着您无法有条件地在DPR文件中包含单位。你必须找到解决你试图解决的任何问题的另一种解决方案。

例如,您可以使用项目中其他位置的单位而不是DPR文件。

或许您可以将两个单位合并为一个,然后有条件地编译其内容

或许您可以一直使用调试代码,因为这会增加您发送测试代码的机会。

或者,如果仅在使用“添加单元”对话框时出现此问题,则可以放弃该对话框并手动编辑DPR文件。除了正如您所注意到的那样使用子句被重写之外,在项目中添加单元背后没有其他魔力。

答案 2 :(得分:0)

为了建立Rob的答案,每当我遇到需要执行此类操作的情况时,我会将所有DPR代码迁移到另一个单元,例如AppInit.pas

unit AppInit;

interface

uses
  Vcl.Forms,
  Unit1,
{$IFDEF DEBUG}
  ADebugUnit
{$ELSE}
  AReleaseUnit
{$ENDIF}
  ;

procedure RunApp;

implementation

procedure RunApp;
begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.Title := 'Sample Application';
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end;

end.

然后你的项目单位只有

program SampleApp;

uses
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1},
  AppInit in 'AppInit.pas';

{$R *.res}

begin
  RunApp;
end.

这样做的另一方面是IDE会混淆它的应用程序类型,当你转到Project > Options时,某些功能将被禁用,例如VCL样式。通过正确的编码,这些事情仍然可以实现。

PS - 请原谅我将这100%直接写入StackOverflow的事实,很抱歉,如果我在该代码中搞砸了。