Почему флаг компоновщика библиотеки иногда должен идти в конце с помощью GCC? - программирование
Подтвердить что ты не робот

Почему флаг компоновщика библиотеки иногда должен идти в конце с помощью GCC?

Я пишу небольшую программу на C, которая использует librt. Я очень удивлен тем, что программа не будет компилироваться, если я поставлю флаг ссылки в начале, а не в конце:

На данный момент для компиляции программы я делаю:

gcc -o prog prog.c -lrt -std=gnu99

Если бы я должен был сделать следующее, он не сможет найти функции в librt:

gcc -std=gnu99 -lrt -o prog prog.c

Тем не менее, это работает с другими библиотеками. Я нашел проблему при попытке использовать простой Makefile. make фактически скомпилировал prog.c, не желая сначала (используя флаг -c), а затем сделал ссылку.

Это Makefile:

CC = gcc

CFLAGS = -std=gnu99

LIBS= -lrt

LDFLAGS := -lrt


prog: prog.o

        $(CC) -o prog prog.c -lrt -std=gnu99

Результат, который я получил бы при вводе make, будет:

gcc -std=gnu99   -c -o prog.o prog.c
gcc -lrt  prog.o   -o prog
prog.o: In function `main':
prog.c:(.text+0xe6): undefined reference to `clock_gettime'
prog.c:(.text+0x2fc): undefined reference to `clock_gettime'
collect2: ld returned 1 exit status
make: *** [buff] Error 1

Теперь я создал Makefile, который помещает ссылку в конец строки gcc, однако я озадачен тем, почему он не работает, если флаг привязки находится в начале.

Буду признателен, если кто-нибудь сможет мне это объяснить. Спасибо.

4b9b3361

Ответ 1

Поскольку компоновщик обрабатывает каждый модуль (будь то библиотека или объектный файл), он пытается разрешить каждый символ undefined, одновременно добавляя к нему список символов undefined. Когда он попадает в список модулей, он либо разрешил все символы undefined, либо успешно, либо сообщает undefined символы.

В вашем случае, когда он обрабатывал librt, у него не было символов undefined. Обработка proc привела к тому, что clock_gettime является символом undefined. gcc не будет возвращаться и смотреть в librt для символов undefined.

По этой причине вы всегда должны иметь свой код, а затем ваши библиотеки, а затем библиотеки, предоставленные платформой.

Надеюсь, что это поможет.

Ответ 2

Из документации ld (GNU linker) (http://sourceware.org/binutils/docs/ld/Options.html#Options):

Линкеров будет искать архив только один раз, в том месте, где он указан в командной строке. Если архив определяет символ undefined в некотором объекте, который появился перед архивом в командной строке, компоновщик будет содержать файлы из архива. Однако символ undefined в объекте, появляющемся позже в командной строке, не заставит компоновщик снова искать архив.

Итак, если вы укажете библиотеку слишком рано, компоновщик сканирует ее, но не найдет ничего интересного. Затем компоновщик переходит к объектному файлу, создаваемому компилятором, и находит ссылки, которые необходимо разрешить, но он уже просмотрел библиотеку и больше не будет смотреть туда.