2008-09-27 22 views
7

Tengo un problema con mi compilador diciéndome que hay una 'referencia indefinida' a una función que quiero usar en una biblioteca. Permítanme compartir algo de información sobre el problema:linker woes - referencia indefinida

  • estoy compilación cruzada con gcc para C.
  • Estoy llamando a una función de biblioteca que se accede a través de una cabecera incluida que incluye otra cabecera, que contiene el prototipo .
  • He incluido el directorio de encabezados usando -I y estoy seguro de que se está encontrando.
  • Primero estoy creando los archivos .o luego vinculándolos en un comando separado.

Así que mi idea es que podría ser el orden en el que incluyo los archivos de la biblioteca, pero no estoy seguro de cuál es la forma correcta de pedirlos. Intenté incluir la carpeta de encabezados antes y después del archivo .o.

Algunos sugieren que sería genial, y tal vez, y una explicación de cómo el enlazador hace su trabajo.

Gracias!


respuesta a las respuestas

  • no hay ningún archivo de biblioteca .a, simplemente .hy .c en la biblioteca, por lo que no es apropiado -l
  • mi comprensión de un archivo de biblioteca es que es solo una colección de archivos de cabecera y fuente, pero tal vez es una colección de archivos .o creados a partir de la fuente ?!
  • no se está creando ningún archivo de objeto de biblioteca, tal vez debería haberlo ?? Sí, parece que no entiendo la diferencia entre includes y libraries ... voy a trabajar en eso :-)

¡Gracias por todas las respuestas! Aprendí mucho sobre las bibliotecas. Me gustaría poner todas las respuestas como la respuesta aceptada :-)

Respuesta

5

Parece que no está compilando el archivo .c en la biblioteca para producir un archivo .o. El enlazador buscaría la implementación del prototipo en el archivo .o producido al compilar la biblioteca

¿Su compilación compila el archivo .c de la biblioteca?

¿Por qué lo llamas "biblioteca" si es solo el código fuente?

0

Supongo que tiene que agregar la ruta donde el vinculador puede encontrar el libraray. En gcc/ld puedes hacer esto con -L y libraray con -l.

-Ldir, --library-path = dir

Directorio de la búsqueda dir antes directorios de búsqueda estándar (esta opción debe preceder a la opción -l que busca ese directorio).

-larch, --library = Archivo

Incluir el arco fichero de archivo en la lista de archivos para vincular .


Respuesta a respuestas - no hay archivo de biblioteca .a, simplemente .hy .c en la biblioteca, por lo que no es -l approriate

Entonces es posible que tenga para crear el libraray primero?

gcc -c mylib.c -o mylib.o 
ar rcs libmylib.a  mylib.o 
4

Los encabezados proporcionan declaraciones de funciones y definiciones de funciones. Para permitir que el vinculador encuentre la implementación de la función (y elimine la referencia indefinida), debe pedirle al controlador del compilador (gcc) que vincule la biblioteca específica donde reside la función utilizando el distintivo -l. Por ejemplo, -lm vinculará la biblioteca matemática. La página del manual de una función generalmente especifica qué biblioteca, si hay alguna, debe especificarse para encontrar la función.

Si el vinculador no puede encontrar una biblioteca especificada, puede agregar una ruta de búsqueda de biblioteca utilizando el modificador -L (por ejemplo, -L/usr/local/lib). También puede afectar permanentemente la ruta de la biblioteca a través de la variable de entorno LIBRARY_PATH.

Aquí hay algunos detalles adicionales para ayudarlo a depurar su problema. Por convención, los nombres de los archivos de biblioteca tienen el prefijo lib y (en su forma estática) tienen una extensión .a. Por lo tanto, la versión estáticamente vinculada de la biblioteca matemática predeterminada del sistema (la que usted vincula con -lm) generalmente reside en /usr/lib/libm.a. Para ver qué símbolos define una biblioteca determinada, puede ejecutar nm --defined-only en el archivo de la biblioteca. En mi sistema, ejecutar el comando en libm.a me da resultados como los siguientes.

e_atan2.o: 
00000000 T atan2 

e_asinf.o: 
00000000 T asinf 

e_asin.o: 
00000000 T asin 

Para ver la ruta de biblioteca que su compilador utiliza y qué bibliotecas se carga por defecto que puede invocar gcc con la opción -v. De nuevo en mi sistema esto da la siguiente salida.

GNU assembler version 2.15 [FreeBSD] 2004-05-23 (i386-obrien-freebsd) 
using BFD version 2.15 [FreeBSD] 2004-05-23 
/usr/bin/ld -V -dynamic-linker /libexec/ld-elf.so.1 /usr/lib/crt1.o 
/usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /var/tmp//ccIxJczl.o -lgcc -lc 
-lgcc /usr/lib/crtend.o /usr/lib/crtn.o 
+0

Un archivo de encabezado ('.h' por defecto) _can_ contiene cualquier tipo de fuente C, pero se desaconseja colocar todo menos las definiciones de macro y _declarations_ allí. – vonbrand

1

Me temo que ha mezclado los conceptos de biblioteca y encabezado. Digamos que tiene una biblioteca libmylib.a que contiene la función myfunc() y un encabezado correspondiente mylib.h que define su prototipo. En su archivo de origen myapp.c, incluya el encabezado, ya sea directamente o incluyendo otro encabezado que lo incluya. Por ejemplo:

/* myapp.h 
** Here I will include and define my stuff 
*/ 
... 
#include "mylib.h" 
... 

el archivo de origen se ve así:

/* myapp.c 
** Here is my real code 
*/ 
... 
#include "myapp.h" 
... 
/* Here I can use the function */ 
myfunc(3,"XYZ"); 

Ahora se puede compilar para obtener myapp.o:

gcc -c -I../mylib/includes myapp.c 

Tenga en cuenta que la -I sólo le dice gcc, donde las cabeceras los archivos son, ¡no tienen nada que ver con la biblioteca en sí!

Ahora se puede enlazar la aplicación a la biblioteca real:

gcc -o myapp -L../mylib/libs myapp.o -lmylib 

Tenga en cuenta que el interruptor -L dice gcc dónde está la biblioteca, y la -l dice que vincular el código a la biblioteca.

Si no hace este último paso, puede encontrar el problema que describió.

Puede haber otros casos más complejos, pero de su pregunta, espero que esto sea suficiente para resolver su problema.

1

Publique su archivo MAKE y la función de biblioteca a la que está intentando llamar. Incluso los archivos make gcc simples suelen tener una línea como esta:

LIBFLAGS = -lc -lpthread -lrt -lstdC++ -lShared -L ../ compartida

En este caso, significa vincular la biblioteca estándar de C, entre otros

0

He encontrado este problema al crear un programa con una nueva versión de gcc. El problema se resolvió llamando a gcc con la opción -std = gnu89. Aparentemente esto se debió a declaraciones de funciones en línea. Encontré esta solución en https://gcc.gnu.org/gcc-5/porting_to.html