Как указать во время компоновки, какая из двух библиотек -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 с помощью адресов выполнения их определений.