Получение неопределенных ссылок при связывании со статической библиотекой

Я сделал статическую библиотеку с помощью GCC. Здание библиотеки было в порядке.

Когда я его использую, компоновщик выдает неопределенные ссылочные ошибки для некоторых функций. Но nm говорит, что функции определены и экспортированы в статическую библиотеку (помеченную буквой T). Я знаю о порядке компоновки, что мне нужно поместить библиотеки после того модуля, который в них нуждается, так что это не может быть проблемой.

Статическая библиотека была собрана из 3 файлов C. A.c B.c и D.c Модуль D зависит от A и B (включая их заголовки).

Нет проблем, когда я использую функции из A и B, но когда я пытаюсь использовать любую функцию из D, я получаю неопределенные ссылки на них.

Если я перемещаю эти функции в A или B, это работает. Но только не в том случае, если они находятся в модуле D.

У меня полностью закончились идеи, что происходит или что я упускаю из виду.

Я использую Code::Blocks и работаю с простыми файлами C.


person Calmarius    schedule 10.07.2010    source источник
comment
Предоставьте дополнительную информацию о том, какие функции находятся в каком файле C и какие из них получают неопределенные ссылки (и вызываете ли вы их из другого объектного файла в этой библиотеке или другого объекта).   -  person paxdiablo    schedule 10.07.2010


Ответы (4)


Старый трюк, который часто работает: перечислите каждую статическую библиотеку дважды на этапе компоновки.

т. е. в вашем make-файле (или в том, что вы используете) поместите:

gcc -o <outfile> <liba> <libb> <libc> <liba> <libb> <libc>

Во всяком случае, я надеюсь, что вы поняли идею.

person adamk    schedule 10.07.2010

Я узнал, что добавил файл .cpp в свой проект и просто переименовал его в .c. Я выбрал язык C вместо C++, когда создавал проект. Я не думал, что это может вызвать проблемы

Я думал, что расширение файла решает, когда IDE выбирает между gcc и g++. Но нет. В Code::Blocks, если вы добавите файл с расширением .cpp, он будет использовать g++. Если вы добавите файл с расширением .c, он будет использовать gcc. Но если вы переименуете файл, он будет использовать тот же компилятор. Вы должны изменить это явно в параметрах проекта.

Этот модуль D был построен с использованием g++ вместо gcc.

Я понял это, когда настроил IDE так, чтобы при сборке отображалась вся командная строка, а не только «Компиляция foo.c».

person Calmarius    schedule 12.07.2010

В главном make-файле, который я написал для упрощения сборки приложения/библиотеки, я использовал решение, которое заключалось в том, чтобы выполнить этап связывания дважды. Использование параметра компоновщика -u, чтобы указать неопределенные символы во второй ссылке.

В моем файле make у меня есть такая цель:

undefined.txt:
    @$(generate-undefined-syms)

который вызывает этот макрос... первая попытка связывания...

define generate-undefined-syms
    $(PRINTF) "$(this_makefile): Generating undefined symbols ... \n"
    $(CC) -o rubbish $(LDFLAGS) $(objects) $(LDLIBS) 2>&1 | $(GREP) 'undefined reference' > tmp.txt; \
    $(SED) 's/^.*`/-Wl,-u/g' < tmp.txt > undefined.txt; \
    rm -f tmp.txt rubbish
endef

Поскольку мои навыки работы с sed/regexp не очень хороши (и я написал этот материал в спешке), я получаю файл undefined.txt, содержащий:

-uSomeSym'
-uSomeOtherSym'

то есть с завершающим '

Затем я использую этот синтаксис make для удаления и удаления дубликатов.

undefined_references = $(filter-out follow, $(sort $(subst ',,$(shell cat undefined.txt))))

Фильтр «follow» возникает потому, что если на неопределенный символ ссылаются много раз, в выводе появляется сообщение «больше ссылок на XXX», что приводит к ложному «follow» в файле undefined.txt, например.

-Wl, uXXXX' follow

Наконец я связываю второй раз (обратите внимание на зависимость от undefined.txt)

$(application): $(library_dependencies) $(objects) undefined.txt
    $(CC) -o $@ $(LDFLAGS) $(undefined_references) $(objects) $(LDLIBS)

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

Управление проектами с помощью GNU Make, третье издание Автор: Роберт Мекленбург

person Matthew Mckay-Davies    schedule 18.05.2012

Возможно, вам следует использовать ranlib или соответствующую опцию ar, чтобы указать индекс для вашего файла .a.

person Jens Gustedt    schedule 10.07.2010