Link estático da função de biblioteca compartilhada no gcc


138

Como vincular estaticamente uma função de biblioteca compartilhada no gcc?


13
O que você quer dizer com vinculado estaticamente? Deseja que seu executável seja distribuído sem exigir o .so?
Emiliano

Respostas:


108

Referir-se:

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

Você precisa da versão estática da biblioteca para vinculá-la.

Uma biblioteca compartilhada é realmente um executável em um formato especial com pontos de entrada especificados (e alguns problemas de endereçamento incluídos). Ele não possui todas as informações necessárias para vincular estaticamente.

Você não pode vincular estaticamente uma biblioteca compartilhada (ou vincular dinamicamente uma biblioteca estática).

A bandeira -static forçará o vinculador a usar bibliotecas estáticas (.a) em vez de compartilhadas (.so). Como as bibliotecas estáticas nem sempre são instaladas por padrão, você pode ter que instalar a biblioteca estática por conta própria.

Outra abordagem possível é usar o statifier ou o Ermine . Ambas as ferramentas tomam como entrada um executável vinculado dinamicamente e como saída criam um executável independente com todas as bibliotecas compartilhadas incorporadas.


11
Quais informações a biblioteca estática possui, para que possa ser vinculada estaticamente, que a biblioteca dinâmica não possui?
Kbolino 17/10/19

75

Se você deseja vincular, digamos, libapplejuice estaticamente, mas não, digamos, liborangejuice , é possível vincular assim:

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

Há uma ressalva - se liborangejuiceusar libapplejuice, entãolibapplejuice será dinamicamente vinculado.

Você precisará vincular liborangejuiceestaticamente ao lado de libapplejuicepara obter libapplejuiceestática.

E não se esqueça de manter o -Wl,-Bdynamicresto, você acabará vinculando tudo que estático, inclusive libc(o que não é uma coisa boa a se fazer).


2
Não existe uma maneira de dizer ao gcc diretamente o que vincular estaticamente, e não ignorá-lo e conversar com o vinculador?
Elazar Leibovich

1
@ElazarLeibovich, você não pode obter uma combinação de estática e dinâmica dessa maneira.
Haozhun 20/05

@EugeneBujak: A ressalva não se aplica ao meu sistema. Exemplo: gcc -o main main.cc -Wl,-rpath=. -Wl,-Bdynamic -lB -Wl,-Bstatic -lA -Wl,-Bdynamic -L. libB usa libA , está vinculado e lddnão mostra uma referência a libA . O executável funciona bem. Testado com g ++ 4.7.3.
radix

Uma dependência indireta (aninhada), estática, de uma dependência direta, dinâmica, não se torna dinamicamente vinculada.
Vinny19:

Considere o seguinte: binA depende da libB.so, que depende da libC.a Como outros já declararam, .so são eles mesmos executáveis; portanto, quando um objeto compartilhado é vinculado, qualquer dependente de uma biblioteca estática é processado pelo vinculador da mesma forma como se um executável estava sendo vinculado: os únicos símbolos extraídos da lib estática .a são aqueles referenciados (e não resolvidos) pelo .so. Isso significa que, se binA referenciar um símbolo no libC.a, não mencionado em qualquer lugar no libB.so, mesmo se binA vincular ao libB.so, esse símbolo será indefinido (a menos que -Wl, - archive inteiro seja usado ao vincular libB.so).
Vinny19:

18

Se você possui o arquivo .a da sua biblioteca compartilhada (.so), basta incluí-lo com o caminho completo, como se fosse um arquivo de objeto, como este:

Isso gera main.o apenas compilando:

gcc -c main.c

Isso vincula esse arquivo de objeto à biblioteca estática correspondente e cria o executável (chamado "main"):

gcc main.o mylibrary.a -o main

Ou em um único comando:

gcc main.c mylibrary.a -o main

Também pode ser um caminho absoluto ou relativo:

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

12

Sim, eu sei que essa é uma pergunta de 8 anos, mas me disseram que era possível vincular estaticamente a uma biblioteca de objetos compartilhados e esse foi literalmente o principal sucesso quando procurei mais informações sobre ela.

Para realmente demonstrar que vincular estaticamente uma biblioteca de objetos compartilhados não é possível com o ld( gccvinculador de), em vez de apenas um monte de pessoas insistindo que isso não é possível, use o seguinte gcccomando:

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

(Claro que você vai ter que compilar objectname.oa partir de sourcename.c, e você provavelmente deve fazer a sua própria biblioteca de objeto compartilhado também. Se você fizer isso, o uso-Wl,--library-path,. para que ld pode encontrar sua biblioteca no diretório local.)

O erro real que você recebe é:

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

Espero que ajude.


10

Um pouco tarde, mas ... Encontrei um link que salvei alguns anos atrás e achei que poderia ser útil para vocês:

CDE: Crie automaticamente aplicativos portáteis do Linux

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

  • Basta baixar o programa
  • Execute a passagem binária como argumento, o nome do binário que você deseja tornar portátil, por exemplo: nmap

    ./cde_2011-08-15_64bit nmap

O programa lerá todas as bibliotecas vinculadas ao nmap e suas dependências e as salvará em uma pasta chamada cde-package / (no mesmo diretório que você).

  • Finalmente, você pode compactar a pasta e implantar o binário portátil em qualquer sistema.

Lembre-se, para iniciar o programa portátil, você precisa executar o binário localizado em cde-package / nmap.cde

Cumprimentos


2
Embora não seja exatamente a resposta da pergunta, é uma solução notável para o problema.
razong

0

No gcc, isso não é suportado. De fato, isso não é suportado em nenhum compilador / vinculador existente que eu conheça.


4
Você poderia explicar como o link estático não é suportado por nenhum compilador existente?
JWW

5
@ noloader, vinculação estática da biblioteca dinâmica?
Nothrow 14/10/12
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.