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



这应该这样工作还是我做错了什么?

我的项目源代码中有以下代码:

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

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

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

ADebugUnit,

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

ARelaseUnit,
添加新

单元后,我必须始终将其恢复为条件语句。有没有办法在不让添加新单元干扰的情况下完成此操作?

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

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

或者,只要小心一点,您就可以使用单元别名来实现您想要的。

考虑您希望在 on 上使用或另一个单元,具体取决于构建配置(调试或发布):

  • DebugUnit.pas
  • ReleaseUnit.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;

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

除其他外,这意味着您不能有条件地在 DPR 文件中包含单位。你必须找到另一个解决方案来解决你试图解决的任何问题。

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

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

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

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

为了构建 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 中的事实,很抱歉,如果我在那个代码中搞砸了什么。

最新更新