Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add unit to project is removing a compiler directive from the project source

Should this work this way or am I doing something wrong?

I have this code in my project source:

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

I want ADebugUnit to be used when in debug mode but AReleaseUnit to be used when compiling in release mode. This works great EXCEPT when I select to add a new unit to the project. When I do that it will basically process the code and only keep the unit that pertains to whichever configuration the project is currently set to.

For example, if the configuration is set to Debug then after adding a new unit to my project the above code changes to just:

ADebugUnit,

Or if my configuration is set to Release it will change to the following after adding a new unit:

ARelaseUnit,

I have to always restore it back to the conditional statements after adding a new unit. Is there a way to accomplish this without having the add new unit interfere?

like image 856
Ann Gossard Avatar asked Oct 16 '13 18:10

Ann Gossard


2 Answers

The problem is that the DPR will not respect any $ifdef's in the uses list and will in fact remove them (as you have found) when it re-writes the uses list in response to certain IDE operations.

One option is to never use those IDE operations, such as "Add/Remove Unit" etc and to only ever manage the DPR uses list manually.

Alternatively with a bit of care you may be able to use unit aliases to achieve what you want.

Consider two units where you wish to use either on or the other depending upon the build configuration (debug or release):

  • DebugUnit.pas
  • ReleaseUnit.pas

In your project options add a Unit Alias for:

DEBUG configuration:

  UnitToUse=DebugUnit

RELEASE configuration:

  UnitToUse=ReleaseUnit

In your DPR add an entry to the uses list:

  uses
    UnitToUse,

This entry in DPR cannot identify a filename using the "in '' syntax and must instead rely on the actual units required being on the project search path.

Anywhere that you would normally use the DebugUnit or ReleaseUnit, refer instead to UnitToUse. Obviously the name for the alias is entirely up to you.

If the two units have the same interface "contracts" then your builds will switch between these two units simply by changing the target configuration.

If they have different interface contracts then you can still use $ifdef directives in your application code to work with the contents of whichever unit UnitToUse refers to, as appropriate, e.g.

uses
  UnitToUse;


procedure DoSomethingInvolvingAliasedUnit;
begin
  {$ifdef DEBUG}
    // code which relies on the debug unit
  {$else}
    // code which relies on the release unit
  {$endif}
end;
like image 55
Deltics Avatar answered Nov 15 '22 00:11

Deltics


The IDE owns much of the DPR file. Be careful of what you do to it, or you risk exactly what you've observed (or worse — depending on the nature of the changes, the IDE might sometimes decide not to allow the file to be compiled at all!).

Among other things, what this means is that you cannot conditionally include units in the DPR file. You'll have to find another solution to whatever problem you were trying to solve.

For example, maybe you could use the unit from somewhere else in your project instead of the DPR file.

Or maybe you could consolidate the two units into one, and then have its contents conditionally compiled instead.

Or maybe you could just use the debug code all the time since that increases the chances that you ship the same code you tested.

Or, if this problem only occurs when you use the "add unit" dialog, you could just forego that dialog and edit the DPR file manually. There's no other magic behind adding a unit to a project, except that the uses clause gets rewritten, as you've noticed.

like image 41
Rob Kennedy Avatar answered Nov 14 '22 23:11

Rob Kennedy