как всегда включать символы из статической библиотеки? - PullRequest
4 голосов
/ 19 ноября 2009

Предположим, у меня есть статическая библиотека libx.a. Как сделать, чтобы некоторые символы (не все) из этой библиотеки были всегда присутствующими в любом двоичном файле, который я связал со своей библиотекой? Причина в том, что мне нужно, чтобы эти символы были доступны через dlopen + dlsym. Мне известно о переключателе компоновщика --whole-archive, но он принудительно связывает все объектные файлы из архива библиотеки в результирующий двоичный файл, и это не то, что мне нужно ...

Наблюдения до сих пор (CentOS 5.4, 32bit) ( upd : этот абзац неправильный; я не могу воспроизвести это поведение)

ld main.o libx.a

удачно удалит все не ссылающиеся символы, а

ld main.o -L. -lx

свяжет всю библиотеку. Я думаю, это зависит от используемой версии binutils, и более новые компоновщики смогут выбирать отдельные объекты из статической библиотеки.

Другой вопрос: как мне добиться того же эффекта под Windows?

Заранее спасибо. Любые советы будут с благодарностью.

Ответы [ 4 ]

3 голосов
/ 10 апреля 2012

Представьте, что у вас есть проект, который состоит из следующих трех файлов C в одной папке:

// ---- jam.h
 int jam_badger(int);

// ---- jam.c
 #include "jam.h"
 int jam_badger(int a)
 {
   return a + 1;
 }

 // ---- main.c
 #include "jam.h"
 int main()
 {
   return jam_badger(2);
 }

И вы создаете его с помощью файла bjam boost-build, как этот;

lib jam : jam.c <link>static ;

lib jam_badger : jam ;

exe demo : jam_badger main.c ;

Вы получите такую ​​ошибку.

undefined reference to `jam_badger'

(я использовал bjam здесь, потому что файл легче читать, но вы можете использовать все, что захотите)

Удаление «статического» приводит к созданию работающего двоичного файла, равно как и добавление статического в другую библиотеку, или просто использование одной библиотеки (а не глупое завершение внутри другой)

Причина, по которой это происходит, в том, что ld достаточно умен, чтобы выбирать только те части архива, которые фактически используются, что в данном случае не является ни одной из них.

Решение состоит в том, чтобы окружить статические архивы с помощью -Wl, - whole-archive и -Wl, - no-whole-archive, вот так;

g++ -o "libjam_candle_badger.so" -Wl,--whole-archive libjam_badger.a Wl,--no-whole-archive

Не совсем уверен, как получить boost-build, чтобы сделать это для вас, но вы поняли идею.

2 голосов
/ 19 ноября 2009

Перво-наперво: ld main.o libx.a не создает допустимый исполняемый файл. В общем, вы должны никогда использовать ld, чтобы связать что-либо напрямую; всегда вместо этого используйте правильный драйвер компилятора (gcc).

Кроме того, "ld main.o libx.a" и "ld main.o -L. -lx" должны быть точно эквивалентны. Я очень сомневаюсь, что вы на самом деле получили разные результаты от этих двух команд.

Теперь, чтобы ответить на ваш вопрос: если вы хотите, чтобы foo, bar и baz были экспортированы из вашего a.out, сделайте это:

gcc -Wl,-u,foo,-u,bar,-u,baz main.o -L. -lx -rdynamic

Обновление:
Ваше утверждение: «символы, которые я хочу включить, используются библиотекой только для внутреннего использования», не имеет особого смысла: если символы являются внутренними для библиотеки, почему вы хотите экспортировать их? И если что-то еще использует их (через dlsym), то они не являются внутренними по отношению к библиотеке - они являются частью публичного API библиотеки.

Вы должны уточнить свой вопрос и объяснить, чего вы на самом деле пытаетесь достичь. Предоставление примера кода также не повредит.

1 голос
/ 19 ноября 2009

Возьмите адрес символа, который вам нужно включить.

Если оптимизатор gcc все равно его устраняет, сделайте что-нибудь с этим адресом - должно быть достаточно.

1 голос
/ 19 ноября 2009

Я бы начал с разделения тех символов, которые вам всегда нужны, на отдельную библиотеку, оставив только дополнительные символы в libx.a.

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