Почему я должен передавать библиотеки в конце строки компоновщика? [Дубликат]

0

Команда вроде этого будет работать:

(LD) $(LDFLAGS) -o reip.app newlib/crt0.o reip.o renetif.o fs.o httpd.o liblwip.a newlib/libc.a

Но если я помещаю *.a перед *.o файлами - он не сможет найти функции из libs.

Я просмотрел некоторые старые проекты и нашел в make файлах такие строки:

$(CC)  $(LIBS) -o $(TARGET) JukeboxMain.o JukeboxPlayer.o ...

который не работает, пока я не переместим $ (LIBS) в конец строки. Но я помню, что это работало для меня давным-давно. Может кто-то может ответить на то, что изменилось и почему он больше не работает) PS Я не большой поклонник игры с компиляторами, линкерами и другими инструментами - я предпочитаю больше всего создавать что-то;)

  • 2
    Создание чего-либо включает в себя создание Makefile, и это включает в себя понимание связей, причуд препроцессора и компилятора
  • 0
    @EliasVanOotegem Ну, не обязательно сделать файл. По крайней мере, не напрямую. Проект CMake работает так же хорошо.
Показать ещё 2 комментария
Теги:
makefile
linker

1 ответ

5
Лучший ответ

Я не могу ответить вам, почему вы думаете, что это могло бы сработать раньше. Но я могу сказать вам, почему это не работает вообще. Большинство компоновщиков в стиле POSIX, которые включают GNU binutils ld использующие GNU/Linux и другие, являются однопроходными линкерами.

Это означает, что они ходят элементы, перечисленные в командной строке, от начала до конца один раз, и они не возвращаются. Когда компоновщик запускает его, в основном ищет один символ, main. Когда он идет по командной строке, любой файл объекта (foo.o), найденный компоновщиком, всегда добавляется к исполняемому файлу. Объект предоставляет список символов, которые определены, и список, который не определен (требуется от других объектов).

Когда компоновщик попадает в статическую библиотеку (libfoo.a), он просматривает объектные файлы в этой библиотеке, и если объект содержит любой символ, который требуется компоновщику, он добавляет этот объект к исполняемому файлу. Если он не содержит никакого символа, который нужен компоновщику, он пропускает этот объект.

В конце командной строки, если какой-либо символ нужен, но не найден, ссылка не работает.

Таким образом, вы можете видеть, что для того, чтобы убедиться, что все найдено за один проход, вещи, которые НЕОБХОДИМЫЕ символы из библиотек должны поступать перед библиотеками, которые предоставляют эти символы, или когда компоновщик попадает в библиотеку за один проход, он выиграл Не знаю, нужны ли библиотеки и пропустит их.

  • 0
    Примечательный (забавный?) Факт: -lpthread - который необходим для большинства многопоточных приложений в системах Unix - следует этому же правилу. Однако -pthread неоспоримым функционально эквивалентными , могут быть размещены в любом месте.
  • 0
    Стефан: очень верно. Это потому, что -lpthread - это просто "найти библиотеку с именем pthread ", как и -lfoo . Это не имеет особого значения. Но -pthread - это магический флаг (не для компоновщика, а для драйвера компилятора), который говорит ему, что он должен делать все, что необходимо для обеспечения многопоточности. Это включает в себя добавление -lpthread (в конце, как и должно быть), а также все, что необходимо во время компиляции (добавление -D_REENTRANT или что-то еще). Поскольку разные системы используют разные опции, -pthread был разработан, чтобы «заставить его работать» везде.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню