как отличить guish между общими и статическими c библиотеками с тем же именем - PullRequest
1 голос
/ 08 мая 2020

У меня есть библиотека, состоящая из 2 частей. Один из них - stati c «заглушка», которая напрямую связана с приложением (и содержит функцию «main» - приложение состоит из обратных вызовов оттуда). Остальные модули библиотеки содержатся в общей библиотеке. Все это было настроено в AIX, где разделяемые библиотеки связываются с помощью ссылки на файл «экспорта». Таким образом, вторая библиотека не следовала обычному соглашению об именах lib.so. Фактическое имя извлекается во время компоновки из файла экспорта. Итак, в AIX это были библиотеки libemapp.a и shlibemapp.o. В make-файле есть ссылка только на libemapp.a - через эту переменную:

LINKEMAPP = -L$(LIBDIR) -lemapp -bI:$(LIBDIR)/shlibemapp.exp

Теперь я портирую этот беспорядок на linux, и мне нужно использовать обычное соглашение об именах lib.so (я предполагаю) для общей части. Моим первым побуждением было использовать одно и то же имя для заглушки stati c и общей основной библиотеки. И я вижу, что в / usr / lib / ... есть случаи, когда одно и то же имя используется для двух библиотек. Я предполагаю, что это действительно stati c и общие версии одного и того же кода, а не две разные библиотеки.

-rw-r--r-- 1 root root 103370 May 23  2018 libtic.a
lrwxrwxrwx 1 root root     11 May 23  2018 libtic.so -> libtic.so.5
lrwxrwxrwx 1 root root     13 May 23  2018 libtic.so.5 -> libtic.so.5.9
-rw-r--r-- 1 root root  63488 May 23  2018 libtic.so.5.9

Я могу легко использовать разные имена, но мне просто интересно. Как указать при компоновке, какая из двух библиотек -lti c подключается? И можете ли вы переопределить любой вариант по умолчанию?

И, если это возможно, могу ли я иметь stati c libemapp.a и общий libemapp.so и связать их оба с приложением. Наверное, нет, а?

1 Ответ

0 голосов
/ 08 мая 2020

Как указать во время компоновки, какая из двух библиотек -lti c подключается?

(когда libtic.a и libtic.so находятся в одном поиске компоновщика

По умолчанию компоновщик GNU binutils ld подчиняется опции -ltic путем поиска сначала в каталогах, указанных -Ldir в порядке их командной строки, а затем в каталогах поиска по умолчанию в их настроенном порядке для любого из файлов libtic.so (общая библиотека) или libtic.a (статическая c библиотека). Выбирается первый, который он находит, и вводится в привязку, если оба они не найдены в одном каталоге поиска, и в этом случае выбирается libtic.so.

И можете ли вы переопределить то, что выбор по умолчанию будет?

Да. Есть три возможных способа: -

1

Если компоновщик вызывается обычным способом, через один из интерфейсов G CC (gcc, g++, gfortran, et c.), То вы можете передать опцию -static веб-интерфейсу. Это заставит его вставить параметр -static (он же -Bstatic) в командную строку, которую он генерирует для ld перед любым из входных файлов. Компоновщик будет подчиняться -(static|Bstatic), игнорируя разделяемые библиотеки, впоследствии обнаруженные при поиске библиотек, до тех пор, пока он не потребует компенсирующую опцию -Bdynamic. Итак:

gcc ... -static -ltic ...

заставит libtic.a быть предпочтительным вместо libtic.so, а также для каждой опции -lname в привязке (включая значения по умолчанию, автоматически добавленные внешним интерфейсом, а не только те, которые вы указали )

2

Любые параметры opt0[,...,optN] для ld могут быть переданы в соединение через интерфейс G CC с опцией -Wl, который имеет использование;

-Wl,opt0[,...,optN]

Итак:

gcc ... Wl,-Bstatic -ltic ...

эквивалентно иллюстрации в 1 (при условии, что конечная ... часть команды не содержит Wl,-Bdynamic).

3

Опция ld -l:name является вариантом -lname, который также принимается G CC frontend и передается в линк без изменений. -l:name указывает компоновщику искать в каждом каталоге файл с точным именем name. Таким образом,

gcc ... -l:libtic.a ...

вызовет ввод libtic.a вместо libtic.so, даже если последний существует в том же каталоге и имеет право на связывание. Однако

gcc ... -static -l:libtic.so

вызовет ошибку связи:

attempted static link of dynamic object `./libtic.so'

, даже если libtic.so будет найдено, потому что -Bstatic действует, когда учитывается -l:libtic.so.

Помимо этих трех вариантов параметра -l, конечно, вы можете просто указать произвольный [path/]name в качестве аргумента связи, и компоновщик попытается преобразовать [path/]name в абсолютное имя файла и ввести этот файл, при условии, что он не разрешается в общую библиотеку, пока действует -Bstatic.

Могу ли я иметь stati c libemapp.a и общий libemapp.so, и связать их оба с приложение

Да. Компоновщик рассматривает каждый параметр -l после sh каждый раз, когда он встречается.

gcc ... -ltic ... -ltic ......

является просто экземпляром:

gcc ... -lx ... -ly ......

и может привести к другой связи из :

gcc ... -ltic ......

, даже если -ltic разрешается каждый раз в один и тот же файл, потому что набор неопределенных ссылок, которые компоновщик пытается разрешить в определения, предоставленные библиотекой, вполне может быть другим набором неопределенных ссылок, когда одна и та же библиотека рассматривается в разных точках связи.

Но -ltic не обязательно каждый раз обращаться к одному и тому же файлу. Итак, при условии, что и libtic.a, и libtic.so существуют там, где компоновщик найдет их, независимо от того, находятся ли они в одном каталоге поиска или нет:

gcc -o prog .... -Wl,-Bstatic -ltic ... -Wl,-Bdynamic -ltic

приведет к тому, что libtic.a будет введено в ссылку первым , а затем libtic.so.

Эффект такой связи будет следующим:

  • Символы, на которые есть неразрешенные ссылки в программе, когда -ltic является первым visible будет статически привязан, где это возможно, к определениям предоставляется объектными файлами, заархивированными в libtic.a 1 .

  • После этого останется 0 или более символов, которые имеют неразрешенные ссылки в программе, когда -ltic видно для второго них. Эти неразрешенные символы будут динамически привязаны, где это возможно, к определениям, предоставленным libtic.so 2 . Компоновщик не будет проверять или исправлять какие-либо привязки stati c или Dynami c, которые он уже сделал.

Очевидно, что полезно для ссылки libtic.a и затем libtic.so, или наоборот, если бы они были не соответственно stati c и Dynami c версиями одной и той же библиотеки и, в частности, набор глобальных символов, определенных libtic.a, был отличается от набора динамических c символов, определенных как libtic.so. Но также очевидно, что было бы неправильно называть их обе libtic.?, если у них даже нет одного и того же API.

Возможно, было бы полезно связать как stati c, так и динамические c версии та же самая библиотека tic, например, в виде ссылки:

gcc -o prog main.o ... -Wl,-Bstatic -ltic ... -Wl,-Bdynamic -lfoo -ltic

Предположим, что в подобном случае x является символом, определенным libtic, на который сделана неразрешенная ссылка в main.o, а внутри libtic.a определено в элементе libtic.a(x.o). Затем libtic.a(x.o) будет объединен с prog, и ссылки на x будут статически привязаны к этому определению. И предположим, что это определение вводит новые ссылки на символы, определенные в разделяемой библиотеке libfoo.so, и что некоторые из этих определений, в свою очередь, вводят новые ссылки, которые определены в libtic.

Тогда связывание приведет к тому, что все ссылки на libtic, которые возникли до -Wl,-Bstatic, будут статически разрешены из объектных файлов libtic.a(x.o), libtic.a(y.o)..., а все последующие, которые появляются после -Wl,-Bdynamic, будут динамически разрешены в libtic.so. Связь будет такой же, как:

gcc -o prog main.o ... x.o y.o... -lfoo -ltic

Не исключено, что когда-нибудь вы встретитесь со сценарием связи, который предлагает связать таким образом как libtic.a, так и libtic.so. Но я сомневаюсь в этом, и даже если вы это сделаете, вам следует отдать предпочтение любой разумной альтернативе, которая менее противоречит обычной практике.


[1] Объектные файлы, которые предоставляют эти определения, а не другие, будут быть извлеченным из libtic.a и физически объединенным с программой, как если бы только эти объектные файлы были индивидуально названы в команде связывания вместо -ltic

[2] Программа будет аннотирована этими динамическими c привязок, позволяя загрузчику среды выполнения загружать libtic.so в процесс программы и исправлять ссылки Dynami c с помощью адресов выполнения их определений.

...