Как собрать проект с циклическими зависимостями библиотек
Автор: Помеха
Часто встречаются проекты, код которых разбит на статические библиотеки. В особых случаях, код этих библиотек ссылается на символы друг друга, что приводит к цикличесим зависимостям (circular dependencies).
Я хочу рассказать об одном неочевидном моменте, касающемся таких зависимостей - линкер Visual Studio нормально справляется с задачей сборки такого кода. Но если вы используете gcc - все становится немного интереснее.
Суть проблемы в том, что линкер VS ищет символы по всем подключенным библиотекам каждый раз, когда они требуются. Линкер из gcc делает это лишь один раз, причем грузит только те символы, которые ему нужны на данный момент и более к этой библиотеке не возвращается.
Я столкнулся с таким поведением при портировании одного проекта: когда поправил очевидные ms-specific нюансы - код прекрасно скомпилировался, но на линковке насыпал мне множество unresolved external symbols. Не беда, подумал я, и поменял порядок библиотек для линковки. И получил множество других unresolved external symbols.
Первое же решение, которое мне подсказал гугл - включать "проблемные" библиотеки несколько раз по очереди - до тех пор, пока ошибки не пропадут. Проверил, работает - в моем случае понадобилось подключить каждую из конфликтующих библиотек всего дважды. Очевидно, что такое решение выглядит слегка неудачным.
Гораздо более удачным выглядит использование флагов линкера.
-Wl,--start-group // перед списком библиотек -Wl,--end-group // после списка библиотек
В моем случае (я использовал Code::Blocks) командная строка стала выглядеть таким образом: