Using Delphi (or in general any tools, if exist of course), is it possible to reduce size of an exe file, removing all code that not is used but that is present there?
(for example, a function or procedure that is present but is never called).
I remember that with Pascal, using unit (without objects) the compiler includes only procedures and functions that are really used and will strip out non-used routines in a unit from the final exe.
With Object-pascal, I remember that in Delphi 1 all members of a object are included in the exe;
Has something has changed since than till Delphi-XE2?
If you aren't using RTTI you can add this to the top of your .dpr file (immediately after program) to remove the extra RTTI information:
{$IFOPT D-}{$WEAKLINKRTTI ON}{$ENDIF}
{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
If you want to strip it out of all the RTL/VCL units then you'd need to include those in your project file too so that the settings above could take effect. I don't think I would recommend doing that since I don't believe the reduction in executable size is worth the complications of compiling your own RTL/VCL.
You can also add the following, again somewhere in your .dpr file:
{$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED}
This will strip the relocation information which is not needed in a .exe. Don't add this to a DLL or package!
reduce the application EXE size - excellent article
(Taken from the link above)
Generally, EXE files created with Delphi are larger than EXE files
created with another programming language. The reason is the VCL.
(Sure, VCL has many advantages...)
There are several ways to reduce a EXE's size:
01) Use a EXE-Packer (UPX, ASPack,...)-UPX
02) Use KOL.
03) Write your application without VCL
04) Use the ACL (API Controls Library)
05) Use StripReloc.
06) Deactivate remote debugging information and TD32.
07) You might want to put code in a dll.
08) Don't put the same images several times on a form. Load them at runtime.
09) Use compressed images (JPG and not BMP)
10) Store less properties in DFM files
If your aim is to reduce the size of your executable, you can use a tool which compress it and allow to execute it as it was not compress.. (=not a zip)
For instance, you can check UPX which works nicely with delphi programs.
Delphi has a smart linking option that is ON by default if I remember correctly. It does exactly what you describe. Only used functions and data are linked to your exe. If you need further size compression you can try one of the many "exe compressor" programs out there.
Just to supplement what other's have written...
The smart linker will eliminate unused routines except under the following conditions:
The unit has an initialization section - unfortunately many of the largest units in the RTL/VCL (Classes, SysUtils, Windows, Forms... to name a few) have initialization sections so if they are in your uses clause you get the whole enchilada linked into your code. Much of the code in the RTL/VCL could be refactored to reduce or eliminate this but it would break backward compatibility.
The routine is part of a class and is marked as virtual or dynamic - If you instantiate and object in your code that has virtual or dynamic methods, those methods are linked into your executable whether you call them or not.
Additional steps to can take to reduce exe file size:
Take advantage of form inheritance - If you have many similar forms, create a base form for them to inherit from. These child forms will only store properties that differ from the base form in their dfms. This can drastically reduce the size of your executable by eliminating redundant information in your dfms.
Store any large graphics in external files and load them on demand - Splash screens, "skins", icon sets, etc. can really bloat the size of an exe. Delphi doesn't always store these files in the most efficient format when they're embedded in the exe.
You can shave 10% - 30% off an exe's size by stripping certain unused data from the exe after its been compiled. There are third party tools that can do this but you can eliminate some of the cruft by setting appropriate PE header flags. Make sure you understand the implications of each flag before using it as some flags could make your exe unusable.
Copy portions of the RTL/VLC into your own units - instead of including Classes or SysUtils in your uses clause, create an new unit and copy just the classes and functions you need into the unit. Then use it instead.
Break code up into loadable modules - If you have multiple exes that reuse the same units you can make them smaller by using dlls or bpls rather than statically linking everything into the exes. A dll/bpl will only be loaded into memory once no matter how many exes need it.
Yet another option:
Use WinRar to create a Setup file (yes, WinRar can do that).
WinRar can automatically execute an EXE file once the unpacking is done.
WinRar has a superior compression ratio. One of the reasons is that it will merge all your files as a single file and then will start the compression, while ZIP (and other similar not-so-sophisticated compressors) will compress each file individually and merge them in a large file after the compression.
This give RAR's algorithm a better chance to find duplicate data among your files.
Plus, WinRar is less complicated than other installers (minus: it does not offer an uninstaller also, but that it is easy to fix with your own program).
Disclaimer: I am not affiliated with WinRAR.
Related
We are using Delphi 10.4.2 Sydney. I would like to create a single unit (or possibly multiple units) that houses all the utility functions we use in our various software products. The idea is we would just include this unit in every project we start and then we can rely on it being there and use these functions freely in all our code. These would probably be mostly class routines and such.
I'm concerned though that some of our projects might only use a single routine in this large unit. The size of our apps is important and we want to keep that size to a minimum. I am not familiar with how Delphi's compiler works or how much space adding a superfluous unit might add or any other issues with this.
Is there perhaps a way to create a Unit where only the functions we actually use will contribute to the final build's size? Is this even something to worry about? How are common utilities library usually handled in Delphi?
The Delphi Linker is supposedly smart enough to detect unused functions and will not include the code for them in the executable it generates. This also applies to class methods. (*1)
So, go ahead and create these units.
You can easily check whether code was generated for a method by looking for the blue dots during debugging.
(*1: That feature can be a major pain in the lower back when you want to call such a function from the Evaluate/Modify dialog during debugging.)
Put the units into a separate package project. If you build your exe as a monolithic exe (so packages are linked in) then the compiler should only link in the units that are actually referenced, not the entire package.
So, I have a myself written run-time package. If a package is statically linked, the project that uses has full access to exported data because the compiler has full knowledge of what is imported from it, am I right? But it's also possible to load a package dynamically via LoadPackage(). But, how to work with imported complex data structures like classes then? I couldn't find a feasible way other than constructing complex expressions like using FindClass('TSomeClass') and invoking RTTI to operate on an instance of the imported class.
The compiler has full knowledge of what's in the package because the DCU and DCP files tell it what's there.
The IDE knows what's in the package because it knows how to find the Register procedure in all the units, and that procedure tells the IDE about the available classes.
In most cases, a program knows what's in a package because the program used units from that package, and the compiler assured that mentioning names of things in those units would resolve to corresponding things in the BPL file at run time. This includes mentioning the BPL file in the program's import table, so the OS loads the BPL automatically.
If the list of BPLs you wish to load can only be determined at run time, then you cannot use any units from those packages. You have to load the package dynamically.
There's still the matter of how to use what's in those packages. You could try to discover the entire contents with RTTI. That's no picnic, though. Instead, define an intermediary package that all involved modules will use.
Define an interface or a common base class for all your packages' classes to have. Put the definition of that class in a unit that's in its own package, which we'll call Shared.bpl. Include that package in the "requires" list of all your other packages and your EXE. Now, everything can refer to the shared unit and the common base class.
This is exactly what Delphi itself does. The shared packages are called RTL and VCL. There are several common base classes already defined there, including TComponent. In your case, it sounds like you need some common definitions beyond what TComponent has.
Short answer:
What you need is the compiler/linker to set you up and use DCPs to do all the linking to types and such.
Then loading of BPLs should be delayed/done by you in custom code.
Unfortunately Delphi won't allow this, probably because of political reasons, you could try and hack it though, see below for more thorough answer.
Long answer:
Apperently DCP describe to the compiler/linker/Delphi yadayadayada what's in those packages/DLLs/BPLs type-wise.
These DCPs can be considered the interface to these DLLs/BPLs, these DCPs are probably somehow compiled into the executable.
Then the BPL probably contains the "implementation".
Now here is where the problem begins. These BPLs are "auto-loaded" as somebody else already mentioned by mentioning "import table".
What you could try is "nuking" / altering the import table so that these BPLs are not loaded automatically anymore.
Then you could try loading these BPLs manually.
I am not sure if it's just as simple as doing a "load package" operation.
Perhaps the loading involves more like acquiring pointers to routines/methods/classes, not sure how that works.
However perhaps that code can be re-used, so all you need to do is "hack" into the import table and hack into the "load bpl" and disable it.
Then you should be able to replace that with your own custom loading code and perhaps finally "re-patch" into other importing routines... like routines calling getprocaddress and such if so required, not sure about this last part.
Anyway this is very sloppy from Delphi developers that there is no functionality to do this little "import table"/"load step" yourself.
This is politics at play though, there is no technical reason why this could not be delayed, done custom by you and then call the rest if necessary.
For some reason they do not want you loading these BPLs manually. They probably want you to keep using the IDE this way.
If you were able to load these things manually, maybe the IDE would then no longer be necessary.
Currently the IDE is necessary to specify where to load this stuff from, without the IDE it will get difficult. Though there are probably also some compiler options somewhere to specify the same, though few would use that.
So to me it seems some very weird "tie-in" into this product, which I honestly must admit is pretty fucking retarded.
They did the same with winsock for example which has two different versions, very easy to load this yourself manually so you can choose which version to use instead of always v1 or v2. For easy for them to delay these getprocs and such, yet they do not...
If they did, Delphi would be much more backwards compatible with windows 95/98, currently Delphi exes no longer works for those older operating systems, though there is no real technical reason why it could not work, it basically has to do with which DLLs are loaded, just a few lines of code could very easily make it work.
This is probably again politics as play to make Delphi only support the latest Windows versions a deal struck between Delphi creators and Microsoft.
Same thing with Windows 10, it apperently detects older processors and then refuses to run on them, removing/hacking these few lines of code/instructions will make Windows 10 work on older processors. Surprise ! =D
I have this craving to do some experiments with modifying the underbelly of the Delphi run time library (RTL), system.pas and the likes... It is possible or not?
I'm very fond of challenges like "yes, but you'll have to provide custom .obj files for some assembler wizardry because they were never distributed with the official Delphi source". Fine with me, I just want to know.
I want to do this experiment with Delphi 7, but inside information on any other version is fine. It is one of the perks of being with a company that worked with Delphi since the Stone Age.
(I always figured this to be one of those RTFM questions, with the answer being a resounding "NO!", but for some reason google won't confirm it.)
You can recompile the RTL like any other unit.
For System.pas you must use the command line compiler.
For instance, here is a working batch file content (there is some not well documented command line switches):
del *.dcu /s
"c:\program files\borland\delphi7\bin\dcc32.exe" -O+ -Q -M -Y -Z -$D+ System.pas
This will recompile System.pas and SysInit.pas (both lowest level RTL files).
But in order to use your recreated dcu files, you'll have to put the folder containing the updated dcu files into the first position of your IDE: for instance, in Delphi 7 it's Option / Environment Options / Library, then put your folder FIRST in both "Libary path" and "Browsing path" field.
And it's perhaps worth deleting the original .dcu files in your Delphi installation directory.
But be sure you won't change the "interface" part of the unit, or you'll have troubles with compiling with other not modified units of the RTL (or third-party components). You can change the "implementation" part, apply fixes or rewrite some part for speed or such, but don't change the "interface" part to avoid any linking error.
Always make a backup of the original .pas and .dcu files which you are changing. And it's a good idea to make some automated compilation test, so that you could be sure that your modifications of the RTL won't add any regression.
We made such a RTL recompilation for our Enhanced Run Time Library for better speed of low-level RTL functions (mostly System.pas and SysUtils.pas). Designed for Delphi 7 and 2007. For more recent Delphi version, you still can use the same principle.
You can only recompile the RTL from the command-line. There should be a makefile in the RTL source directory of your installation. It is designed to be used with the make.exe command-line utility which should be in the "bin" folder of your installation. I would recommend you copy the relevant sources to a separate location for experimentation. I must caution you that the System unit is tightly coupled with the compiler which expects many functions to have a specific name and have particular parameter lists, if any are even declared. Many RTL "helper" functions don't have any formally declared parameters, yet expect parameters to be passed in a certain fashion.
Another bit of caution is changing the interface declarations of certain classes, functions or types. Doing so may cause serious incompatibilities with existing DCU files and components. For this reason you must be very careful when intermixing DCU files from the included RTL or third-party components with your custom modified versions. I would suggest you start by only making implementation section changes only before venturing into the mine-field of interface breaking changes.
Very recently I have come back to Delphi after a long pause and written a rather straightforward utility app my client requested to support an older release...
I know these days the size does not matter much, but it struck me as odd that the one-unit application, when compiled, amounted to 1'084'416 b executable. The one and only .pas unit I wrote is some 20.8k large, mostly because of the richness of the gui.
The uses clause is as follows:
uses
Windows, Messages, SysUtils, Variants, Classes, Controls, Forms, strutils,
Dialogs, ADODB, DB, DBGrids, ExtCtrls, DBCtrls, StdCtrls, Grids, Menus,
Buttons;
I wonder if there's any way I could reduce the size of the application to 300-400k or less?
Did you do a debug or release build? (Make it release for smaller size, make sure optimization is on, debug information turned off)
Did you turn off RTII (delphi 2010 and up) if not needed? (Smaller EXE sizes.)
Number of units in your uses clause of your main unit, is not a good way to guess EXE size. Think of it this way: The VCL itself is one large amount of code, the Database Layer another, and the stuff you write is probably a very small percentage of the EXE size.
To understand your executable size, try the JCL Project Analyzer, or read the MAP file that is produced when you turn on the Map option. This will tell you exactly what is inside your executable file.
It would be silly for various reasons, but you could get a smaller executable by using Delphi 7, for example. In the end when I make an application and I want to make it smaller, I look at how much time it would take, and how much effort to rebuild everything (such as with a vcl alternative) and I then say to myself, forget about it.
You can try using KOL (Key Objects Library is a set of objects to develop power (but small) 32 bit Windows GUI applications using Delphi but without VCL). KOL allows to create very compact Windows32 GUI applications (starting from ~11K without compression - if suggested system units replacement used). The most of code is converted to built-in assembler.
Another option is use a exe compressor like UPX.
MapFileStats (DelphiTools.info) is a good (free) tool that allows you to see how much space every unit occupies in your executable. My own tool DelphiUnitSizes is an alternative that in addition to unit sizes also display the size of each function or class.
Delphi 2010 made the default executable about 30% larger, probably because of RTTI included in the RTL/VCL units, so you can use an older version of Delphi for smaller exe-size.
As others have mentioned UPX is a great tool too, the false positives by virusscanners are not that frequent in my experience.
The size of Delphi-executables can be very much trimmed down using custom System-units and UPX-compression. I can generate exe-files that are less that 64kb in size with my Delphi-based game-generator ZGameEditor, even with Delphi Berlin.
How big is your DFM? It is included as a resource in your EXE. Depending on how complex your GUI is, you might find that creating the GUI at runtime in code could reduce the EXE size.
You may also considere to add the following line to the top of the project file:
{$SetPEFlags 1}
Explanation here : http://hallvards.blogspot.fr/2006/09/hack12-create-smaller-exe-files.html
Yes, but then you'd need to supply the other code units as additional files. Just as .net required the assembly, and you have VB runtimes etc., this is just the Delphi runtime - but it's embedded in the exe.
Another option is to compress the executable, there are tools for that around.
You say you're coming back to Delphi. If you still have an old version available, use that - every new version adds extra features and if you don't need them them your exes will be smaller without them.
Make sure you're only including units you actually use.
But whatever you do I very much doubt you'll get down to 300k. If memory serves, even a 'hello world' application in Delphi 2 would be larger than that.
Do you have any resource files or pictures that are linked into the project?
I think the ADODB also includes quite some overhead. If your app really uses a database then a mere 1MB isn't too bad for file size? Don't forget that your app is just this exe - no need for extra dll's etc.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Reduce exe file
What are some tools that, given an EXE file, remove all unused code and make a new EXE file with code really used by the application? I think that something like that should exist. Just for curiosity; but I think that it can be really good as tools for producing a smaller EXE file without unused code.
P.S.: Delphi produces standalone EXE files that contain code of all object used in an application, but not all elements of this object are really used. This makes big files.
I remember the first version of Pascal that include only code really used and did not insert unused code, and EXE files were smaller.
Current Delphi also excludes unused code. You can easily see this in Delphi. If you compile, you get 'blue dots' in the gutter of your code. Functions that are not used don't have blue dots, meaning they are excluded. If you check the Optimization checkbox in project options, code is rewritten to make more use of registers thus eliminating certain variables.
Nevertheless, Delphi executables grow, especiall when using certain units. I think the smallest .exe you can create in Delphi 7 is about 10Kb. In later versions this will probably be a bit larger.
Important causes of file size is
resources. Large or lots of images consume a lot of space. If you use icons on multiple forms, make sure to put them in a central image list (on a shared datasource). Use one of the available PngImageList implementations for smaller image size against better quality.
rtti. The runtime type information causes class definitions to consume extra space. Thise space is partly due to the meta information about the class, but mainly because all extra code. Any methods that may be called using RTTI could be bound in a kind of 'late binding' fashion. Therefor, the compiler cannot know whether the methods can be eliminated, so it needs to include them in the executable.
registered classes. Similar to 2. If a class is registered, it can be fetched and instantiated using its name as a string. Those classes must be included in the project, even if they are never used, just because the compiler cannot know if they are needed.
It's a fact that RTTI is expanded in recent Delphi versions. I think this also causes the RTTI meta information about classes to consume more space. There's only so much you can do about that.
In general, I think the Delphi compiler still does a lot of optimizing. You shouldn't have to worry about exe file size. If you do, you could try a packer like upx. I've got good esperiences with upx. It cuts down the executables to about a fifth or less of their original size, while retaining all functionality.
If you application is huge, check if you don't have a lot of debug info compiled in.
Try a release build and check if it's any smaller.
What i sometimes do is configure the project to compile all .dcu files into a single folder. That way you quickly see all of the useless units that get compiled into your .exe. It often happens that you include a single unit for a single function, but in turn you get a whole tree of dependent units. You'll just have to search your uses clauses and try to get rid of these dependencies somehow.
I think both gexperts and cnpack contain tools to show dependencies, or to scan for unused units in your project. They can be helpful with this.
After you've removed useless dependencies, you can always compress your compiled exe with upx. There are supposed disadvantages to that (barry kelly wrote about it some time ago), but i've got good experiences with it. It sometimes makes the file 4x as small which can be a big deal.