2008-09-27 2 views
7

У меня возникла проблема с моим компилятором, говорящим, что есть «неопределенная ссылка» на функцию, которую я хочу использовать в библиотеке. Позволь мне поделиться некоторой информацией о проблеме:linker woes - undefined reference

  • Я кросс компиляция с GCC для C.
  • Я вызываю функцию библиотеки, который доступен через включаемый заголовок, который включает в себя еще один заголовок, который содержит прототип ,
  • Я включил каталог заголовков, используя -I, и я уверен, что он найден.
  • Я сначала создаю файлы .o, а затем связывая их в отдельной команде.

Итак, я думаю, что это может быть порядок, в который я включаю файлы библиотеки, но я не уверен, что это правильный способ их заказа. Я попытался включить папку заголовков как до, так и после файла .o.

Некоторые предложения были бы замечательными и, возможно, и объяснением того, как компоновщик делает свою работу.

Спасибо!


Ответ на ответы

  • нет файла библиотеки .a, просто .h и .c в библиотеке, поэтому -l не подходит
  • моего понимания файла библиотека заключается в том, что это всего лишь коллекция заголовков и исходных файлов, но, может быть, это коллекция файлов .o, созданных из источника ?!
  • не создается объект библиотеки библиотеки, может быть, должно быть? Да, кажется, я не понимаю разницы между включениями и библиотеками ... я буду работать над этим :-)

Спасибо за все ответы! Я много узнал о библиотеках. Я бы хотел, чтобы все ответы были приняты в качестве принятого ответа :-)

ответ

5

Похоже, что вы не компилируете файл .c в библиотеке для создания файла .o. Компилятор будет искать реализацию прототипа в файле .o, созданного путем компиляции библиотеки

Выполняет ли ваш процесс сборки файл .c?

Почему вы называете это «библиотекой», если это на самом деле только исходный код?

0

Я думаю, вы должны добавить путь, где компоновщик может найти библиотеку. В gcc/ld вы можете сделать это с помощью -L и libraray с -l.

-ldir, --library-путь = каталог

каталог Поиск реж до стандартного поиска каталогов (эта опция должна предшествовать опции -l, который ищет , что каталог).

-larch, --library = архив

Включить архивный файл арку в списке файлов ссылку.


Ответ на ответы - нет файла библиотеки .a, просто .h и .c в библиотеке, так -l не вывоза мебели

Тогда вы, возможно, сначала создать либрару?

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

Заголовки предоставляют декларации функций и определения функций. Чтобы позволить компоновщику найти реализацию функции (и избавиться от неопределенной ссылки), вам нужно попросить драйвер компилятора (gcc) связать конкретную библиотеку, в которой находится эта функция, используя флаг -l. Например, -lm свяжет математическую библиотеку. На странице руководства функции обычно указывается, какая библиотека, если таковая имеется, должна быть указана для поиска функции.

Если компоновщик не может найти указанную библиотеку, вы можете добавить путь поиска библиотеки, используя ключ -L (например, -L/usr/local/lib). Вы также можете постоянно влиять на путь библиотеки через переменную среды LIBRARY_PATH.

Дополнительные сведения, которые помогут вам отладить вашу проблему. По соглашению имена файлов библиотеки имеют префикс lib и (в их статической форме) имеют расширение .a. Таким образом, статически связанная версия математической библиотеки по умолчанию для системы (та, которую вы связываете с -lm) обычно находится в /usr/lib/libm.a. Чтобы узнать, какие символы заданы в данной библиотеке, вы можете запускать nm --defined-only в файле библиотеки. В моей системе запуск команды на libm.a дает мне вывод, как показано ниже.

e_atan2.o: 
00000000 T atan2 

e_asinf.o: 
00000000 T asinf 

e_asin.o: 
00000000 T asin 

Чтобы увидеть библиотеки путь, который использует компилятор и библиотеки, которые он загружает по умолчанию вы можете ссылаться на GCC с опцией -v. Снова в моей системе это дает следующий результат.

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

Файл заголовка ('.h' по умолчанию) _can_ содержит любой источник C, но _strongly_ обескуражен, чтобы помещать туда что-либо, кроме макроопределений и _declarations_. – vonbrand

1

Я боюсь, что вы смешали концепцию библиотеки и заголовка. Предположим, у вас есть библиотека libmylib.a, которая содержит функцию myfunc() и соответствующий заголовок mylib.h, который определяет его прототип. В исходном файле myapp.c вы включаете заголовок либо напрямую, либо включаете другой заголовок, который включает его. Например:

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

ваш исходный файл выглядит следующим образом:

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

Теперь вы можете скомпилировать его, чтобы получить myapp.o:

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

Обратите внимание, что -I просто говорит GCC, где заголовки файлы, они не имеют ничего общего с самой библиотекой!

Теперь вы можете связать приложение с реальной библиотеки:

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

Обратите внимание, что переключатель -L говорит GCC, где находится библиотека, и -l говорит, что связать свой код в библиотеку.

Если вы не сделаете этот последний шаг, вы можете столкнуться с проблемой, которую вы описали.

Могут быть другие более сложные случаи, но из вашего вопроса я надеюсь, что этого будет достаточно, чтобы решить вашу проблему.

1

Опубликуйте свой файл makefile и функцию библиотеки, которую вы пытаетесь вызвать. Даже простые НКУ Makefiles обычно имеют такую ​​строку:

LIBFLAGS = -lc -lpthread -lrt -lstdC++ -lShared -L ../ общий

В данном случае это означает связать стандартную библиотеку C, в том числе Другие

0

Я столкнулся с этой проблемой при создании программы с новой версией gcc. Проблема была устранена вызовом gcc с опцией -std = gnu89. По-видимому, это было связано с объявлениями встроенных функций. Я нашел это решение по адресу https://gcc.gnu.org/gcc-5/porting_to.html