проблемы компоновщика - неопределенная ссылка

StackOverflow https://stackoverflow.com/questions/143530

  •  02-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

Спасибо!


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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

Опубликуйте свой makefile и библиотечную функцию, которую вы пытаетесь вызвать.Даже простые gcc makefile обычно содержат строку, подобную этой:

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

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

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

-Ldir, --library-path=каталог

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

-лиственница, --библиотека=архив

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


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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top