Страницы

Поиск по вопросам

четверг, 2 января 2020 г.

Выборочная линковка в GCC

#c #gcc #link


Как правильно организовать выборочную сборку программы в GCC?
Предположим имеется такой набор независимых друг от друга исходных файлов:

Vec2.c
Vec3.c
Mat3.c


, которые собираются в библиотэкуlibMegaSuperMath.a.
Ясен пень, линкуя такую библиотэку, мы включаем все ее содержимое в конечный исполняемый
модуль (или не включаем?).
Как организовать выборочную линковку, в случае, если программа, использующая такую
библиотэку не нуждается в некоторых из ее компонентов? Вырежет ли GCC неиспользуемые
структуры, функции и данные? Какие флаги оптимизации требуются для этого?
Приемлем ли в подобной ситуации подход, при котором отдельные "классы" библиотэки
собираются в объектные файлы, а инструкция сборки формируется на основании требующихся
"классов"? Типа как-то так:

Vec2.o
Vec3.o
Mat3.o


и

cc NewUberTurboProgramm.c Vec2.o Mat3.o -o Run.exe

    


Ответы

Ответ 1



Нет, библиотека не линкуется безусловно и целиком. Библиотека - это архив объектных файлов, из которого берутся только "нужные" объектные файлы. В "классическом" алгоритме линковки библиотек из библиотеки берутся те и только те объектные файлы, которые нужны на текущий момент. Линкер просматривает линкуемые компоненты последовательно, слева-направо, как они указаны в командной строке линкера. В процессе такого просмотра он поддерживает список ненайденных/неразрешенных на данный момент символов (в самом начале этот список состоит из просто символа main или его аналога). В процессе обработки слева-направо из очередной встреченной в командной строке библиотеки берутся те и только те объектные файлы, которые разрешают какие-то из не разрешенных на текущий момент символов. Таким образом изъятие кода из библиотеки делается с точностью до объектного файла. Так что ваше утверждение "линкуя такую библиотэку, мы включаем все ее содержимое в конечный исполняемый модуль" - не верно. Из этого также следует, что библиотеки в командной строке линкера лучше указывать где-то в конце - когда линкер уже знает весь список неразрешенных символов и, соответственно, возьмет из библиотеки все, что надо. Если указать библиотеку в командной строке слишком рано, то может получиться так, что линкер возьмет из нее не все, что нужно, ибо в этот момент он еще не знал все, что нужно. В частности, если указать библиотеку самой первой в командной строке, из нее не возьмется вообще ничего (если библиотека не предоставляет main). С прямым указанием отдельных объектных файлов в командной строке линкера ситуация иная: явно указанный объектный файл всегда безусловно целиком линкуется в программу, независимо от того, "нужен" ли он на этот момент или нет. В традиционном "классическом" линкере добиться линковки с точностью до функции можно только помещая каждую функцию в свой отдельный объектный файл. Но многие современные компиляторы и линкеры уже поддерживают линковку с точностью до отдельной функции без необходимости такого индивидуального разбрасывания функций по файлам. В GCC это делается через LTO - link-time optimizations.

Комментариев нет:

Отправить комментарий