Как GCC компилирует приложения, которые ссылаются на статическую библиотеку - PullRequest
0 голосов
/ 05 мая 2010

Я читал, что компилятор gcc может выполнять определенную оптимизацию при компиляции приложения, которое ссылается, например, на статическую библиотеку - он «вытянет» только тот код из статической библиотеки, от которой зависит приложение. Это помогает свести размер исполняемого файла приложения к минимуму, если части статической библиотеки не используются приложением.

1) Это правда?

2) Как GCC узнает, какой код из статической библиотеки на самом деле использует приложение? Это только смотрит на заголовочные файлы, которые включены (прямо и косвенно) в приложение, а затем извлекает код соответствующим образом? Или он действительно смотрит на то, какие методы из статической библиотеки вызываются?

Ответы [ 3 ]

2 голосов
/ 05 мая 2010

Статическая библиотека - это просто пакет объектных файлов. Компоновщик (ld) будет отслеживать, какие объектные файлы используются (т. Е. Содержит функцию, на которую ссылаются откуда-то), и не будет включать код без ссылок в окончательный исполняемый образ.

1 голос
/ 06 мая 2010

Ответы
1) Да, будет извлечен только код, на который есть ссылка. Помимо меньшего размера, также увеличивается скорость соединения, поскольку статическая библиотека содержит таблицу индексов всех символов, экспортируемых библиотекой. В этой таблице поиск выполняется быстрее, чем поиск в объектных файлах один за другим.
В качестве альтернативы, если вы хотите добавить все символы в статическую библиотеку независимо от ссылки. Вы можете передать ключ --whole-archive в ld.

2) Правильнее было бы задать этот вопрос в контексте ld (компоновщик gnu), поскольку именно это и привлекает ссылки. GCC просто вызывает компоновщик после завершения компиляции (если вы не выполните gcc -c, что приводит к его остановке после компиляции). Итак, после завершения компиляции ld вызывается с упорядоченным списком файлов объектов (.o) и библиотек. ld обрабатывает файлы .o по одному и для каждого компоновщика а) Записывает внешние символы, необходимые для этого файла, которые еще не могут быть решены. Добавляет их в (скажем) неразрешенную таблицу. б) Проверяет символы (функции, глобальные переменные), экспортированные этим файлом, и разрешает любые предыдущие ссылки, которые могут. Это очень упрощенный обзор процесса компоновки. Теперь, когда компоновщик приходит в статическую библиотеку, он делает то же самое, на этот раз используя статическую библиотеку для разрешения символов. Однако есть одно отличие: компоновщик извлекает только неразрешенные символы и их зависимости. Итак, предположим, у нас есть a.o и libstatic.a, которые в свою очередь содержат b.o и c.o.
b.o определяет bar () и moreBar ();
c.o определяет baz () и moreBaz ();
a.o определяет foo ();
где foo называет бар, который вызывает баз. Теперь, когда вы делаете gcc -o app a.o libstatic.a После обработки a.o компоновщик знает, что ему нужно разрешить панель, это разрешается из статической библиотеки, однако, разрешая панель, компоновщик замечает, что для панели требуется база. Это снова решается из libstatic.a. moreBar () и moreBaz () не имеют ссылок и игнорируются.

1 голос
/ 05 мая 2010

gcc ничего подобного не делает. Все, что вы описываете, это ссылка , которая обрабатывается ld.

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

...