6

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

我的项目源代码中有这段代码:

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

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

例如,如果配置设置为调试,那么在我的项目中添加一个新单元后,上面的代码将更改为:

ADebugUnit,

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

ARelaseUnit,

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

4

3 回答 3

4

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

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

或者,稍加注意,您也许可以使用单位别名来实现您想要的。

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

  • 调试单元.pas
  • 发布单元.pas

在您的项目选项中添加一个单位别名

调试配置:

  UnitToUse=DebugUnit

发布配置:

  UnitToUse=ReleaseUnit

在您的 DPR 中,将一个条目添加到使用列表中:

  uses
    UnitToUse,

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

您通常会使用DebugUnitReleaseUnit的任何地方,请参阅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;
于 2013-10-17T02:15:39.497 回答
2

IDE 拥有大部分 DPR 文件。小心你对它所做的事情,否则你会冒着你所观察到的风险(或者更糟 - 根据更改的性质,IDE 有时可能决定根本不允许编译该文件!)。

除其他外,这意味着您不能有条件地在 DPR 文件中包含单位。无论你试图解决什么问题,你都必须找到另一种解决方案。

例如,也许您可​​以在项目的其他地方使用该单元,而不是 DPR 文件。

或者,也许您可​​以将这两个单元合并为一个单元,然后对其内容进行有条件地编译。

或者,也许您可​​以一直使用调试代码,因为这会增加您发布测试过的相同代码的机会。

或者,如果此问题仅在您使用“添加单元”对话框时出现,您可以放弃该对话框并手动编辑 DPR 文件。正如您所注意到的,将单元添加到项目中并没有其他神奇之处,只是 use 子句被重写

于 2013-10-16T18:42:27.267 回答
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 中,如果我在该代码中搞砸了,请原谅。

于 2013-10-17T00:03:51.117 回答