горе линкера - неопределенная ссылка - PullRequest
7 голосов
/ 27 сентября 2008

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

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

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

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

Спасибо!


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

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

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

Ответы [ 6 ]

5 голосов
/ 27 сентября 2008

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

Ваш процесс сборки компилирует файл библиотеки .c?

Почему вы называете это "библиотекой", если на самом деле это просто исходный код?

4 голосов
/ 27 сентября 2008

Заголовки обеспечивают объявления функций и определения функций. Чтобы компоновщик мог найти реализацию функции (и избавиться от неопределенной ссылки), вам нужно попросить драйвер компилятора (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
1 голос
/ 27 сентября 2008

Разместите свой make-файл и библиотечную функцию, которую вы пытаетесь вызвать. Даже простые make-файлы gcc обычно имеют такую ​​строку:

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

В данном случае это означает ссылку на стандартную библиотеку C, среди прочего

1 голос
/ 27 сентября 2008

Боюсь, вы смешали понятия библиотеки и заголовка. Допустим, у вас есть библиотека 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 указывает ему связать ваш код с библиотекой.

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

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

0 голосов
/ 11 октября 2016

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

0 голосов
/ 27 сентября 2008

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

-Ldir, --library-path = dir

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

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

Включить архив архива в список файлов для ссылки.


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

Тогда вам, возможно, придется сначала создать библиотека?

gcc -c mylib.c -o mylib.o
ar  rcs libmylib.a      mylib.o
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...