如何合并归档文件中的目标文件内容?

问题描述

我将几个(数百个)C ++文件编译为目标文件,然后ar将它们编译为档案。我注意到每个目标文件都很大,大概每个目标文件都包含一组丰富的标题。整个对象的集合大部分相同。归档文件的大小是各个部分的总和,达到GB大小(这是可笑的IMO)。

假设目标文件内容大部分是在共享标头中找到的内容的重复,那么如何减小归档的大小?最好采用不完全重写代码或构建系统的方式。


我比较了一个带有和不带有调试信息(objcopy --strip-debug foo.o foo_no_debug.o)的目标文件的大小,发现对于一个文件,99.5%的内容是调试信息。可能与任何答案有关。我猜想解决方法对调试信息标志的限制更大。

解决方法

一些搜索和实验我找到了答案。

简短版本:ld选项--relocatable-r,有时也称为“增量链接”:

ld -r -o abc.o a.o b.o c.o

长版:

ld可以做到,但确实很糟糕。

将包含标头的10个相同文件逐步链接在一起,并使用-g3选项进行编译,仅将归档文件的大小从24MB减小到16MB。更糟糕的是ld不支持压缩,这意味着任何压缩的调试信息(与-gz一起编译)都将通过增量链接进行解压缩!

值得庆幸的是,ld.gold的性能要好得多,归档文件为5MB。 ld.gold还具有用于压缩输出的选项-O6--compress-debug-sections=zlib,可将存档大小减小到3MB。

测试时使用的标题:

#include <vector>
#include <array>
#include <memory>
#include <sys/time.h>
#include <pthread.h>
#include <boost/date_time.hpp>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/filesystem.hpp>
#include <boost/bind.hpp>
#include <boost/memory_order.hpp>
#include <boost/token_functions.hpp>
#include <boost/scope_exit.hpp>
#include <boost/operators.hpp>
#include <boost/foreach.hpp>
#include <boost/concept_check.hpp>
#include <boost/concept_archetype.hpp>
#include <boost/array.hpp>
#include <sqlite3.h>
#include <elf.h>
#include <unistd.h>

使用GCC 6.3.0,GNU ld 2.28和GNU gold 1.14进行了测试。没有测试LLVM lld,但是由于支持相同的选项并且总体上处于领先地位,所以我希望得到类似的结果。