Over on stackoverflow, Ann Gossard had a question about using an $ifdef in the project (DPR) uses list to use one unit in preference over another, specifically in debug builds. In this situation, it immediately occurred to me that unit aliases might be creatively deployed.
What follows is a slightly expanded version of the answer I posted to that question.
The problem Ann was experiencing is the well known issue of the DPR not respecting any $ifdef‘s in the uses list, removing them if [when – Ed] it re-writes the uses list in response to certain IDE operations such as “Add/Remove Unit” etc.
As Rob suggested (and I echoed in my answer), one option is to avoid those IDE operations and to only ever manage the DPR uses list manually. But occasionally you will likely slip up and have to reconstruct your uses list from time to time.
If you are using a version of Delphi which supports build configurations (Delphi 2007 or later), a unit alias can be used to select a unit based on the selected build configuration without relying on an $ifdef in the uses list.
If you are using a version of Delphi prior to Delphi 2007 then I have a vague recollection that there may have been 3rd party solutions that provided similar functionality before this official support was added but I didn’t use them myself and do not know if they included support for per-configuration unit aliases. Google will have to be your friend if you fall into this camp I’m afraid. π
But, if you do have Delphi 2007 or later….
Alias Smith and Jones…
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
Note: This screen capture is taken from Delphi 2010. Things worked slightly different in Delphi 2007 but unfortunately my Delphi 2007 installation seems to have a problem in this area, throwing an exception in delphicoreide100.bpl whenever I try to access the Configuration Manager, which is were the different option sets were managed in that version. So I’m afraid I can’t show a working example from that version. π
But, if using Delphi 2009 or later (or you’ve got a working Configuration Manager in Delphi 2007) …
In the DPR add an entry to the uses list for
UnitToUse
Note that this entry in DPR cannot identify a filename using the in '<filename.pas>'
syntax and must instead rely on the aliased units being on the project (or IDE) 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 seamlessly switch between these two units simply by changing the target configuration from Debug to Release or vice versa.
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;
Caveat Developor
This technique has an admittedly narrow application.
It only works where you need to select between one unit or another (or N units where there is a 1:1 correspondence between each unit used in the DEBUG and RELEASE builds).
It obviously cannot work if you needed to use more units in the DEBUG build than in the RELEASE build (or vice versa).
In the case where you have one unit with no corresponding alternative, you could use an alias to select an entirely empty unit (consisting of empty interface and implementation sections), but arguably it would be simpler to just wrap an $ifdef around the contents of the interface and implementation sections of a consistently used unit in that case.
But still, for Ann’s specific case of selecting one of an alternate pair of units, this struck me as a particularly elegant solution. It’s not often that Unit Aliases find much purpose beyond that which they dutifully provide day in, day out, quietly and unobtrusively.
Which is perhaps why they are sometimes overlooked. π
One more candidate solution of a problem from russian delphi-blog http://teran.karelia.pro/articles/item_4498.html
(sorry for my translation):
“I solved this problem as follows: I created a unit, for example under such name:
MyAdditions.pas
In which directives I turn on (or I don’t include) additional modules in uses of this file (I have there FastMM/FastCode/EurekaLog etc. )
And in the dpr-file in the section uses the MyAdditions module goes the first.”
This decision works in my project.
I do it exactly like that.
But the disadvantage is that your project can’t directly reference anything which is contained inside a unit that is linked by myadditions.pas.
Delphi has had unit aliases from at least version 3. So with a little bit of creativity your solution would work with these ancient versions as well.
I’m using unit aliasses with D2007 without problem. They are configured in the project ioptions dialog, no need for the configuration manager.
Regarding 1:1 correspondence: Delphi’s default aliasses include “WinTypes=Windows;WinProcs=Windows” with Windows referred twice. So I guess one could map non-existing units in one configuration to some random unit in the other configuration.
Good point! π
Yep, but I the Project Options dialog has no facility for defining or switching between configuration sets (Debug vs Release configuration) in Delphi 2007. That’s where the Configuration Manager is involved.
This is the difference in Delphi 2009 – Configuration Management was absorbed into the Project Options UI.
I used this technique extensively when migrating from Delphi 6 to XE2. For examples I used Mike Lischke’s theme manager in D6. But in XE2 the unit names changed. This reach of the alias obviously extends beyond the .DPR and into all source units.
Unfortunately there are sometimes more things that need to be done bespoke in a .dpr than simple unit switching.
Yep. There are tricks to avoid those as well. π
I think one can have same-named unit in config-specific paths.
I also think unit aliases were introduced back in D2 times to bring Windows unit together. However that could be a global Ide setting rather than project’s property
Yes unit aliases have been around for a long, long time.
It’s the combination of unit aliases and build configurations that provide the extra utility here (though you can achieve a similar result independent of IDE configuration sets, using command-line compilation or something like FinalBuilder).