最小化导出的符号
如果您的应用程序或framework具有公共接口,则应该将导出的符号限制为接口所需的符号。导出的符号会占用可执行文件中的空间,应该尽可能减少。这不仅减少了可执行文件的大小,还减少了动态链接器所做的工作量。
默认情况下,Xcode会从项目中导出所有符号。您可以使用下面的信息来识别和删除不想导出的符号。
识别导出的符号
要查看应用程序导出的符号,请使用nm
工具。此工具读取可执行文件的符号表并显示您请求的符号信息。您可以查看所有符号,也可以只查看可执行代码特定段中的符号。例如,要只显示外部可用的全局符号,可以在命令行上指定-g
选项。
要查看符号的详细信息,可以使用带-m
选项的命令nm。该选项的输出告诉您符号的类型,以及它是外部的还是本地的(非外部的)。例如,要查看TextEdit
应用程序的详细符号信息,可以如下所示使用nm:
1 | %cd /Applications/TextEdit.app/Contents/MacOS |
结果输出的一部分可能如下所示:
1 | 9005cea4 (prebound undefined [lazy bound]) external _abort (from libSystem) |
在此模式下,nm根据符号显示各种信息。对于驻留在__TEXT段中的函数和其他代码,nm会显示预绑定信息和初始库(originating library)。对于__DATA段中的信息,nm显示符号的specific section及其链接。对于所有符号,nm显示该符号是外部的还是本地的。
限制导出的符号
如果您知道要从项目导出的符号,则应该创建一个导出文件,并将该文件添加到项目的链接器设置中。导出文件是一个纯文本文件,其中包含您希望外部调用者可用的符号的名称。每个符号必须列在单独的一行上。前导和后面的空格不被认为是符号名称的一部分。以#号开头的行将被忽略。
要在Xcode项目中包含导出文件,请修改项目的target或构建样式设置。将“Exported symbols file”设置的值设置为导出文件的名称。Xcode将适当的选项传递给静态链接器。
若要从命令行导出符号列表,请在链接器命令中添加-exported_symbols_list
选项。您也可以导出所有符号,然后限制特定列表,而不是导出特定的符号列表。要限制特定的符号列表,请在链接器命令中使用-unexported_symbols_list
选项。
注意,运行时库导出的符号必须显式地包含在导出文件中,以便应用程序能够正常启动。若要收集这些符号的列表,请在没有导出文件的情况下链接代码,然后从终端执行nm -m
命令。从结果输出中,收集任何标记为external且不属于代码的符号,并将它们添加到导出文件中。
使用GCC 4.0限制导出
GCC 4.0支持为单个符号自定义可见性属性。此外,编译器提供了编译时标志,允许您为已编译文件的所有符号设置默认可见性。有关使用GCC 4.0的新符号可见性特性的信息,请参阅c++运行时环境编程指南中的“控制符号可见性”。