Как работать с рекурсивными зависимостями между статическими библиотеками с помощью компоновщика binutils?
Я переношу существующую систему из Windows в Linux. Конструкция построена с несколькими статическими библиотеками. Я столкнулся с ошибкой связывания, когда символ (определенный в libA) не найден в объекте из libB. Линия компоновщика выглядела как
g++ test_obj.o -lA -lB -o test
Проблема, конечно, в том, что к тому моменту, когда компоновщик находит, что ему нужен символ из libA, он уже передал его и не выполняет повторное сканирование, поэтому он просто выдает ошибки, даже несмотря на то, что символ существует для принятия.
Моя первоначальная идея состояла в том, чтобы просто поменять ссылку (на -lB -lA), чтобы впоследствии была проверена libA, и все символы, отсутствующие в libB, которые находятся в libA, были подобраны. Но потом я нахожу, что на самом деле существует рекурсивная зависимость между libA и libB! Я предполагаю, что компоновщик Visual С++ обрабатывает это каким-то образом (он выполняет повторное сканирование по умолчанию?).
Способы решения этой проблемы, которую я рассмотрел:
-
Использование общих объектов. К сожалению, это нежелательно с точки зрения требования к PIC-усложнению (это код с высокой чувствительностью к производительности и потерять% ebx, чтобы удерживать GOT, действительно больно), а общие объекты не нужны.
-
Создайте одну мегавалюту всех объектов, избегая проблемы.
-
Реструктурируйте код, чтобы избежать рекурсивной зависимости (что, очевидно, делает Right Thing, но я пытаюсь сделать этот порт с минимальными изменениями).
Есть ли у вас другие идеи, чтобы справиться с этим? Можно ли каким-то образом убедить компоновщик binutils выполнить rescans библиотек, на которые он уже посмотрел, когда ему не хватает символа?
Ответы
Ответ 1
Просто сделайте следующее:
g++ test_obj.o -lA -lB -lA -o test
Когда компоновщик читает первый libA в командной строке, он отбрасывает в нем объект/символы, от которых никто не зависел, например. все символы libB нужны, но не test_obj.o. Таким образом, вы просто заставляете его снова читать libA, и он также подберет эти символы.
Ответ 2
В то время как @nos предоставляет простое решение, оно не масштабируется, если задействовано несколько библиотек, а взаимные зависимости более сложны. Чтобы решить проблемы, ld
предоставляет --start-group archives --end-group
.
В вашем конкретном случае:
g++ test_obj.o --start-group -lA -lB --end-group -o test