Add block to project - remove the compiler directive from the project source

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

I have this code in the project source:

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

I want ADebugUnit to be used in debug mode, but AReleaseUnit was used when compiling in release mode. This works EXCEPTLY when I choose to add a new project to the project. When I do this, it will mainly process the code and only support the block that relates to the configuration in which the project is currently installed.

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

 ADebugUnit, 

Or, if my configuration is set to Release, after adding a new device, it will change as follows:

 ARelaseUnit, 

I should always return it back to conditional statements after adding a new module. Is there a way to do this without the intervention of a new block?

+6
source share
3 answers

The IDE owns most of the DPR file. Be careful what you do with it, or you risk exactly what you observed (or, even worse - depending on the nature of the changes, the IDE may sometimes decide not to allow the file to be compiled at all).

Among other things, this means that you cannot conditionally include units in a DPR file. You will need to find a different solution for any problem you are trying to solve.

For example, perhaps you can use the device from a different place in the project instead of a DPR file.

Or maybe you can combine the two blocks into one, and then its contents will be compiled instead.

Or maybe you can just use the debug code all the time, as this increases the likelihood that you are sending the same code that you tested.

Or, if this problem occurs only when using the "add block" dialog, you can simply discard this dialog box and edit the DPR file manually. There is no other magic to adding a unit to a project, except that the uses clause is overwritten, as you noticed.

+2
source

The problem is that DPR will not respect any $ ifdef in the use list and will actually delete them (as you already found) when it rewrites the use list in response to certain IDEs.

One option is to never use these IDE operations, such as Add / Remove Device, etc., and only ever manage the DPR usage list manually.

Alternatively, with little attention, you can use module aliases to achieve what you want.

Consider two devices in which you want to use either on the other or depending on the configuration of the assembly (debugging or release):

  • DebugUnit.pas
  • ReleaseUnit.pas

In your project options, add a module alias for:

DEBUG Configuration :

  UnitToUse=DebugUnit 

RELEASE :

  UnitToUse=ReleaseUnit 

In DPR, add an entry to the use list:

  uses UnitToUse, 

This entry in DPR cannot identify the file name using the "in" syntax, and should instead rely on the actual units that should be in the project search path.

Anywhere where DebugUnit or ReleaseUnit is commonly used, use UnitToUse instead. Obviously, the name of the alias is completely up to you.

If two blocks have the same “contracts” interface, your assemblies will switch between the two blocks simply by changing the target configuration.

If they have different interface contracts, you can still use the $ ifdef directives in the application code to work with the contents of the unit that UnitToUse refers to, for example,

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

To build Rob's answer, whenever I have situations when I need to do something, I transfer all the DPR code to another block, for example, 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. 

Then your project unit will have

 program SampleApp; uses Vcl.Forms, Unit1 in 'Unit1.pas' {Form1}, AppInit in 'AppInit.pas'; {$R *.res} begin RunApp; end. 

The downside of this is that the IDE will be confused as to what kind of application it is, and when you go to Project > Options , some features will be disabled, such as VCL Styles. With the right coding, such things can still be implemented.

PS - I apologize for writing this 100% directly in StackOverflow, so sorry if I did something in this code.

0
source

Source: https://habr.com/ru/post/956109/


All Articles