Domanda

Sto riscontrando un problema con il mio compilatore che mi dice che esiste un 'riferimento indefinito a' una funzione che voglio usare in una libreria. Vorrei condividere alcune informazioni sul problema:

  • Sto compilando in modo incrociato con gcc per C.
  • Sto chiamando una funzione di libreria a cui si accede tramite un'intestazione inclusa che include un'altra intestazione, che contiene il prototipo.
  • Ho incluso la directory delle intestazioni usando -I e sono sicuro che sia stata trovata.
  • In primo luogo sto creando i file .o quindi collegandoli in un comando separato.

Quindi il mio pensiero è che potrebbe essere l'ordine in cui includo i file della libreria, ma non sono sicuro di quale sia il modo corretto di ordinarli. Ho provato ad includere la cartella delle intestazioni sia prima che dopo il file .o.

Alcuni suggeriscono che sarebbe fantastico, e forse e una spiegazione di come il linker fa la sua cosa.

Grazie!


Risposta alle risposte

  • non esiste un file di libreria .a, solo .h e .c nella libreria, quindi -l non è appropriato
  • la mia comprensione di un file di libreria è che è solo una raccolta di file header e sorgente, ma forse è una raccolta di file .o creati dalla fonte ?!
  • non è stato creato alcun file oggetto libreria, forse dovrebbe esserci ?? Sì, sembra che non capisca la differenza tra include e librerie ... Ci lavorerò su :-)

Grazie per tutte le risposte! Ho imparato molto sulle biblioteche. Vorrei mettere tutte le risposte come risposta accettata :-)

È stato utile?

Soluzione

Sembra che tu non stia compilando il file .c nella libreria per produrre un file .o. Il linker cercherebbe l'implementazione del prototipo nel file .o prodotto compilando la libreria

Il tuo processo di compilazione compila il file .c della libreria?

Perché la chiami una " libreria " se in realtà è solo codice sorgente?

Altri suggerimenti

Le intestazioni forniscono dichiarazioni e definizioni di funzioni. Per consentire al linker di trovare l'implementazione della funzione (e sbarazzarsi del riferimento indefinito) è necessario chiedere al driver del compilatore (gcc) di collegare la libreria specifica in cui risiede la funzione usando il flag -l. Ad esempio, -lm collegherà la libreria matematica. La pagina del manuale di una funzione in genere specifica quale libreria, se presente, deve essere specificata per trovare la funzione.

Se il linker non riesce a trovare una libreria specificata, puoi aggiungere un percorso di ricerca della libreria usando l'opzione -L (ad esempio -L / usr / local / lib). È inoltre possibile influire in modo permanente sul percorso della libreria tramite la variabile di ambiente LIBRARY_PATH.

Ecco alcuni dettagli aggiuntivi per aiutarti a eseguire il debug del tuo problema. Per convenzione i nomi dei file di libreria sono preceduti da lib e (nella loro forma statica) hanno un'estensione .a. Pertanto, la versione staticamente collegata della libreria matematica predefinita del sistema (quella a cui si collega -lm) risiede in genere in /usr/lib/libm.a. Per vedere quali simboli definisce una determinata libreria puoi eseguire nm --defined-only sul file della libreria. Sul mio sistema, eseguire il comando su libm.a mi dà un output simile al seguente.

e_atan2.o:
00000000 T atan2

e_asinf.o:
00000000 T asinf

e_asin.o:
00000000 T asin

Per vedere il percorso della libreria usato dal compilatore e quali librerie carica per impostazione predefinita, puoi invocare gcc con l'opzione -v. Ancora una volta sul mio sistema, questo dà il seguente output.

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

Temo che tu abbia mescolato i concetti di libreria e intestazione. Supponiamo che tu abbia una libreria libmylib.a che contiene la funzione myfunc () e un'intestazione corrispondente mylib.h che ne definisce il prototipo. Nel tuo file sorgente myapp.c includi l'intestazione, direttamente o includendo un'altra intestazione che la include. Ad esempio:

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

il tuo file sorgente è simile a:

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

Ora puoi compilarlo per ottenere myapp.o :

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

Nota che -I dice a gcc dove sono i file delle intestazioni, non hanno nulla a che fare con la libreria stessa!

Ora puoi collegare la tua applicazione con la vera libreria:

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

Nota che l'opzione -L indica a gcc dove si trova la libreria e l'opzione -l indica di collegare il tuo codice alla libreria.

Se non esegui quest'ultimo passaggio, potresti riscontrare il problema che hai descritto.

Potrebbero esserci altri casi più complessi ma dalla tua domanda, spero che questo sia sufficiente per risolvere il tuo problema.

Pubblica il tuo makefile e la funzione di libreria che stai tentando di chiamare. Anche i semplici makefile di gcc di solito hanno una linea come questa:

LIBFLAGS =-lc -lpthread -lrt -lstdc++ -lShared -L../shared

In questo caso, significa collegare la libreria C standard, tra gli altri

Suppongo che devi aggiungere il percorso in cui il linker può trovare il libraray. In gcc / ld puoi farlo con -L e libraray con -l.

  

-Ldir, --library-path = dir

     

Cerca nella directory directory prima dello standard   cerca nelle directory (questa opzione deve   precede l'opzione -l che cerca   quella directory).

     

-larch, --library = archive

     

Includi l'arco del file di archivio nel file   elenco di file da collegare.


  

Risposta alle risposte: non esiste un file di libreria .a, solo .h e .c nella libreria, quindi -l non è appropriato

Quindi potrebbe essere necessario creare prima il libraray?

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

Ho riscontrato questo problema durante la creazione di un programma con una nuova versione di gcc. Il problema è stato risolto chiamando gcc con l'opzione -std = gnu89. Apparentemente ciò era dovuto alle dichiarazioni di funzioni in linea. Ho trovato questa soluzione su https://gcc.gnu.org/gcc-5/porting_to .html

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top