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