i have use delphi xe recently but exe size is very big because of rtti(i think)
howto remove rtti , and can i make my application size as small as delphi 2009 application(490 kb) without comprssion; and what is the use of rtti
In short (full story provided by links in the splash's answer):
{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
Note that as of XE6 and newer, this needs to be in each individual unit for which you want to disable RTTI. Before that (XE5 and below) it could be in the DPR file and would apply to all units in the project.
Read the Online Help for Delphi ...
Working with RTTI
RTTI directive
... and search Stack Overflow:
Why should I care about RTTI in Delphi?
Practical usage for Delphi's new RTTI
Keep in mind that the $RTTI directive has to be included in every unit where it should take effect. See How can I set the $RTTI directive for the entire project?
Your problem is not related to RTTI. If you are talking about relatively small increase (100-200K), this is due to extra functions in RTL (added for Unicode support etc). If you get 500-700K increase or so, then check whether you link VCL UI units (Forms, Controls etc). If you get 3Mb increase, then you've turned on extra debug symbols.
It's because some generics functionality has been added to sys units.
Generics were added in 2009 but in systems units some classes were rewritten with generics in xe and xe2. imho
Add this flags to reduce the size in dpr file (Project > view source) to each individual unit (as of XE5)*.
{$SETPEFlAGS IMAGE_FILE_DEBUG_STRIPPED or IMAGE_FILE_LINE_NUMS_STRIPPED or
IMAGE_FILE_LOCAL_SYMS_STRIPPED OR IMAGE_FILE_RELOCS_STRIPPED}
{$WEAKLINKRTTI ON}
{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
(*) Note that as of XE5 and newer, this needs to be in each individual unit for which you want to disable RTTI. Before that (XE4 and below) it could be in the DPR file and would apply to all units in the project.
I do not think it is RTTI what adds so much size overhead to your application. How do you know it is?
Related
I'm creating my own DB-aware grid control for Delphi 7. In DBReg unit Delphi registers the property editors for db-aware controls but almost all of them are local types, so I cannot re-use them:
TDataSetProperty
TNestedDataSetProperty
TDataSourceProperty
TLookupSourceProperty
TLookupDestProperty
TLookupIndexProperty
TLookupFieldProperty
Why they are local types and does it change in newer versions of delphi? And is it a good practice if I just copy it to my unit?
I expect that the designers confined these classes to implementation sections to ensure that other developers were not able to use them.
Does it change in newer versions of delphi?
In XE3, and presumably in all other versions since Delphi 7, these types are still confined to the implementation section of DBReg.
Is it a good practice if I just copy it to my unit?
No it would not–that would be a clear violation of the Delphi license.
I'm moving my code to Delphi XE3 from XE2, but it should compile in both. I notice that some units get 'System.Actions' auto added to the USES clause. This then causes an error when returning to XE2 with:
F1026 File not found: 'System.Actions.dcu' (unit scope "System" indicates Win64, OSX32, Win32 only)
I've never really understood unit scope properly. Is there a correct solution to resolve this rather than wrapping stuff within compiler version {$IFDEF}'s?
Thanks
There is no Actions unit in XE2. It is new in XE3, as part of refactoring work to bring Actions support into FireMonkey. This is documented:
What's New in Delphi and C++Builder XE3:
Actions: FireMonkey now supports actions and action lists, two features that were previously supported only in VCL:
Important: Every FireMonkey or VCL application that uses actions must specify the System.Actions and System.Classes units in the uses section.
Changes in Implementation of VCL Actions
The System.Actions unit is created in the RTL package. Classes from the Vcl.ActnList unit that provide framework-independent action features are moved into this unit. Classes in System.Actions extend the most fundamental behavior of action features introduced in the TBasicAction and TBasicActionLink classes.
Important: As a result of these changes, you need to add the System.Classes and System.Actions units into the uses section.
Implementation of Actions in FireMonkey and VCL
FireMonkey (FMX)
The framework-independent implementation is common to FireMonkey and VCL:
This basic actions functionality is extended in the new System.Actions RTL unit.
VCL
Framework-independent action features that were implemented in the Vcl.ActnList unit in previous RAD Studio releases are now in the new System.Actions unit in the RTL (common to VCL and FireMonkey).
Important: As a result of these changes, you need to add the System.Actions unit to the uses section (or #includes) in your VCL applications that use actions.
You will have to either remove the reference to Actions if you are not actually using actions in your code, or else {$IFDEF} it out.
What Remy said is quite correct, but there may be an easier way to make your code work in both XE2 and XE3. Simply add a unit alias from System.Actions to Vcl.ActnList.
Add this in your project options, on the Delphi Compiler page. You need to add the following:
System.Actions=Vcl.ActnList
Note that if you need to compile in both XE2 and XE3 using the same .dproj file then you are out of luck. That unit alias setting will stop the program compiling under XE3. However, if you have have different .dproj files for XE2 and XE3, then this will allow you to use the same source in both. Or, if you only need to compile for XE2 at the command line, then you could add this unit alias there. I can't tell whether or not this will help you, but I know that the unit alias feature has helped me out of a similar spot on more than one occasion in the past.
If you have ONE project file you still can solve the problem with a "dummy" System.Actions.pas file in your project path directory:
This file will be taken under XE2.
The XE3 compiler will find his System.Actions.dcu in the IDE /lib directory.
Anyway: In normal cases you should use different project files - then the solution with the unit alias is recommended.
The dummy System.Actions.pas could look like:
unit System.Actions;
(*
XE2 compatibility unit: since XE3 unit System.Actions will be inserted into every
interface in units which use actions.
compilerswitch in [uses] is ignored by IDE - so this solution enable successful
compilation in XE2 with same project file than XE3
*)
interface
implementation
end.
I have a unit I wrote in Delphi 7 some time ago, and have just had the fun (pain) of converting to Delphi XE (Unicode).
The Unit works fine after some trouble, I am now trying to make this unit compatible with different Delphi Versions should I ever need to switch IDE back to Delphi 7 whilst updating some other code.
I only have Delphi 7 and Delphi XE, but from what I gather code written in Delphi 1 to Delphi 2007 will compile, but code from Delphi 2009 and above will be Unicode.
...Anyway, in the Unit I am separating the non-unicode and unicode like so:
{$IFDEF VER150} //Delphi 7
// code
{$ELSE IFDEF VER220} //Delphi XE
// code
{$ENDIF}
How do I modify the compiler directive so the rules apply to multi versions? For example something like:
{$IFDEF VER80, //D1
VER90, //D2
VER100, //D3
VER120, //D4
VER130, //D5
VER140, //D6
VER150, //D7}
This would then cover all Delphi versions should I distribute the source or .dcu unit.
Thanks.
I wonder if the simplest approach in this instance is to switch behaviour on the UNICODE conditional. This conditional is defined if and only if you are using a Unicode version of Delphi, i.e. in Delphi 2009 and later. The big advantage of this is that it is future proof—you don't need to update your code every time a new Delphi is released. What's more, the conditional switch will be far more readable since it will clearly express the intent.
The Delphi documentation has an excellent topic listing all the pre-defined conditionals. The full list of version conditionals is also linked from there.
Your best bet is actually to look at one of the many JEDI projects, http://sourceforge.net/projects/jedi-apilib/ for example and look at how they do it. They have common include files that contain exactly the details you are interested in. JVCL is another good choice ...
In this question (link) it was said that the line below (in each unit) would remove as much RTTI as possible:
{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
The posting didn't mention what Delphi version it works with, but I assume D2010. However, when I include the line above, I get this error:
DCC Fatal Error: E2158 System unit out of date or corrupted:
missing TVisibilityClasses.
I'm using a "stock" version of D2010 and have never done anything that I'm aware of that would change the default installation or the libraries.
Any suggestions? TIA
Related question: link.
Make sure you put the "{$RTTI" line below the "unit unit1;" line.
Note that as of XE5 and newer, this directive needs to be in each individual unit for which you want to disable RTTI. Before that (as in comments, which applies only to XE4 and below) it could be in the DPR file and would apply to all units in the project.
The new RTTI is for Delphi 2010 and up.
It can be removed, but then lots of things will have limited functionality (like JSON conversion, part of DataSnap and many of the newer 3rd party libraries that do ORM or other mappings).
Things depending on TValue are gone anyway.
"old style" RTTI (which was introduced in Delphi 1 and is still present in Delphi 2010) cannot be removed.
So: it is recommended to remove RTTI only from your own units, and not from the RTL and VCL.
--jeroen
I'm working on migrating an old project from Delphi 2007 to Delphi 2010. One thing I've found is that the resulting executable has more than doubled in size, and the original was already quite big. (Over 50 MB.) I suspect that a lot of it has to do with extended RTTI.
Since the project predates Delphi 2010, it doesn't use extended RTTI anywhere, and I'd like to be conservative about including it. Is there any way to use the Project Options dialog to globally set {$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])} as the default? I'd have expected there to be an option for this (and for $WEAKLINKRTTI) somewhere, but I don't see them.
Does anyone know if this can be done from the "Additional options to pass to the compiler" field, or some other way? I'd really prefer not to have to add an include file to every single unit in the project, as there are a few thousand of them...
The behavior of the $RTTI directive has been changed since XE6 because actually it was a bug because it was supposed to be local to the current unit (and it was actually documented as that since Delphi 2010).
Also it could have fatal affects using the directive at all even in one unit because due to the bug it basically switched a global flag affecting the following units (as in the order of compilation).
You can try with the dcc32 –$weaklinkrtti command-line option. (like {$WEAKLINKRTTI ON}).
But that has not the impact of {$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])} in each unit.
Your best bet would be to have it at the top of each unit in an include file.
But then it wouldn't do it for the VCL/RTL which would still be inflated....
Update: Also make sure you compare what's comparable. For instance verify if you don't include debug information in the Linker Options in the new D2010 project where you may not have it in the D2007 one...
In a comment on Mason's own blog, in response to a comment of mine, Mason answered this question.
Try putting these two lines at the top
of your DPR, before the USES clause:
{$WEAKLINKRTTI ON}
{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
This will make sure that no RTTI gets
generated for your own code or any
third-party libraries you use, unless
they’re in a unit where RTTI
generation is explicitly enabled. You
can’t turn it off for the RTL or VCL,
but that shouldn’t add very much to
your size anyway.
Are you certain this is caused by the new RTTI info? While it's a lot of data it shouldn't really double the size of your application.
Check that it's not including debug info in the release build executable.
(Project options -> Delphi Compiler -> Debug information should be False)
As for the question, I use {$WEAKLINKRTTI ON} before the uses clause in the dpr file and it seems to work fine.
I don't know of such an option, but I still would use an include file.
I wont be a problem for any experienced Delphi programmer to write a small program to add an {$i ProjectIncludeFile.inc} to any unit in your folders (immediatly after the unit line).
And that way you can use it for whatever purpose you like.
I myself use if f.i. to set a WriteTempFiles compiler directive (which I use f.i. to save stringlist contents at various places when developing the program), that way I can disable it in one place when the program is ready for deployment.
Since most of my projects involve multiple executables and/or dll's, this is the easiest way to accomplish this globaly for the whole project.