БОЛЬШОЙ ОТКАЗ ОТ ЖИРА Делайте это только в случае крайней необходимости. Предпочтительным способом является рефакторинг структуры вашего проекта таким образом, чтобы она не содержала циклы зависимостей.
При создании разделяемой библиотеки компоновщику вообще не нужно знать о других разделяемых библиотеках. Можно использовать их в командной строке, но это необязательно. Пример:
// libA.cpp
extern void funcB();
void funcA() {
funcB();
}
Компиляция и ссылка:
g++ -fPIC -c libA.cpp
g++ -shared -o libA.so libA.o
funcB
должен жить в libB.so
, но мы не сообщаем компоновщику, где его найти. Символ просто остается неопределенным в libA.so
и будет (надеюсь) разрешен в время загрузки .
// libB.cpp
extern void funcA();
void funcB() {
funcA();
}
Компиляция и компоновка, теперь явно использующие libA.so (игнорируйте бесконечную рекурсию, это всего лишь пример):
g++ -fPIC -c libB.cpp
g++ -shared -o libB.so libB.o -L/where/libA/is -lA
Теперь исполняемый файл должен загружать libB.so
перед загрузкой libA.so
, иначе libA.so
не может быть загружен. Это легко сделать (просто связать исполняемый файл только с libB.so
, а не libA.so
), но иногда это может быть неудобно. Таким образом, можно повторно связать libA.so
после building libB.so
:
g++ -shared -o libA.so libA.o -L /where/libB/is -lB
Теперь можно связать исполняемый файл с libA или libB, а другой будет выбран автоматически.