In Delphi XE3, it seems that one can use either "System.SysUtils" or "SysUtils", "Vcl.FileCtrl" or "FileCtrl".
I read the article in http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/usingnamespaces_xml.html , it seems the former is called full qualified namespace, while the latter is the generic name. But if i understand correct, one should add statements like:
"Uses System, Vcl", before one can use the units under these namespaces. But I check the codes but cannot find any "Uses System" or "Uses vcl". Why?
You are reading old documentation, and reading the wrong topic anyway.
System and Vcl in this context are actually Unit Scope Names, which are similar to, but quite different from, Namespaces. Unit Scope Names were introduced in XE2, to allow VCL and FMX to share common unit names under different scopes (Vcl.Forms vs FMX.Forms, etc). Existing VCL code being migrated to FMX did not (largely) need to be re-written, it could use just Forms, etc and magically pick up the correct scope based on project type. The same does not work with Namespaces.
The reason you don't have to explicitly specify Unit Scope Names in uses statements in code is because they are configured at the project level instead, and by default most VCL projects have the System and Vcl scope names pre-configured.
So, when you use just SysUtils, FileCtrl etc in your code, the compiler checks them against the project's Unit Scope Names and eventually finds System.SysUtils, Vcl.FileCtrl, etc.
Related
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.
we had the same issue...
The easiest way is to do it that way:
{$IF CompilerVersion < 24}{$ELSE}System.Actions,{$IFEND}
{$IF CompilerVersion >= 24}{$ELSE}Actnlist,{$IFEND}
If you open the file in old IDE's, than you may see an error, which says "unit X" not found, but it will compile fine and no automatic adding is performed.
It looks not so nice, but it works quite well...
Kind regards,
Bernd
Is it better to fully qualify the namespaces in the uses clause? For example, is one of these declarations better than the other?
uses
ShellApi,
Windows,
SHFolder,
SysUtils;
uses
Winapi.ShellApi,
Winapi.Windows,
Winapi.SHFolder,
System.SysUtils;
It really depends on what you're building. If it's a simple VCL application as Delphi is most known for, then you usually don't need to worry about it. However, if you're building a package, with components for example, you need to be sure to clearly define which environment you intend to use: VCL or FMX. Embarcadero added namespace prefixes to be able to differentiate different possible solutions.
However, in most scenarios, the . only serves as a visual representation. It helps you, the coder, be able to identify which libraries you're using.
Take this other question for example. The Delphi IDE/Compiler would not accept one very common unit without either adding the namespace prefix or the namespace in the project options. The standard Graphics unit needed to be explicitly defined as Vcl.Graphics, as opposed to FMX.Graphics.
On a side-note, using the full namespace is comfortable for many coders who come from other languages where it was strictly enforced, and not only that, but allows you to see the nature of everything in a single glance, without having to look elsewhere for more information about what you're actually using.
EDIT
In addition, I just recently saw that using fully qualified namespaces also helps speed up compile-time, because the compiler doesn't have to try to resolve all the namespaces.
The main benefit of fully qualifying names is that your code can be compiled successfully into projects, irrespective of the namespace prefix settings of those projects.
Why is this useful? Well, if you are writing application code then you likely know and control the namespace prefix settings of the project(s) that contain a particular unit. However, if you are writing library code, code that is intended to be included in projects outside of your control, then you cannot predict what the namespace prefixes will be in those projects. If you do not fully qualify unit names, then you place a constraint on the projects settings of any project that consumes your library code. And library code is expected not to do that.
So, in summary, for application code, namespace qualifiers can reasonably be omitted, if you prefer less verbose names. For library code, fully qualified names should be used to allow the library code to stand alone.
We're in the process of moving out Delphi XE2 apps over to Delphi XE5 (We have a window :) )
I'm wondering whether, as part of the move, I should be thinkning of adding my own Unit Scope to our internal applications. This question suggests that it's just of case of renaming units as Company.Unit.
Is it as simple as using Rename in the Project Manager?
Am I missing anything?
It's nearly that simple. You can use the Rename action in the project manager and that will rename the file, give the unit a new name, and change references in the .dpr and .dproj file. But that will not rename any references in code.
So, if you list the unit in uses clauses (seems likely that you will), or use the unit name to resolve ambiguous scope, then you will need to change the names there too.
If you don't have too many units it won't be very difficult to make the change in the project manager, and then fix all the errors that the compiler throws at you. If you have a larger project then you may be better scripting the change. I expect that you could go 99% of the way there with a simple regex based script that did the following:
Update references in the .dpr and .dproj files.
Change the file names and the unit names.
Find the uses clauses (interface and implementation sections) and update references there.
This would leave you to deal with the uses that perform scope resolution and my guess is that there would be few enough of these to let the compiler find them all.
I use a great Tool from http://www.easy-ip.net (DELPHI UNIT DEPENDENCY SCANNER) for that task.
You can change the Name of the unit and the DUPS change all your uses clause's.
I am updating some projects to XE2 and I don't understand why on some projects
uses jpeg;
is accepted
and in other i need to write
uses vcl.imaging.jpeg;
Could you explain me please?
The difference is down to the the unit scope names setting in the project options for your various projects.
If you have Vcl.Imaging included in that setting then you don't need to fully specify the unit scope. Typically, old projects that are upgraded from previous Delphi versions will have Vcl.Imaging included in the unit scope names setting. New projects do not.
This is described in the documentation for Unit Scope Names.
Please explain package use (in short sentences with small words (for Dummies)).
I just moved from D7 to XE2 and packages seem much more prevelant, and I seem to need to qualify a lot more things.
In D7 I would say uses windows and now I must say uses winapi.windows.
I find that when I call MessageDlg() I can't pass in mtError, I need to qualify it.
Before I go too far down the wrong road - what's the simple solution?
Can I somehow continue to use my old code with package names which I suspect are terminal (that is, for packages A.B.C I have auses C clause).
Can I add one statement somewhere to do this? Or configure the project.
Sorry to sound so dumb :-(
Package use is no different in XE2 than in earlier versions. What is different is that all of Embarcadero's unit names are now prefixed with new Unit Scope Names ("System", "Vcl", "Winapi", etc) to help designate which units belong to the RTL, the VCL, FireMonkey, specific platforms, etc.
You can update your code to fully qualify everything now, if you want to, but you do not have to. You can instead specify the particular scope names in the "Unit Scope Names" setting of the Project Options instead, then no code changes are needed (other than the usual changes when migrating from one version to another).
These are called unit scopes. Because of the new FireMonkey libraries, and the cross-platform support, it's required that you declare which unit you're referring to for types and function declarations.
You can set defaults using Project->Options->Compiler->Unit Scope Names. This is documented as well.