减少exe文件
Posted
技术标签:
【中文标题】减少exe文件【英文标题】:Reduce exe file 【发布时间】:2011-11-15 22:46:06 【问题描述】:使用 Delphi(或一般任何工具,当然如果存在的话),是否可以减小 exe 文件的大小,删除所有未使用但存在的代码? (例如,存在但从未调用过的函数或过程)。 我记得在 Pascal 中,使用单元(没有对象)编译器只包含真正使用的过程和函数,并且会从最终的 exe 中去除单元中未使用的例程。
使用 Object-pascal,我记得在 Delphi 1 中,对象的所有成员都包含在 exe 中; 自 Delphi-XE2 以来有什么变化吗?
【问题讨论】:
在带有 MSVC 的 C/C++ 中,您可以在链接时设置/OPT:REF
选项,这会删除所有未使用的代码和数据。
【参考方案1】:
如果您不使用 RTTI,您可以将其添加到 .dpr 文件的顶部(紧跟在 program
之后)以删除额外的 RTTI 信息:
$IFOPT D-$WEAKLINKRTTI ON$ENDIF
$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])
如果您想将其从所有 RTL/VCL 单元中剥离出来,那么您还需要将它们包含在您的项目文件中,这样上述设置才能生效。我认为我不建议这样做,因为我不认为减少可执行文件大小值得编译您自己的 RTL/VCL 的复杂性。
您还可以在 .dpr 文件的某处再次添加以下内容:
$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED
这将去除 .exe 中不需要的重定位信息。不要将此添加到 DLL 或包中!
【讨论】:
如果您关闭 RTTI,新的 Livebinding 功能将无法使用。 @Robert 是的,我猜如果没有 RTTI,很多事情都会失败。但我敢打赌,绝大多数现存的代码都会没问题。 希望你在我实施 $SetPEFlags 时在场。你的信任会让我的工作变得更简单。如果/当命运不同意我们的决定时,我会有一个方便的替罪羊。 ;> 来自 MSDN:“虽然这可能会节省可执行文件中的空间,但可能会导致可执行文件无法在其他基于 Win32 的实现上运行。例如,假设您为 Windows NT 和基于0x10000 处的 EXE。如果您告诉链接器去除重定位,EXE 将无法在 Windows 95 下运行,因为地址 0x10000 已经在使用中。 msdn.microsoft.com/en-us/library/ms809762.aspx 当你建议人们关闭重定位时,你应该告诉他们这些限制。没有什么是免费的。【参考方案2】:reduce the application EXE size - 优秀文章
(取自上面的链接)
一般来说,用 Delphi 创建的 EXE 文件比 EXE 文件大 用另一种编程语言创建。原因是VCL。 (当然,VCL 有很多优点……)
有几种方法可以减小 EXE 的大小:
01) 使用 EXE-Packer (UPX, ASPack,...)-UPX
02) 使用 KOL。
03) 在没有 VCL 的情况下编写应用程序
04) 使用 ACL(API 控件库)
05) 使用 StripReloc。
06) 停用远程调试信息和 TD32。
07) 您可能希望将代码放入 dll 中。
08) 不要在一个表单上多次放置相同的图像。在运行时加载它们。
09) 使用压缩图像(JPG 而不是 BMP)
10) 在 DFM 文件中存储较少的属性
【讨论】:
【参考方案3】:只是为了补充别人写的……
智能链接器将在以下情况下消除未使用的例程except:
该单元有一个 initialization
部分 - 不幸的是,RTL/VCL(类、SysUtils、Windows、表单......等等)中的许多最大单元都有初始化部分,所以如果它们在您的uses
子句将整个辣酱玉米饼馅链接到您的代码中。 RTL/VCL 中的大部分代码都可以重构以减少或消除这种情况,但会破坏向后兼容性。
例程是类的一部分,并被标记为 virtual 或 dynamic - 如果您在具有虚拟或动态方法的代码中实例化和对象,无论您是否调用它们,这些方法都会链接到您的可执行文件中。
减少 exe 文件大小的其他步骤:
利用表单继承 - 如果您有许多相似的表单,请创建一个基本表单供它们继承。这些子表单将仅在其 dfms 中存储与基本表单不同的属性。这可以通过消除 dfms 中的冗余信息来显着减小可执行文件的大小。
将任何大型图形存储在外部文件中并按需加载它们 - 启动画面、“皮肤”、图标集等确实会使 exe 的大小膨胀。当这些文件嵌入到 exe 中时,Delphi 并不总是以最有效的格式存储这些文件。
您可以通过在编译后从 exe 中删除某些未使用的数据来将 exe 的大小减少 10% - 30%。有第三方工具可以做到这一点,但您可以通过设置适当的 PE 标头 flags 来消除一些麻烦。在使用它之前,请确保您了解每个标志的含义,因为某些标志可能会使您的 exe 无法使用。
将 RTL/VLC 的部分复制到您自己的单元中 - 不要在您的 uses 子句中包含类或 SysUtils,而是创建一个新单元并将您需要的类和函数复制到单元中。然后改用它。
将代码分解为可加载的模块 - 如果您有多个重复使用相同单元的 exe,您可以使用 dll 或 bpls 将它们缩小,而不是将所有内容静态链接到 exe。无论有多少 exe 需要,一个 dll/bpl 只会被加载到内存中一次。
【讨论】:
更正:具有初始化部分的单元不会固有地导致该单元中的所有内容都链接到可执行文件中。初始化部分在内部就像任何其他函数一样被处理:只有它引用的类型才会链接到可执行文件中。一些 VCL 单元初始化部分确实拖入了大量材料,因为它们涉及具有 RTTI 包或大量虚拟方法表的关键核心类。如果您的单元初始化部分不涉及您的任何类,它不会增加您的 exe。 使用 dll 或包会显着缩小 .exe 文件的大小,但代价是您必须与 exe 一起分发的 dll/bpl 文件大小比 exe 的大小要大很多倍如果与 dcus 静态链接。仅当您有多个应用程序共享相同的包时,切换到 BPL 包才能节省净文件大小。【参考方案4】:如果您的目标是减小可执行文件的大小,您可以使用压缩它的工具并允许在未压缩时执行它。(=不是 zip)
例如,您可以查看UPX,它可以很好地与 delphi 程序配合使用。
【讨论】:
在使用 UPX 之前,您应该阅读 this article from Jordan Russel 以了解其缺点。【参考方案5】:Delphi 有一个 智能链接 选项,如果我没记错的话,默认情况下它是开启的。它完全符合您的描述。只有使用过的函数和数据会链接到您的 exe。如果您需要进一步的大小压缩,您可以尝试使用众多“exe 压缩器”程序之一。
【讨论】:
这在很大程度上是正确的,但最近 RTTI 的变化使事情变得有些复杂。 嗯,我没用过最新的Delphis。为信息 +1。以上是关于减少exe文件的主要内容,如果未能解决你的问题,请参考以下文章
在 powershell 中使用 DcomPerm.exe 和 SetAcl.exe 的替代方法