Reduce exe file
Asked Answered
I

6

21

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?

Ipswich answered 13/9, 2011 at 7:59 Comment(1)
In C/C++ with MSVC you can set the /OPT:REF option when linking, which removes all codes and datas that are not used.Taima
C
21

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!

Console answered 13/9, 2011 at 8:8 Comment(27)
The new Livebinding feature will not work if you turn off the RTTI.Maxwellmaxy
@Robert Yes, I guess quite a few things will fail without RTTI. But I bet the vast majority of extant code will be fine.Console
How much will this actually reduce the size (percentage wise)?Tanker
@Tanker 30% reduction in size for my executable. But this figure varies between different projects.Console
+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.Dineen
@Blobby or just redeclare theConsole
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.Butyl
@Butyl Can you give an example? I've never heard of such a thing.Console
@Butyl 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?Console
@Butyl 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?Console
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. ;>Butyl
global heap: GlobalAlloc() msdn.microsoft.com/en-us/library/windows/desktop/…Butyl
@Butyl It's global in name only on Win32. Name left over from Win16.Console
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.Butyl
@Butyl Sure, but the exe is loaded before any code has a chance to call GlobalAlloc. Process virtual address really is isolated.Console
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.aspxButyl
@Butyl I only build for XP and later, NT only.Console
When you advise folks to turn off relocations, you should advise them of the limitations. Nothing is free.Butyl
@Butyl 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.Console
@Butyl As a parting line, I'd say that I've been stripping for years without any trouble!!Console
@Butyl 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.Console
@Butyl 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."Console
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? :)Goodlooking
@ServerOverflow Varies for program to program. Try it with your program.Console
Hm... strange. I added the two lines to my DPR project (Delphi 10.4). The exe size is the same.Goodlooking
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!Goodlooking
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....Goodlooking
V
8

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

Valvate answered 13/9, 2011 at 9:12 Comment(1)
UPX, ASPack <-- Warning many antivirus programs don't like AT ALL those packers!Goodlooking
P
4

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.

Preside answered 13/9, 2011 at 9:4 Comment(1)
Before using UPX you should read this article from Jordan Russel to be aware of the downsides.Escrow
M
3

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.

Majors answered 13/9, 2011 at 8:8 Comment(2)
That used to be largely true, but the recent changes in RTTI have complicated matters somewhat.Console
Hmm, I haven't used the most recent Delphis. +1 for the info.Majors
I
0

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.

Inkerman answered 18/11, 2011 at 19:0 Comment(2)
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.Butyl
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.Butyl
G
0

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.

Goodlooking answered 29/3, 2022 at 8:49 Comment(1)
It's called WinRAR and I'll link it.Dunleavy

© 2022 - 2024 — McMap. All rights reserved.