减小exe文件大小

20

使用 Delphi(或者一般的其他工具,如果有的话),是否有可能减小可执行文件的大小,删除未被使用但出现在其中的所有代码?(例如,一个存在但从未被调用的函数或过程)。
我记得在 Pascal 中,使用单元(不带对象)时,编译器仅包括真正使用的程序和函数,并将单元中未使用的例程从最终的可执行文件中剥离掉。

对于 Object-pascal,在 Delphi 1 中我记得所有对象成员都包含在 exe 文件中;
自那以后到 Delphi-XE2 是否有所改变?


在使用MSVC编译器的C/C++中,链接时可以设置/OPT:REF选项,该选项会删除所有未使用的代码和数据。 - user26742873
6个回答

21

如果你没有使用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 或软件包!


4
如果关闭 RTTI,新的 Livebinding 功能将无法工作。 - Robert Love
1
@Robert 是的,我猜没有RTTI会有很多问题。但我敢打赌,绝大多数现有的代码都没问题。 - David Heffernan
2
希望你在我实现$SetPEFlags时在场。你的信心会让我的工作变得更简单。如果/当命运不符合我们的决定,我还有一个方便的替罪羊。;> - dthorpe
2
虽然这样可以节省可执行文件中的空间,但可能会导致可执行文件在其他基于Win32的实现上无法正常工作。例如,假设您为Windows NT构建了一个EXE,并将EXE基址设置为0x10000。如果您告诉链接器剥离重定位信息,那么该EXE将无法在Windows 95下运行,因为地址0x10000已经被占用了。 - dthorpe
2
当您建议用户关闭重定位时,您应该告知他们其局限性。没有免费的东西。 - dthorpe
显示剩余22条评论

8

缩小应用程序 EXE 文件大小 - 绝妙的文章

(摘自上述链接)

一般来说,使用 Delphi 创建的 EXE 文件比使用其他编程语言创建的 EXE 文件更大。原因是 VCL。(当然,VCL 有许多优点...)

有几种方法可以减小 EXE 文件的大小:

01) 使用 EXE 打包工具(UPX、ASPack 等)- UPX

02) 使用 KOL。

03) 不使用 VCL 编写应用程序

04) 使用 ACL (API Controls Library)

05) 使用 StripReloc。

06) 关闭远程调试信息和 TD32。

07) 您可能需要将代码放置在 dll 中。

08) 不要在表单上多次放置相同的图像。在运行时加载它们。

09) 使用压缩图像 (JPG 而不是 BMP)

10) 在 DFM 文件中存储较少的属性


UPX,ASPack <-- 警告:许多防病毒程序非常不喜欢这些压缩软件! - Gabriel

4
如果您的目标是减小可执行文件的大小,您可以使用一种工具来压缩它,并允许像未压缩一样执行它。 (=不是zip)
例如,您可以检查UPX,它可以很好地与Delphi程序配合使用。

15
在使用UPX之前,你应该阅读Jordan Russel的这篇文章以了解其中的缺点。 - Uwe Raabe

3

Delphi有一个名为智能链接的选项,默认情况下是打开的,如果我没记错的话。它正是你描述的那样。只有使用过的函数和数据会被链接到你的exe文件中。如果你需要更进一步的大小压缩,你可以尝试其中许多可用的“exe压缩器”程序之一。


3
过去这基本上是正确的,但最近RTTI的变化使事情有些复杂了。 - David Heffernan
1
嗯,我还没有使用过最新的Delphi。感谢提供信息。 - cyco130

0
另一个选项是: 使用WinRar创建安装文件(是的,WinRar可以做到这一点)。 WinRar可以在解压缩完成后自动执行EXE文件。
WinRar具有更高的压缩比。其中一个原因是它将所有文件合并为单个文件,然后开始压缩,而ZIP(和其他类似的不太复杂的压缩程序)会逐个压缩每个文件,然后在压缩后将它们合并成一个大文件。
这使得RAR算法更有机会在您的文件中找到重复数据。
此外,WinRar比其他安装程序更简单(减少:它也没有提供卸载程序,但是您可以使用自己的程序轻松解决)。
免责声明:我与WinRAR无关。

它叫做WinRAR,我会提供链接 - AmigoJack

0
只是为了补充其他人所写的内容...
智能连接器将消除未使用的例程,除非符合以下条件:
  • 单元具有初始化部分-不幸的是,RTL/VCL中的许多最大单元(Classes、SysUtils、Windows、Forms等)都具有初始化部分,因此如果它们在您的uses子句中,则会将整个代码链接到您的代码中。 RTL/VCL中的大部分代码可以重构以减少或消除这种情况,但这将破坏向后兼容性。

  • 该例程是类的一部分,并标记为virtualdynamic- 如果您在代码中实例化对象并具有虚拟或动态方法,则这些方法将链接到您的可执行文件中,无论您是否调用它们。

可以采取的其他步骤以减小exe文件大小:

  • 利用表单继承 - 如果您有许多类似的表单,请为它们创建一个基本表单以进行继承。这些子表单仅会存储它们在 dfms 中与基础表单不同的属性。这可以通过消除 dfms 中的冗余信息大幅减小可执行文件的大小。

  • 将任何大型图形存储在外部文件中并按需加载 - 启动画面、"皮肤"、图标集等可能真正膨胀 exe 的大小。当它们嵌入到 exe 中时,Delphi 并不总是以最有效的格式存储这些文件。

  • 通过在编译后从 exe 中剥离某些未使用的数据,可以将 exe 的大小缩小 10% 到 30%。有第三方工具可以完成此任务,但您可以通过设置适当的 PE 标头 flags 来消除一些无用的东西。在使用之前,请确保了解每个标志的含义,因为某些标志可能会使您的 exe 无法使用。

  • 将 RTL/VLC 的部分内容复制到自己的单元中 - 不要在 uses 子句中包括 Classes 或 SysUtils,而是创建一个新单元,将您需要的类和函数复制到该单元中,然后使用它。

  • 将代码分解成可加载的模块 - 如果您有多个重用相同单元的 exes,您可以通过使用 dll 或 bpl 而不是将所有内容静态链接到 exes 中来使它们变小。无论需要多少个 exes,dll/bpl 只会在内存中加载一次。


2
更正:具有初始化部分的单元并不会本质上导致该单元中的所有内容链接到可执行文件中。初始化部分在内部的处理方式与任何其他函数一样:只有它所引用的类型才会链接到可执行文件中。一些VCL单元的初始化部分确实会拖入大量材料,因为它们涉及具有RTTI负担或庞大虚拟方法表的关键核心类。如果您的单元初始化部分未涉及任何类,则不会增加可执行文件的体积。 - dthorpe
2
使用dll或包将显着缩小.exe文件大小,但是需要分发的dll/bpl文件大小比静态链接到dcus的exe要大得多。如果多个应用程序共享相同的包,则切换到BPL包仅提供净文件大小节省。 - dthorpe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接