Использование ссылок --start-group и --end-group быстрее, чем создание статической библиотеки? - PullRequest
11 голосов
/ 14 августа 2011

Если кто-то строит статические библиотеки в своих скриптах сборки, и кто-то хочет использовать эти статические библиотеки для компоновки конечного исполняемого файла, важен порядок, в котором упоминаются файлы .a:

g++ main.o hw.a gui.a -o executable

Если gui.a использует что-то, определенное в hw.a, ссылка потерпит неудачу, потому что во время обработки hw.a компоновщик еще не знает, что определение понадобится позже, и не включает его в исполняемый файл.Вручную возиться с линией компоновщика нецелесообразно, поэтому решение состоит в том, чтобы использовать --start-group и --end-group, что заставляет компоновщик дважды проходить по библиотекам, пока не будут найдены неопределенные символы.

g++ main.o -Wl,--start-group hw.a gui.a -Wl,--end-group -o executable

Однако в руководстве GNU ld говорится:

Использование этой опции приводит к значительным потерям производительности.Лучше всего использовать его только тогда, когда между двумя или более архивами есть неизбежные циклические ссылки.

Поэтому я подумал, что может быть лучше взять все файлы .a и собрать их в один .a файл с индексом (опция -s в GNU ar), который говорит, в каком порядке файлы должны быть связаны.Тогда каждый дает только один .a файл g++.

Но мне интересно, будет ли это быстрее или медленнее, чем использование групповых команд.И есть ли проблемы с этим подходом?Мне также интересно, есть ли лучший способ решить эти проблемы взаимозависимости?


РЕДАКТИРОВАТЬ: я написал программу, которая принимает список .a файлов и создает объединенный файл .a.Работает с общим форматом GNU ar.Сборка всех статических библиотек LLVM работает следующим образом

$ ./arcat -o combined.a ~/usr/llvm/lib/libLLVM*.a

Я сравнил скорость с распаковкой всех файлов .a вручную, а затем поместил их в новый файл .a с помощью ar, пересчитав индекс,Используя мой arcat инструмент, я получаю постоянную продолжительность работы около 500 мс.Используя ручной способ, время сильно меняется, и занимает около 2 с.Поэтому я думаю, что оно того стоит.

Код здесь .Я положил это в общественное достояние:)

Ответы [ 2 ]

3 голосов
/ 14 августа 2011

Вы можете определить порядок, используя утилиты lorder и tsort, например

libs='/usr/lib/libncurses.a /usr/lib/libedit.a'
libs_ordered=$(lorder $libs | tsort)

, что приведет к /usr/lib/libedit.a /usr/lib/libncurses.a, поскольку libedit зависит от libncurses.

только преимущество выше --start-group, если вы не запускаете lorder и tsort снова для каждой команды ссылки.Кроме того, он не допускает взаимных / циклических зависимостей, как --start-group.

2 голосов
/ 14 августа 2011

Есть ли третий вариант, когда вы просто начинаете создавать одну библиотеку? У меня была похожая проблема, и я в итоге решил пойти с третьим вариантом.

По моему опыту, группа работает медленнее, чем просто объединение файлов .a. Вы можете извлечь все файлы из архива, а затем создать новый файл .a из файлов меньшего размера

Однако вы должны быть осторожны с ситуацией, когда оба файла содержат одно и то же определение (вы можете явно проверить это с помощью nm, чтобы увидеть, какие определения содержатся в каждой библиотеке)

...