Как бороться с рекурсивными зависимостями между статическими библиотеками с помощью компоновщика binutils? - PullRequest
15 голосов
/ 29 апреля 2010

Я портирую существующую систему с 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 ]

19 голосов
/ 29 апреля 2010

Просто сделайте это:

g++ test_obj.o -lA -lB -lA       -o test

Когда компоновщик читает первый libA в командной строке, он отбрасывает объект / символы в нем, от которых еще никто не зависел, например, все символы, которые нужны libB, но не test_obj.o. Так что вы просто заставляете его читать libA снова, и он также подхватит эти символы.

10 голосов
/ 14 февраля 2013

Хотя @nos предоставляет простое решение, оно не масштабируется, когда задействовано несколько библиотек и взаимные зависимости более сложны. Чтобы разобраться в проблемах ld предоставляет --start-group archives --end-group.

В вашем конкретном случае:

g++ test_obj.o --start-group -lA -lB --end-group -o test
...