I am trying to modify my Delphi 2010 code to compile in XE7 (and want to retain the ability to compile it in 2010). So in the unit that houses my mainform I added conditional directives. The following works fine in 2010
uses
{$IF CompilerVersion >= 24}System.Actions, {$ELSE}Actnlist,{$IFEND}
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
But XE7 automatically adds a System.Actions
at the end to create a uses clause that now has System.Actions declared twice (see below), and gives an error message [dcc32 Error] MyForm.pas(10): E2004 Identifier redeclared: 'System.Actions'
. Why is XE7 not accepting the unit from within the conditional directive ?
uses
{$IF CompilerVersion >= 24}System.Actions, {$ELSE}Actnlist,{$IFEND}
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
System.Actions; // <- automatically added
As Ken says, the interface uses clause will be modified by the IDE and the processes by which this is achieved are somewhat less than sophisticated (as you have discovered). The same problem affects the project uses clause. Unfortunately this is much harder to avoid in the case of Form/DataModule uses clauses.
You could use a Unit Alias (see David Heffernan's answer) but need to be aware that if you create an alias for a unit that the IDE wishes to add, then the IDE will still add a reference to the required unit since it does not recognise the alias as identifying that required unit. Aliasing to the System unit will avoid this since it is already (implicitly) used by every unit.
Another alternative is to remove all such conditionals from your uses list and instead create place-holder units as required so that the different compilers you wish to use on the project can each be satisfied by the single uses list combined from the list that each IDE insists is required (the IDE won't remove unused units from the uses list, something that is often a complaint but in this case actually helps solve your problem).
In this case, in your Delphi 2010 project create an empty Actions unit:
unit Actions;
interface
implementation
end.
You will of course need to ensure that this unit is not in the project path for your XE7 version of the project.
One way to achieve that would be ensure that the empty Actions.pas unit is not explicitly listed in the DPR uses list, but is placed in a subfolder of your project source (e.g. 'placeholders'). You can then add this subfolder to the project search path for the Delphi 2010 version but not the XE7 version:
\Project Folder
project2010.dpr
project2010.dproj
projectXE7.dpr
projectXE7.dproj
\placeholders
Actions.pas
If you find that you need placeholders for each of the different versions then you will need separate placeholder folders. You might create further version specific subfolders, for example:
\placeholders
\2010
Actions.pas
\XE7
D2010UnitNotPresentInXE7.pas
This sort of structure might be advisable simply from the point of view of creating an auto/self documenting organisation.
Note that this is only required for dealing with unit references in the uses clause of the interface section of Forms (or Frames etc). In non-visual units or in the implementation section, the IDE does not interfere so conditional compilation directives should present no issues there.
The easiest way to fix this is to add a unit alias to your Delphi 2010 project. You'll need to use different .dproj files for your different Delphi versions, but you need to do that anyway.
In the unit aliases settings for the Delphi 2010 project add this:
Actions=System
I'm using System
as the alias target because the System
unit is automatically included in every Delphi unit and so aliased inclusions are benign. It's the simplest way that I can think of to make the compiler effectively ignore an entry in a uses clause.
Then you can declare your uses clause like this:
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Actions, Actnlist;
This will compile fine in Delphi 2010, because the alias processing will map Actions
onto System
. In XE7 you are also fine because there is no alias, and the IDE is satisfied by the presence of the Actions
unit and so feels no compulsion to modify the uses clause.
Would there be something wrong with
{$IF CompilerVersion < 24}Actnlist,{$IFEND}
or is this an academic argument?
Addendum...
Then add a dummy System.Actions.dcu
containing nothing into your 2010 compile-path.
I'd theorise that the IDE would then insist on inserting uses ... System.Actions
, 2010 has what it wants, XE7 has what it wants.
But I don't have XE7 so I can't test it out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With