Инкрементное связывание с использованием 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, как это было раньше.