Один и тот же объектный файл в разных библиотеках stati c при компоновке - PullRequest
1 голос
/ 30 января 2020
clang++ ... foo.cpp ... -o dir1/foo.o
clang++ ... foo.cpp ... -o dir2/foo.o
//The only difference beween the above two clang++ command lines
//is the output directory
llvm-ar ... dir1/lib1.a ...  dir1/foo.o ...
llvm-ar ... dir2/lib2.a ...  dir2/foo.o ...
clang++ ... dir1/lib1.a dir2/lib2.a ... -o lib.so

Что происходит с дублированными символами из foo. cpp при генерации lib.so? Требуется ли какой-либо флаг, чтобы не генерировать ошибки дублирования символов?

1 Ответ

1 голос
/ 10 апреля 2020

При связывании нескольких библиотек 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:

  1. Компоновщик обработает и добавит obj1.o к lib.so, отметив, что указанный символ не определен.
  2. Компоновщик откроет dir1/lib1.a и проверит, содержат ли какие-либо объектные файлы, содержащиеся в архиве, указанный символ. Поскольку foo.o определяет символ, foo.o будет добавлен к lib.so, и символ будет помечен как определенный.
  3. Компоновщик откроется dir2/lib2.a. Но в настоящее время нет неопределенных символов, поэтому дублированный объектный файл будет игнорироваться.
  4. Компоновщик обработает и добавит 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 библиотеки) к выходу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...