Статичне посилання функції спільної бібліотеки в 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.