Объединение статических библиотек - PullRequest
13 голосов
/ 20 марта 2009

Предположим, у меня есть три C статических библиотеки, которые говорят libColor.a , что зависит от * libRGB. * A, что, в свою очередь, зависит от libPixel.a . Библиотека libColor.a , как говорят, зависит от библиотеки libRGB.a , поскольку в libColor.a есть некоторые ссылки на некоторые символы, определенные в libRGB.a . Как объединить все вышеперечисленные библиотеки в новый libNewColor.a , который является независимым?

Независимо означает, что в новой библиотеке должны быть определены все символы. Поэтому при связывании мне просто нужно дать -lNewColor . Размер новой библиотеки должен быть минимальным, т.е. она не должна содержать никаких символов в libRGB.a , которая не используется libColor.a и т. Д. Я попытал счастья, используя различные опции в команде ar (используется для создания и обновления статических библиотек / архивов).

Ответы [ 3 ]

16 голосов
/ 03 сентября 2013

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

CREATE libNewColor.a
ADDLIB libColor.a
ADDLIB libRGB.a
ADDLIB libPixel.a
SAVE
END

Тогда вы можете вызвать ar следующим образом:

ar -M < script.ar

и вы получите libNewColor.a, который содержит все файлы .o из libColor.a libRGB.a и libPixel.a.

Кроме того, вы также можете добавить обычные файлы .o, а также команду ADDMOD:

CREATE libNewColor.a
ADDLIB libColor.a
ADDLIB libRGB.a
ADDLIB libPixel.a
ADDMOD someRandomCompiledFile.o
SAVE
END

Кроме того, эти сценарии очень просто генерировать в Makefiles, поэтому я обычно создаю несколько универсальное правило make-файла для создания архивов, которое фактически генерирует сценарий и вызывает ar в сценарии. Примерно так:

$(OUTARC): $(OBJECTS)
    $(SILENT)echo "CREATE $@" > $(ODIR)/$(ARSCRIPT)
    $(SILENT)for a in $(ARCHIVES); do (echo "ADDLIB $$a" >> $(ODIR)/$(ARSCRIPT)); done
    $(SILENT)echo "ADDMOD $(OBJECTS)" >> $(ODIR)/$(ARSCRIPT)
    $(SILENT)echo "SAVE" >> $(ODIR)/$(ARSCRIPT)
    $(SILENT)echo "END" >> $(ODIR)/$(ARSCRIPT)
    $(SILENT)$(AR) -M < $(ODIR)/$(ARSCRIPT)

Хотя теперь, когда я смотрю на это, я думаю, что это не сработает, если $ (OBJECTS) пусто (т.е. если вы просто хотите объединить архивы без добавления дополнительных объектных файлов), но я оставлю это в качестве упражнения для читателя чтобы исправить эту проблему, если это необходимо ...: D

Вот документы для этой функции:

https://sourceware.org/binutils/docs/binutils/ar-scripts.html#ar-scripts

12 голосов
/ 20 марта 2009

1 / Извлеките ВСЕ объектные файлы из каждой библиотеки (используя ar) и попробуйте скомпилировать ваш код без библиотек или каких-либо объектных файлов. Вы, вероятно, получите абсолютную загрузку неопределенных символов. Если вы не получили неопределенных символов, перейдите к шагу 5.

2 / Возьмите первый и выясните, какой объектный файл удовлетворяет этому символу (используя nm).

3 / Запишите этот объектный файл, затем скомпилируйте ваш код, включая новый объектный файл. Вы получите новый список неопределенных символов или, если их нет, перейдите к шагу 5.

4 / Перейти к шагу 2.

5 / Объединить все объектные файлы в вашем списке (если есть) в одну библиотеку (снова с ar).

Взрыв! Там у вас есть это. Попробуйте связать свой код без каких-либо объектов, но с новой библиотекой.

Все это можно относительно легко автоматизировать с помощью сценария оболочки.

5 голосов
/ 20 марта 2009

Статическая библиотека - это не более, чем архив некоторых объектных файлов (.o). Что вы можете сделать, это извлечь все объекты из двух библиотек (используя «ar x»), а затем использовать «ar», чтобы связать их вместе в новой библиотеке.

...