Инкрементное связывание с использованием gcc в Linux. Является ли это возможным?

В соответствии с тем, как разрабатывается проект моей команды, мы генерируем библиотеку общих объектов для нашего приложения из всех наших .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, которая, похоже, просто объединяет все объектные файлы в один большой объектный файл. К сожалению, похоже, что это не то, что я хочу.

Короче говоря, я хотел бы связать только измененные объектные файлы после начальной ссылки, что приведет к более быстрому процессу связывания для будущих ссылок. Есть ли способ сделать это?

РЕДАКТИРОВАТЬ: пример того, что я пробовал с -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, поэтому я предполагаю, что у него не может быть всех объектных файлов. Я чувствую, что это то, в чем я, вероятно, допускаю небольшую ошибку. У кого-нибудь есть совет? Заранее спасибо.


person Raphael Raven    schedule 22.11.2010    source источник
comment
Действительно ли фаза связывания доминирует в ваших инкрементальных сборках? Если нет, то зачем?   -  person dmckee --- ex-moderator kitten    schedule 22.11.2010
comment
Можете ли вы показать нам, что вы пробовали с _1 _ / _ 2_? Похоже, что это вариант, который вам нужен, хотя я ожидаю, что вы столкнетесь с конфликтами символов (учитывая, что нет опции «заменить»).   -  person Stéphan Kochen    schedule 22.11.2010
comment
Фаза компоновки - не самая трудоемкая часть моих сборок. Однако это задача, которую мне поставил руководитель моей группы. Мы уже умеем компилировать только то, что изменилось. В настоящее время мы компилируем только то, что изменилось, при этом каждый раз заново связываем каждый объектный файл.   -  person Raphael Raven    schedule 22.11.2010
comment
Обновлено с редактированием того, что я пробовал до сих пор, с -r. Спасибо за помощь.   -  person Raphael Raven    schedule 22.11.2010
comment
Вот минимальный работоспособный пример и синтетический тест без -static: stackoverflow.com/questions/29391965/ Возможно, нам следует изменить заголовок этого вопроса, чтобы указать общие объекты.   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 28.12.2018


Ответы (2)


Похоже, вы правы насчет того, что -shared и -r не работают вместе. Я скептически относился к вашей старой версии GCC, но даже в Ubuntu 10.10 я вижу то же самое:

$ ld -shared -r
/usr/bin/ld.bfd.real: -r and -shared may not be used together

К сожалению, это означает, что вы зашли в тупик, если вам абсолютно необходимы общие объекты. Компоновщик binutils этого просто не реализует.

Если вам подходят статические библиотеки, это просто архивы, которыми можно легко управлять с помощью утилиты ar.

В противном случае вам придется искать разные компоновщики или комплекты компиляторов. Я не могу гарантировать, что вы найдете эту функцию, хотя она кажется экзотической.

person Stéphan Kochen    schedule 22.11.2010
comment
В порядке. Большое спасибо за ваши быстрые ответы. Я обязательно поговорю с руководителем моей группы и посмотрю, можно ли будет использовать статические библиотеки. Также в своем исследовании я обнаружил альтернативный линкер под названием gold, который был разработан Яном Лэнсом Тейлором из Google. Он был добавлен в binutils в марте 2008 года. Я тоже могу изучить это. Я надеялся, что есть способ сделать это с помощью компоновщика по умолчанию, но похоже, что это не так. Еще раз спасибо за вашу помощь! - person Raphael Raven; 22.11.2010
comment
Кажется, у меня установлен gold, но gold -shared -r дает тот же результат. - person Stéphan Kochen; 22.11.2010
comment
Ха-ха, конечно, так и будет. :) В очередной раз благодарим за помощь. - person Raphael Raven; 22.11.2010
comment
-r не делает то, что вы думаете. Он сообщает компоновщику создать объектный файл вместо исполняемого файла или разделяемой библиотеки. Таким образом, ld не поддерживает -r и -shared вместе, потому что это не имеет смысла. Это означало бы «создать общую библиотеку, которая является обычным объектным файлом». - person Maarten; 26.09.2014
comment
Если это правда, то справочная страница GNU binutils ld на самом деле не описывает это как таковое. Но похоже, что справочная страница для OSX ld более ясна: «-r Объединяет объектные файлы для создания другого объектного файла mach-o с типом файла MH_OBJECT». - person Stéphan Kochen; 28.09.2014

Вы можете получить то же поведение, что и при использовании архивных / статических библиотек, но первоначальная ссылка все равно займет такое же время.

Используя архивный файл:

# 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 потребуется столько же времени, как и раньше.

person Brian Vandenberg    schedule 03.07.2012
comment
Более того, вы можете использовать ar T тонкие архивы, чтобы избежать чрезмерного копирования всех объектов в архивы: stackoverflow.com/questions/2157629/ Это то, что начало делать ядро ​​Linux: unix.stackexchange.com/questions/5518/ - person Ciro Santilli 新疆再教育营六四事件ۍ 28.12.2018