Инкрементное связывание с использованием gcc on linux. Является ли это возможным?
Как разрабатывается мой командный проект, мы генерируем библиотеку Shared Object для нашего приложения из всех наших объектных файлов .o
. Моя задача (надеюсь, она достаточно конкретна, но также достаточно общая, чтобы быть полезной для других!) Заключается в связывании только с объектными файлами, которые были изменены с момента создания исполняемого файла. Например, вот командная строка, которую я использую для сборки .so:
g++34 -shared -rdynamic -m64 -Wl,-rpath,'$ORIGIN' MyObject1.o MyObject2.o MyObject3.o MyObject4.o -o libMySharedLibrary.so
Работает так, как ожидалось!:) Моя цель состоит в том, чтобы иметь возможность связываться только с измененными объектными файлами с этого момента, чтобы ускорить параллельный процесс связывания. Пример команды:
g++34 -shared -rdynamic -m64 -Wl,-rpath,'$ORIGIN' MyObject1.o MyObject3.o -o libMySharedLibrary.so
Что бы обновить libMySharedLibrary.so
с новыми объектными файлами, а также сохранить старые файлы объектов в libMySharedLibrary.so
. На самом деле, когда я генерирую libMySharedLibrary.so
, используя указанную выше команду, размер файла намного меньше, чем размер всех объектных файлов, поэтому я почти уверен, что указанная выше команда не делает то, что я хочу.
В ходе моего исследования я обнаружил, что для компоновщика есть опция -i
, которая совпадает с опцией -r
, которая, как представляется, просто объединяет все объектные файлы в один большой файл объекта. К сожалению, не кажется, что это то, что я хочу.
Короче говоря, я хотел бы связать только измененные файлы объектов после начальной ссылки, что приведет к более быстрому процессу связывания для будущих ссылок. Есть ли способ сделать это?
EDIT: пример того, что я пробовал с помощью -i/-r
:
Пример команды: g++34 -Wl,-r -nostdlib -rdynamic -m64 -Wl,-rpath,'$ORIGIN' MyObject1.o MyObject2.o MyObject3.o MyObject4.o -o AllMyObjects.o
Мне пришлось добавить тег -nostdlib
, чтобы он не кричал на меня о необходимости его и не удалял -shared
, потому что разделяемые объекты не допускаются с тегом -r
.
Эта команда, похоже, захлопнет все мои файлы .o в один большой файл .o. Поэтому, если бы я мог просто обновить этот .o файл отсюда только с измененными файлами .o, это было бы здорово. После того, как AllMyObjects.o изначально был создан, я пробовал эту команду: g++34 -Wl,-r -nostdlib -rdynamic -m64 -Wl,-rpath,'$ORIGIN' MyObject1.o MyObject3.o -o AllMyObjects.o
, но он также создавал бы гораздо меньший размер (размер файла) AllMyObjects.o
, поэтому я предполагаю, что он не может иметь все объектных файлов. Я чувствую, что это то, что я, вероятно, совершу небольшую ошибку. У кого-нибудь есть совет? Спасибо заранее.
Ответы
Ответ 1
Похоже, вы правы в отношении -shared
и -r
, которые не работают вместе. Я скептически относился к вашей старой версии GCC, но даже в Ubuntu 10.10 я вижу то же самое:
$ ld -shared -r
/usr/bin/ld.bfd.real: -r and -shared may not be used together
К сожалению, это означает, что вы достигли тупиковой ситуации, если вам абсолютно необходимы общие объекты. Компонент binutils просто не реализует его.
Если статические библиотеки являются для вас вариантом, это просто архивы, с которыми легко можно манипулировать с помощью утилиты ar
.
В противном случае вам придется искать разные компоновщики или компиляторы. Я не могу гарантировать, что вы найдете эту функцию, хотя она кажется экзотической.
Ответ 2
Вы можете получить поведение, которое вы используете после использования архивных/статических библиотек, но исходная ссылка будет занимать одинаковое время.
Использование архивного файла:
# Initially create the archive
ar r libmylib.a <all object files>
# Create your shared object (re-use this line after libmylib.a is updated)
g++ -shared -rdynamic -m64 -Wl,-rpath,'$ORIGIN' libmylib.a -o libmylib.so
# Update the archive file
ar r libmylib.a updated1.o updated2.o
Как я уже сказал, все равно потребуется столько же времени, чтобы связать .so
, как это было раньше.