LINUX.ORG.RU

Как слинковать программу статически только с частью библиотек


0

0

Задача стоит такая: программу надо слинковать сатически с некоторыми библиотеками (конкретно - с теми которые c++, т. к. требуется максимальная переносимость программы в бинарном виде, а у c++ abi постоянно меняется). С остальными (glibc и прочие) надо слинковать динамически. Вопрос: это как-то по-человечески сделать можно? Я нашёл только один способ - прописывание руками путей до всех статических библиотек, с которыми нужно линковать статически. А более "прямого" способа нет?

★★


AFAIK примерно так:

gcc ... -Wl,-Bstatic -lfoo -lbar -Wl,-Bdynamic

В данном случае будут искаться statiс библиотеки foo и bar,
все остальные библиотеки (включая стандартные) будут shared.
В командной строке можно переключать это дело при помощи
-Wl,-B<link_type> произвольное число раз, каждый переключатель
действует на библиотеки следующие за ним и до следующего
переключателя. Стандартные же библиотеки (не указываемые в
командной строке явно) будут линковаться так, как указывает самый
последний переключатель в командной строке (поэтому в примере выше
мы переключаемся на dynamic в конце).

Вроде так... может наврал чего... подробности в USENET или groups.google.com ;-)

BTW твое предложение указывать полный путь к статическим библиотекам
IMHO имеет то преимущество, что более системно-независимо (и в общем-
то не так уж и плохо).

HTH

Onanim
()
Ответ на: комментарий от Onanim

2Onanim:

Это про Це. А с ЦеПП несколько сложнее и зависит от версии компилятора.

Надо вручную засунуть stdc++ (и, может, еще кое-что) и использовать в качестве фронтенда к линкеру не g++ а gcc. Например, кусочек их мейкфайла:

#Qt and stdc++ are static:

LIBS = -Xlinker -Bstatic -lqt -lstdc++ -Xlinker -Bdynamic -lX11 -lXext -lm

#ATTENTION! Here gcc as a front-end to ldd must be used instead of g++!

(-Xlinker -- то же, что и -Wl,)

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Это про Це. А с ЦеПП несколько сложнее и зависит от версии компилятора.

Да оно и для C в общем-то зависит от компилятора/линкера
(если мы говорим не только о Linux).
Поэтому мой выбор - явное указание статической библиотеки как .a файла :-)))
(не знаю правда, работает ли это с libstdc++ - как-то не требовалось)

Onanim
()
Ответ на: комментарий от Onanim

> Поэтому мой выбор - явное указание статической библиотеки как .a файла :-)))

Кстати, можно подробнее? Типа, -l/path/to/lib/libHAHA.a ? Или просто /path/to/lib/libHAHA.a в аргументах cc? У меня такое не получалось...

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Кстати, можно подробнее? Типа, -l/path/to/lib/libHAHA.a ? Или просто /path/to/lib/libHAHA.a в аргументах cc? У меня такое не получалось...

Конечно без -l:

cc ... /path/to/library.a ...

В конце концов .a - это всего лишь совокупность .o, с чего бы линкеру
их не прилинковать?
Я не уверен насколько это применимо впрямую к стандартным библиотекам
C и C++, возможно надо что-то еще сказать. Но для обычных библиотек
должно работать.

BTW интересная ссылка - http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html

HTH

Onanim
()
Ответ на: комментарий от Onanim

> Я не уверен насколько это применимо впрямую к стандартным библиотекам C и C++, возможно надо что-то еще сказать. Но для обычных библиотек должно работать.

Применимо, применимо. Я таким образом libstdc++ прилинковывал. Просто указывается путь к .a файлу, безо всяких ключей.

За -Wl спасибо, посмотрю...

slav ★★
() автор топика
Ответ на: комментарий от Onanim

Onanim:

> cc ... /path/to/library.a ...

Не знаю, как сейчас, но раньше такая штука у меня не канала.

И еще -- вообще говоря, оно ж таким образом всю библиотеку прилинкует! Не только то, что вызывается, но и вообще всю целиком!

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Не знаю, как сейчас, но раньше такая штука у меня не канала.

Не буду спорить - хотя сам такого не встречал :-/
(даже на достаточно старой Solaris 2.6 это работает)

> И еще -- вообще говоря, оно ж таким образом всю библиотеку прилинкует! Не только то, что вызывается, но и вообще всю целиком!

Интересный вопрос. Хотя не вижу проблем для линкера поступать
и в этом случае так же, как при указании библиотеки через -l.
Линкер-то в любом случае знает, что это static library (иначе
он бы ее не прочитал). Нуждается в экспериментальной проверке ;-)

Onanim
()
Ответ на: комментарий от Onanim

Вдогонку:

Повтыкал в "Linker and Libraries Guide" от Solaris 2.6.
Насколько я понял вне зависимости от метода указания archive-файла
всегда происходит selective extraction (если явно не указано иное).
СОбственно параграф Archive Processing это и описывает.

Увы документация к GNU ld на эту тему хранит молчание... она вообще немногословна ;-)

Onanim
()
Ответ на: комментарий от Onanim

Как я понял, ГНУтый линкер все в кучу валит, до чего дотянется.

Надо попробовать, однако...

Кстати, похожая проблема так решалась:

http://www.linux.org.ru/jump-message.jsp?msgid=248738

(немного не то, но все равно интересно).

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> И еще -- вообще говоря, оно ж таким образом всю библиотеку прилинкует! Не только то, что вызывается, но и вообще всю целиком!

Нет. Проверил - суммарный размер библиотек, с которыми линкуется - 4.2М, бинарник получается 2.2М до strip -s и 1.7М после strip -s. Хотя возможно что из статического архива прилинковываются целиком .o файлы, но только нужные...

slav ★★
() автор топика
Ответ на: комментарий от slav

2slav:

Посмотри с помощью nm на получившийся бинарник -- все фукции тама. Независимо от способа линковки, кстати.

Надо это как-то прояснить бы...

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Посмотри с помощью nm на получившийся бинарник -- все фукции тама. 
> Независимо от способа линковки, кстати. 
> Надо это как-то прояснить бы...

Что за система у тебя такая?
Я тут проверил на Solaris и Linux - все нормально, никаких
лишних символов при обоих способах линковки нет:

/* f1.c */
void function_1() {}

/* f2.c */
void function_2() {}

/* main.c */
int main() { function_1(); return 0; }

Пробуем на Solaris:

$ cc -c f?.c && ar -rs libf.a f?.o                               
f1.c:
f2.c:
$ cc main.c -o main1 -L. -lf
$ cc main.c -o main2 ./libf.a 
$ nm main1 | grep function_ 
[50]    |     67216|      20|FUNC |GLOB |0    |8      |function_1
$ nm main2 | grep function_ 
[50]    |     67216|      20|FUNC |GLOB |0    |8      |function_1
$
$ cc -V       
cc: Sun WorkShop 6 update 2 C 5.3 Patch 111679-07 2002/04/23
$ uname -rs
SunOS 5.8

Пробуем на Lunux:

$ cc -c f?.c && ar -rs libf.a f?.o
ar: creating libf.a
$ cc main.c -o main1 -L. -lf
$ cc main.c -o main2 ./libf.a 
$ nm main1 | grep function_
080483a8 T function_1
$ nm main2 | grep function_
080483a8 T function_1
$
$ uname -rs
Linux 2.6.16.13-4-default
$ cc --version
cc (GCC) 4.1.0 (SUSE Linux)
$

Onanim
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.