这应该以这种方式工作还是我做错了什么?
我在项目源代码中有这个代码:
{$IFDEF DEBUG}
ADebugUnit,
{$ELSE}
ARelaseUnit,
{$ENDIF}
我希望在调试模式下使用ADebugUnit,但在发布模式下编译时要使用AReleaseUnit。当我选择向项目添加新单元时,这种方法效果很好。当我这样做时,它基本上将处理代码,并且只保留与项目当前设置的任何配置相关的单位。
例如,如果配置设置为Debug,那么在向项目添加新单元后,上面的代码将更改为:
ADebugUnit,
或者如果我的配置设置为Release,则在添加新单元后将更改为以下内容:
ARelaseUnit,
添加新单元后,我必须始终将其恢复为条件语句。有没有办法在没有添加新单元干扰的情况下实现这一目标?
答案 0 :(得分:4)
问题是DPR在使用列表中不会尊重任何 $ ifdef ,并且当它在响应中重写用途列表时实际上会删除它们(如您所见)某些IDE操作。
一种选择是永远不要使用那些IDE操作,例如“添加/删除单元”等,并且只能手动管理DPR使用列表。
或者稍加谨慎,您可以使用单位别名来实现您想要的效果。
根据构建配置(调试或发布),考虑两个您希望在其中使用的单元:
在项目选项中为:
添加单位别名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样式。通过正确的编码,这些事情仍然可以实现。