2011-12-27 3 views
12

Я пытаюсь связать модуль C++ с использованием GCC, по сути, как это:Код ссылки GCC изменен?

gcc -c hello.c 
g++ -c world.cpp 
gcc -ohello -lstdc++ hello.o world.o 

Обратите внимание, что я использую -lstdc++ связать модуль C++ в, так что я могу использовать gcc вместо g++. Проблема заключается в том, что я получаю сообщение об ошибке:

undefined reference to `operator new(unsigned long)' 

(Предполагая, что world.cpp содержит, по меньшей мере, один вызов new.)

Эта ошибка исправлена, если я ставлю -lstdc++ в конце линкера линии , например:

gcc -ohello hello.o world.o -lstdc++ 

Я знаю, что этот вопрос задавался много раз здесь, но у меня есть специальное требование. Я напрямую не звоню в GCC. Я использую систему сборки для другого языка программирования (Mercury), который вызывает от меня GCC, и я не могу легко изменить способ его вызова GCC (хотя я могу указать дополнительные библиотеки, используя переменную среды LDFLAGS). Так что у меня есть два дополнительных требования:

  • Я не могу использовать g++ связать (только gcc) - вот почему я делаю -lstdc++ трюк выше, чем просто связь с g++).
  • Я не думаю, что могу контролировать порядок команд компоновщика - Mercury поместит файлы .o в командной строке после любых библиотек.

Я понимаю основную причину, почему порядок важен, но то, что сбивает с толку меня это почему этот перерыв сейчас? Я просто обновился до Ubuntu 11.10/GCC 4.6.1. Я успешно скомпилировал эту программу в течение многих лет, используя именно эту технику (сначала ставил -lstdc++). Только теперь эта ошибка возникла. Несвязанная программа моих ссылок на OpenGL с использованием -lgl, и это тоже сломалось, когда я обновился, и мне пришлось переместить -lgl в конец командной строки. Вероятно, я узнаю, что десятки моих программ больше не компилируются. Почему это изменилось? Что-то не так с моей новой системой, или так, как сейчас? Обратите внимание, что это обычные общие библиотеки, а не статически связанные.

Есть ли что-нибудь, что я могу сделать, чтобы GCC вернулась к старому пути, где порядок библиотек не имеет значения? Есть ли другой способ, которым я могу убедить GCC правильно связать libstdc++, не перемещая его после файлов .o в командной строке?

ответ

12

Если Mercury помещает файлы объектов после библиотек, Меркурий не работает. Библиотеки принадлежат объектным файлам - всегда. Иногда вы можете уйти с обратным порядком, но не надежно. (Статические библиотеки должны идти за объектными файлами, которые ссылаются на символы в статической библиотеке. Иногда линкер отмечает символы, определенные общей библиотекой, даже если ни один из символов не используется, иногда компоновщик будет отмечать только символы общей библиотеки если в общей библиотеке имеется хотя бы один символ.)

+3

Итак, в основном этот «регресс» - это только для моей карьеры развития, я полагался на то, что он «случайно работал», и теперь он перестает работать? Похоже, это довольно серьезное изменение - я помещал библиотеки перед объектными файлами в течение большей части десятилетия, потому что я понятия не имел, что это проблема :(Спасибо за совет.Похоже, проблема заключалась не в том, что объекты Mercury помещаются после библиотек, но в моей команде LDFLAGS есть более сложные зависимости. Я добиваюсь прогресса, поэтому я дам вам галочку. Благодарю. – mgiuca

+1

Неподтвержденная гипотеза: возможно, произошли изменения в 'ld', которые влияют на вас. Целью может быть избежать загрузки неиспользуемых разделяемых библиотек. Если вы используете статические библиотеки, вы получаете только то, что вам нужно. Раньше было, что если вы указали общую библиотеку в линии ссылок, она будет загружена во время выполнения, даже если библиотека не предоставила никаких символов. Только загрузка библиотеки, если она удовлетворяет хотя бы одному символу, может сократить время запуска программы. Но это также означает, что если единственным выдающимся символом при сканировании библиотеки является 'main()', то библиотека не будет загружена. –

+0

Просмотреть комментарии о '--as-needed' для версии 2.20' ld' в [НОВОСТИ] (http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout//src/ld/NEWS? rev = 1.121 & content-type = text/plain & cvsroot = src & only_with_tag = binutils-binutils-2_22). См. Также [manual] (http://sourceware.org/binutils/docs-2.22/ld/Options.html#Options) и '-copy-dt-required-entries' и' -no-copy- dt-required-entries'. Я полагаю, что предыдущая гипотеза - хотя бы несколько доказана. –

Смежные вопросы