Reduce exe file

12,217

Solution 1

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!

Solution 2

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

Solution 3

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.

Solution 4

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.

Solution 5

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.

Share:
12,217
Marcello Impastato
Author by

Marcello Impastato

Computer consultant. Web Designer. Programmer.

Updated on June 15, 2022

Comments

  • Marcello Impastato
    Marcello Impastato almost 2 years

    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?

  • David Heffernan
    David Heffernan over 12 years
    That used to be largely true, but the recent changes in RTTI have complicated matters somewhat.
  • cyco130
    cyco130 over 12 years
    Hmm, I haven't used the most recent Delphis. +1 for the info.
  • Uwe Raabe
    Uwe Raabe over 12 years
    Before using UPX you should read this article from Jordan Russel to be aware of the downsides.
  • Robert Love
    Robert Love over 12 years
    The new Livebinding feature will not work if you turn off the RTTI.
  • David Heffernan
    David Heffernan over 12 years
    @Robert Yes, I guess quite a few things will fail without RTTI. But I bet the vast majority of extant code will be fine.
  • Johan
    Johan over 12 years
    How much will this actually reduce the size (percentage wise)?
  • David Heffernan
    David Heffernan over 12 years
    @Johan 30% reduction in size for my executable. But this figure varies between different projects.
  • Admin
    Admin over 12 years
    +1, Excellent tip :) I couldn't compile the directive {$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED} though. To correct it, make sure Windows is included in uses clause.
  • David Heffernan
    David Heffernan over 12 years
    @Blobby or just redeclare the
  • dthorpe
    dthorpe over 11 years
    Be careful stripping relocation entries from exes. Though rare, there are situations where an .exe may not be able to load at its preferred base address.
  • David Heffernan
    David Heffernan over 11 years
    @dthorpe Can you give an example? I've never heard of such a thing.
  • dthorpe
    dthorpe over 11 years
    Correction: A unit having an initialization section does not inherently cause everything in that unit to be linked into the executable. The initialization section is treated internally just like any other function: only the types that it refers to will be linked into the executable. Some VCL unit intialization sections do drag in a lot of material because they touch critical core classes that have RTTI baggage or hefty virtual method tables. If your unit initialization section touches none of your classes, it won't bulk up your exe.
  • dthorpe
    dthorpe over 11 years
    Using dlls or packages will shrink the .exe file size significantly, but the tradeoff is that the dll/bpl file size that you have to distribute with your exe is many times larger than what the exe would have been if statically linked with the dcus. Switching to BPL packages provides a net file size savings only if you have multiple applications sharing the same packages.
  • David Heffernan
    David Heffernan over 11 years
    @dthorpe The system DLLs will be relocated. And what's global heap? No such thing so far as I know. Are you thinking of 16 bit?
  • David Heffernan
    David Heffernan over 11 years
    @dthorpe The exe comes in first. It always gets loaded at its preferred base address. Then come the DLLs. Now they way be relocated. Even system DLLs like comctl32 can be relocated. System DLLs are no more special than other DLLs. Sharing of code segments between processes happens for all DLLs. Which API for global heap?
  • dthorpe
    dthorpe over 11 years
    Wish you were there when I was implementing $SetPEFlags. Your confidence would have made my work much simpler. And I would have a handy scapegoat if/when fate didn't agree with our decision. ;>
  • dthorpe
    dthorpe over 11 years
  • David Heffernan
    David Heffernan over 11 years
    @dthorpe It's global in name only on Win32. Name left over from Win16.
  • dthorpe
    dthorpe over 11 years
    It still allocates memory from the process virtual address space. And as such, global memory allocations can block placement of code at preferred base addresses. Usually DLLs.
  • David Heffernan
    David Heffernan over 11 years
    @dthorpe Sure, but the exe is loaded before any code has a chance to call GlobalAlloc. Process virtual address really is isolated.
  • dthorpe
    dthorpe over 11 years
    From MSDN: "While this may save space in the executable file, it may cause the executable not to work on other Win32-based implementations. For example, say you built an EXE for Windows NT and based the EXE at 0x10000. If you told the linker to strip the relocations, the EXE wouldn't run under Windows 95, where the address 0x10000 is already in use." msdn.microsoft.com/en-us/library/ms809762.aspx
  • David Heffernan
    David Heffernan over 11 years
    @dthorpe I only build for XP and later, NT only.
  • dthorpe
    dthorpe over 11 years
    When you advise folks to turn off relocations, you should advise them of the limitations. Nothing is free.
  • David Heffernan
    David Heffernan over 11 years
    @dthorpe I thought I had done that. When I said only to do it on an EXE. So far as I know, in the modern world, reloc stripping is no probs for executable files.
  • David Heffernan
    David Heffernan over 11 years
    @dthorpe As a parting line, I'd say that I've been stripping for years without any trouble!!
  • David Heffernan
    David Heffernan over 11 years
    @dthorpe Having said all of that in defence of stripping, I'm hardly sure it's worth it. If the EXE doesn't need rebasing then the relocs will never even be read off the disk. Stripping might reduce the size of your exe for distribution/download, but it's only around 5% for my executable. Is it ever worth it? I doubt it.
  • David Heffernan
    David Heffernan over 11 years
    @dthorpe Take a look at MSDN docs for the /FIXED option of LINK: msdn.microsoft.com/en-us/library/w368ysh2.aspx specifically this bit: "By default, /FIXED:NO is the default when building a DLL, and /FIXED is the default for any other project type."
  • Server Overflow
    Server Overflow about 2 years
    I am not going to use this flag in my program because of the problems it will bring up, BUT just out of curiosity: how much one will expect to reduce the size if this flag is used? :)
  • Server Overflow
    Server Overflow about 2 years
    UPX, ASPack <-- Warning many antivirus programs don't like AT ALL those packers!
  • David Heffernan
    David Heffernan about 2 years
    @ServerOverflow Varies for program to program. Try it with your program.
  • Server Overflow
    Server Overflow about 2 years
    Hm... strange. I added the two lines to my DPR project (Delphi 10.4). The exe size is the same.
  • Server Overflow
    Server Overflow about 2 years
    Hm... Interesting. I moved the two lines IMMEDIATELY after the "Program" line at the top of DPR. Now the IDE/compiler froze in the middle of the compilation. Looks like I have found a compiler bug!
  • Server Overflow
    Server Overflow about 2 years
    More weird things: I right-click the Delphi button is taskbar and clicked "Close". Now a dlg box ask me if I want to cancel the background compilation AND as long as that dlg is open, the compilation continues....