Статичне посилання функції спільної бібліотеки в gcc


138

Як я можу статично пов'язати функцію спільної бібліотеки в gcc?


14
Що ви маєте на увазі під статично пов'язаними? Ви хочете, щоб ваш виконуваний файл розповсюджувався, не вимагаючи .so?
Еміліано

Відповіді:


108

Відноситься до:

http://www.linuxquestions.org/questions/linux-newbie-8/forcing-static-linking-of-shared-libraries-696714/

http://linux.derkeiler.com/Newsgroups/comp.os.linux.development.apps/2004-05/0436.html

Вам потрібна статична версія бібліотеки, щоб зв’язати її.

Спільна бібліотека - це справді виконуваний файл у спеціальному форматі із зазначенням точок входу (а також деякі липкі проблеми вирішення). У ньому немає всієї інформації, необхідної для статичного зв’язку.

Ви не можете статично зв’язати спільну бібліотеку (або динамічно зв'язати статичну).

Прапор -staticзмусить лінкер використовувати статичні бібліотеки (.a) замість спільних (.so). Але статичні бібліотеки не завжди встановлюються за замовчуванням, тому вам, можливо, доведеться встановлювати статичну бібліотеку самостійно.

Інший можливий підхід - використовувати статифікатор або Ermine . Обидва інструменти приймають як вхід динамічно пов'язаний виконуваний файл і як вихід створюють автономний виконуваний файл з усіма вбудованими бібліотеками.


11
Яку інформацію має статична бібліотека, щоб вона могла бути статично пов'язана, що динамічна бібліотека не має?
kbolino

75

Якщо ви хочете пов’язати, скажімо, libapplejuice статично, але не, скажімо, liborangejuice , ви можете зв’язати так:

gcc object1.o object2.o -Wl,-Bstatic -lapplejuice -Wl,-Bdynamic -lorangejuice -o binary

Є застереження - якщо liborangejuiceвикористовується libapplejuice, то libapplejuiceбуде також динамічно пов’язано.

Вам потрібно буде liborangejuiceстатично зв’язатись, а libapplejuiceтакож стати libapplejuiceстатичним.

І не забудьте зберегти -Wl,-Bdynamicінше, ви в кінцевому підсумку зв’яжете все статичне, в тому числі libc(що не дуже добре робити).


2
Чи не існує способу сказати gcc безпосередньо, що статично пов’язати, а не обійти його і поговорити з лінкером?
Елазар Лейбович

1
@ElazarLeibovich ви не можете отримати поєднання статичного та динамічного таким чином.
Хаожун

@EugeneBujak: застереження не поширюється на моїй системі. Приклад: gcc -o main main.cc -Wl,-rpath=. -Wl,-Bdynamic -lB -Wl,-Bstatic -lA -Wl,-Bdynamic -L. libB використовує libA , він пов'язаний і lddне показує посилання на libA . Виконаний файл працює чудово. Перевірено з g ++ 4.7.3.
радікс

Непряма (вкладена), статична, залежність прямої, динамічної, залежності сама по собі не стає динамічно пов'язаною.
Вінні

Розглянемо наступне: binA залежить від libB.so, що залежить від libC.a Як уже говорили інші, .so - це самі виконувані файли, тому коли спільний об'єкт пов'язаний, будь-які статичні залежність бібліотеки обробляються лінкером приблизно так само, як якщо б виконується зв'язування виконуваного файлу: єдині символи, витягнуті зі статичної лібрики, - це ті, на які посилається (і не вирішено) .so. Це означає, що якщо binA посилається на символ у libC.a, не посилається ніде в libB.so, то навіть якщо binA посилається на libB.so, цей символ не буде визначений (якщо тільки -Wl, - при посиланні використовується цілий архів libB.so).
Вінні

18

Якщо у вас є .a файл вашої спільної бібліотеки (.so), ви можете просто включити його з його повним шляхом, як якщо б це був об’єктний файл, наприклад:

Це створює main.o, просто компілюючи:

gcc -c main.c

Це пов'язує об'єктний файл із відповідною статичною бібліотекою та створює виконуваний файл (з назвою "main"):

gcc main.o mylibrary.a -o main

Або в одній команді:

gcc main.c mylibrary.a -o main

Це також може бути абсолютний або відносний шлях:

gcc main.c /usr/local/mylibs/mylibrary.a -o main

12

Так, я знаю, що це 8-річне запитання, але мені сказали, що можна статично зв’язатись із бібліотекою спільних об'єктів, і це було буквально найкращим ударом, коли я шукав додаткову інформацію про це.

Для того, щоб фактично продемонструвати, що статично зв’язувати бібліотеку спільних об'єктів неможливо з ld( gcc's linker) - на відміну від простої групи людей, наполягаючи, що це неможливо - використовуйте таку gccкоманду:

gcc -o executablename objectname.o -Wl,-Bstatic -l:libnamespec.so

(Звичайно, вам доведеться компілювати objectname.oз sourcename.c, і ви, мабуть, також повинні скласти свою власну бібліотеку спільних об'єктів. Якщо це зробити, використовуйте -Wl,--library-path,.так, щоб ld міг знайти вашу бібліотеку в локальному каталозі.)

Фактична помилка, яку ви отримуєте:

/usr/bin/ld: attempted static link of dynamic object `libnamespec.so'
collect2: error: ld returned 1 exit status

Сподіваюся, що це допомагає.


10

Трохи пізно, але ... Я знайшов посилання, яке я врятував пару років тому, і я подумав, що може бути корисним для вас, хлопці:

CDE: Автоматичне створення портативних програм для Linux

http://www.pgbovine.net/cde.html

  • Просто завантажте програму
  • Виконайте бінарний прохід як аргумент ім'я бінарного файлу, який ви хочете зробити портативним, наприклад: nmap

    ./cde_2011-08-15_64bit nmap

Програма прочитає всі файли, пов'язані з nmap та його залежностями, і збереже їх у папці, що називається cde-package / (у тому самому каталозі, що і ви).

  • Нарешті, ви можете стиснути папку та розгорнути портативний двійковий файл у будь-якій системі.

Пам'ятайте, що для запуску портативної програми вам потрібно виконати бінарний файл, розташований у cde-package / nmap.cde

З найкращими побажаннями


2
Хоча точно не дає відповіді на питання, - це помітне рішення проблеми.
razong

Здається, посилання зараз мертва.
Синан

0

У gcc це не підтримується. Насправді це не підтримується в жодному з існуючих мені компіляторів / лінкерів.


4
Чи можете ви пояснити, як статичне посилання не підтримується жодним існуючим компілятором?
jww

5
@noloader, статичне з'єднання динамічної бібліотеки?
nothrow
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.