Enlace estático de la función de biblioteca compartida en gcc

138

¿Cómo puedo vincular una función de biblioteca compartida estáticamente en gcc?

suresh
fuente
14
¿Qué quieres decir con estáticamente vinculado? ¿Desea que su ejecutable se distribuya sin requerir el .so?
Emiliano el

Respuestas:

108

Referirse a:

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

Necesita la versión estática de la biblioteca para vincularla.

Una biblioteca compartida es en realidad un ejecutable en un formato especial con puntos de entrada especificados (y se incluyen algunos problemas de direccionamiento fijo). No tiene toda la información necesaria para vincular estáticamente.

No puede vincular estáticamente una biblioteca compartida (o vincular dinámicamente una estática).

El indicador -staticobligará al vinculador a usar bibliotecas estáticas (.a) en lugar de compartidas (.so). Pero las bibliotecas estáticas no siempre se instalan de manera predeterminada, por lo que es posible que deba instalar la biblioteca estática usted mismo.

Otro enfoque posible es usar statifier o Ermine . Ambas herramientas toman como entrada un ejecutable vinculado dinámicamente y como salida crean un ejecutable autónomo con todas las bibliotecas compartidas incrustadas.

Sam Liao
fuente
11
¿Qué información tiene la biblioteca estática, para que pueda vincularse estáticamente, que la biblioteca dinámica no tiene?
kbolino
75

Si desea vincular, por ejemplo, libapplejuice estáticamente, pero no, por ejemplo, liborangejuice , puede vincular así:

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

Hay una advertencia: si se liborangejuiceusa libapplejuice, entonceslibapplejuice también se vinculará dinámicamente.

Tendrás que vincular liborangejuiceestáticamente junto con libapplejuicepara obtener libapplejuiceestática.

Y no olvides guardar -Wl,-Bdynamicotra cosa, terminarás vinculando todo estático, incluido libc(lo cual no es algo bueno).

Eugene Bujak
fuente
2
¿No hay una manera de decirle a gcc directamente qué vincular estáticamente, y no evitarlo y hablar con el vinculador?
Elazar Leibovich
1
@ElazarLeibovich no puedes obtener una combinación de estática y dinámica de esa manera.
Haozhun
@EugeneBujak: La advertencia no se aplica en mi sistema. Ejemplo: gcc -o main main.cc -Wl,-rpath=. -Wl,-Bdynamic -lB -Wl,-Bstatic -lA -Wl,-Bdynamic -L. libB usa libA , está vinculado y lddno muestra una referencia a libA . El ejecutable funciona bien. Probado con g ++ 4.7.3.
radix
Una dependencia indirecta (anidada), estática, de una dependencia directa y dinámica no se vincula dinámicamente.
Vinny
Considere lo siguiente: binA depende de libB.so, que depende de libC.a Como ya han dicho otros, los .so son ejecutables, por lo que cuando un objeto compartido está vinculado, el enlazador procesa cualquier dependiente de biblioteca estática de la misma manera que si se estaba vinculando un ejecutable: los únicos símbolos extraídos de la biblioteca estática .a son los referenciados (y no resueltos) por .so. Esto significa que si binA hace referencia a un símbolo en libC.a, no referenciado en ningún lugar de libB.so, incluso si binA se vincula a libB.so, ese símbolo estará indefinido (a menos que -Wl, - se use el archivo completo al vincular libB.so).
Vinny
18

Si tiene el archivo .a de su biblioteca compartida (.so), simplemente puede incluirlo con su ruta completa como si fuera un archivo objeto, como este:

Esto genera main.o simplemente compilando:

gcc -c main.c

Esto vincula ese archivo de objeto con la biblioteca estática correspondiente y crea el ejecutable (llamado "main"):

gcc main.o mylibrary.a -o main

O en un solo comando:

gcc main.c mylibrary.a -o main

También podría ser una ruta absoluta o relativa:

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

Sí, sé que esta es una pregunta de hace 8 años, pero me dijeron que era posible vincular estáticamente contra una biblioteca de objetos compartidos y este fue literalmente el éxito principal cuando busqué más información al respecto.

Para demostrar realmente que no es posible vincular estáticamente una biblioteca de objetos compartidos con ld( gcc'linker'), a diferencia de un grupo de personas que insisten en que no es posible, use el siguiente gcccomando:

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

(Por supuesto, tendrá que compilar objectname.odesde sourcename.c, y probablemente también debería crear su propia biblioteca de objetos compartidos. Si lo hace, use -Wl,--library-path,.para que ld pueda encontrar su biblioteca en el directorio local).

El error real que recibe es:

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

Espero que ayude.

Ian Moote
fuente
10

Un poco tarde pero ... Encontré un enlace que guardé hace un par de años y pensé que podría ser útil para ustedes:

CDE: cree automáticamente aplicaciones portátiles de Linux

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

  • Solo descarga el programa
  • Ejecute el paso binario como argumento del nombre del binario que desea convertir en portátil, por ejemplo: nmap

    ./cde_2011-08-15_64bit nmap

El programa leerá todas las librerías vinculadas a nmap y sus dependencias y las guardará en una carpeta llamada cde-package / (en el mismo directorio que usted).

  • Finalmente, puede comprimir la carpeta e implementar el binario portátil en cualquier sistema.

Recuerde, para iniciar el programa portátil debe ejecutar el binario ubicado en cde-package / nmap.cde

Atentamente

Francis
fuente
2
Si bien no proporciona exactamente la respuesta a la pregunta, es una solución notable al problema.
razong
El enlace parece estar muerto ahora.
sinan hace
0

En gcc, esto no es compatible. De hecho, esto no es compatible con ningún compilador / enlazador existente que conozca.

nada
fuente
44
¿Podría explicar cómo un compilador existente no admite la vinculación estática?
jww
55
@noloader, enlace estático de biblioteca dinámica?
nothrow