При связывании нескольких библиотек stati c, если один и тот же объектный файл встречается в более чем одной из предоставленных библиотек, не приведет к ошибкам дублирования символов (по умолчанию).
Это связано с тем, что компоновщик не "объединяет библиотеки stati c" в конечный исполняемый файл. Он только объединяет предоставленные объектные файлы в исполняемый файл. Компоновщик обрабатывает список объектных файлов и архивных библиотек слева направо. При обнаружении библиотеки stati c компоновщик проверяет, определяет ли какой-либо из предоставленных библиотекой объектных файлов неопределенный в данный момент символ. Тогда и только тогда извлечет этот объектный файл.
В вашем примере:
clang++ ... dir1/lib1.a dir2/lib2.a ... -o lib.so
рассмотрим два дополнительных объектных файла:
clang++ obj1.o dir1/lib1.a dir2/lib2.a obj2.o -o lib.so
Если obj1.o
ссылается на символ, который существует в foo.cpp
:
- Компоновщик обработает и добавит
obj1.o
к lib.so
, отметив, что указанный символ не определен. - Компоновщик откроет
dir1/lib1.a
и проверит, содержат ли какие-либо объектные файлы, содержащиеся в архиве, указанный символ. Поскольку foo.o
определяет символ, foo.o
будет добавлен к lib.so
, и символ будет помечен как определенный. - Компоновщик откроется
dir2/lib2.a
. Но в настоящее время нет неопределенных символов, поэтому дублированный объектный файл будет игнорироваться. - Компоновщик обработает и добавит
obj2.o
к lib.so
. Компоновщик не go назад и повторно обрабатывает lib1.a
или lib2.a
Поэтому не должно возникать ошибка дублирующегося символа (по умолчанию при Linux ). Чтобы изменить это поведение, вы можете использовать опцию компоновщика --whole-archive
clang++ ... -Wl,--whole-archive dir1/lib1.a dir2/lib2.a -Wl,--no-whole-archive ... -o lib.so
При --whole-archive
все объектные файлы из указанных архивных библиотек будут добавлены к выходным данным. Приведенная выше команда затем приводит к ошибке «множественное определение» для любых символов в foo.cpp
.
Этот ответ описывает поведение на Linux, я считаю, что AIX отличается и всегда добавит все встреченные объектные файлы ( от stati c библиотеки) к выходу.