desgraças vinculador - referência indefinida
Pergunta
Eu estou tendo um problema com meu compilador me dizendo há uma 'referência indefinida para' uma função que eu quero usar em uma biblioteca. Deixem-me partilhar algumas informações sobre o problema:
- Eu sou compilação cruzada com gcc para C.
- Eu estou chamando uma função de biblioteca que é acessado através de um cabeçalho incluído, que inclui outro cabeçalho, que contém o protótipo.
- Eu incluí o diretório cabeçalhos usando -I e eu tenho certeza que ele está sendo encontrado.
- Estou primeiro criar os arquivos .o, em seguida, ligando-os em um comando separado.
Então, meu pensamento é que poderia ser a ordem na qual incluo os arquivos de biblioteca, mas não tenho certeza qual é a maneira correta de encomendá-los. Eu tentei com incluindo os cabeçalhos de pasta antes e depois do arquivo .o.
Alguns sugere seria ótimo, e talvez e explicação de como o vinculador faz sua coisa.
Obrigado!
Response to respostas
- não há nenhum arquivo de biblioteca .a, apenas .he .c na biblioteca, então -l não é apropriado
- minha compreensão de um arquivo de biblioteca é que ele é apenas uma coleção de arquivos de inclusão e de código, mas talvez seja uma coleção de .o arquivos criados a partir da fonte?!
- não há nenhum arquivo objeto de biblioteca que está sendo criado, talvez deve haver ?? Sim parece que eu não entendo a diferença entre inclui e bibliotecas ... eu vou trabalhar nisso: -)
Obrigado por todas as respostas! Eu aprendi muito sobre as bibliotecas. Eu gostaria de colocar todas as respostas como a resposta aceita: -)
Solução
Parece que você não está compilando o arquivo .c na biblioteca para produzir um arquivo .o. O vinculador ficaria para a implementação do protótipo no arquivo .o produzido por compilar a biblioteca
Será que o seu processo de compilação compilar o arquivo .c biblioteca?
Por que você chamá-lo de uma "biblioteca" se é realmente o código-fonte apenas?
Outras dicas
cabeçalhos apresentar declarações de função e definições de função. Para permitir que o linker encontra a implementação da função (e livrar-se da referência indefinida), você precisa pedir ao motorista compilador (gcc) para ligar a biblioteca específica onde reside a função usando o sinalizador -l. Por exemplo, -lm vai ligar a biblioteca de matemática. página do manual de uma função tipicamente especifica que biblioteca, se houver, devem ser especificados para encontrar a função.
Se o vinculador não é possível encontrar uma biblioteca especificada você pode adicionar um caminho de pesquisa da biblioteca usando o interruptor -L (por exemplo, -L / usr / / lib local). Você também pode afetar permanentemente o caminho da biblioteca através da variável de ambiente LIBRARY_.
Aqui estão alguns detalhes adicionais para ajudar a depurar o seu problema. Por convenção os nomes de arquivos de biblioteca são prefixados com lib e (em sua forma estática) têm uma extensão .a. Assim, a versão estaticamente ligado da biblioteca de matemática padrão do sistema (o que você vincular com -lm) geralmente reside no /usr/lib/libm.a. Para ver o que símbolos um determinado define biblioteca você pode executar nm --defined-somente no arquivo de biblioteca. No meu sistema, executar o comando em libm.a me dá saída como a seguinte.
e_atan2.o:
00000000 T atan2
e_asinf.o:
00000000 T asinf
e_asin.o:
00000000 T asin
Para ver o caminho da biblioteca que usa seu compilador e as bibliotecas ele carrega por padrão você pode invocar o gcc com a opção -v. Mais uma vez no meu sistema que dá o seguinte resultado.
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 que misturou os conceitos de biblioteca e cabeçalho.
Vamos dizer que você tem uma libmylib.a
biblioteca que contém o myfunc()
função e uma mylib.h
cabeçalho correspondente que define seu protótipo. Em sua myapp.c
arquivo de origem que você incluir o cabeçalho, diretamente ou incluindo outro cabeçalho que inclui. Por exemplo:
/* myapp.h
** Here I will include and define my stuff
*/
...
#include "mylib.h"
...
sua aparência arquivo de origem como:
/* myapp.c
** Here is my real code
*/
...
#include "myapp.h"
...
/* Here I can use the function */
myfunc(3,"XYZ");
Agora você pode compilá-lo para obter myapp.o
:
gcc -c -I../mylib/includes myapp.c
Note que o -I apenas diz gcc onde os arquivos de cabeçalhos são, eles não têm nada a ver com a própria biblioteca!
Agora você pode vincular sua aplicação na biblioteca real:
gcc -o myapp -L../mylib/libs myapp.o -lmylib
Note que o interruptor -L
diz gcc onde a biblioteca é, eo -l
diz-lhe para ligar seu código para a biblioteca.
Se você não fizer este último passo, você pode encontrar o problema que você descreveu.
Pode haver outros casos mais complexos, mas a partir de sua pergunta, eu espero que isso seria suficiente para resolver seu problema.
Coloque seu makefile, e a função de biblioteca que você está tentando chamar. Mesmo makefiles gcc simples costumam ter uma linha como esta:
LIBFLAGS =-lc -lpthread -lrt -lstdc++ -lShared -L../shared
Neste caso, isso significa ligar a biblioteca C padrão, entre outros
Eu acho que você tem que adicionar o caminho onde o vinculador pode encontrar o libraray. Em gcc / ld você pode fazer isso com -L e libraray com -l.
-Ldir, --library-path = dir
Procurar diretório dir antes de padrão aos diretórios de busca (Esta opção deve preceder a opção -l que pesquisas esse diretório).
-larch, --library = arquivo
Inclua o arco arquivo no lista de arquivos a ligação.
Response to respostas - não há nenhum arquivo de biblioteca .a, apenas .he .c na biblioteca, então -l não é approriate
Em seguida, você pode ter que criar o libraray primeiro?
gcc -c mylib.c -o mylib.o
ar rcs libmylib.a mylib.o
Eu encontrei este problema ao construir um programa com uma nova versão do gcc. O problema foi corrigido chamando gcc com a -std = gnu89 opção. Aparentemente, isso foi devido a declarações de função in-line. Eu encontrei esta solução em https://gcc.gnu.org/gcc-5/porting_to .html