doctrine2 - Как улучшить эффективность промывки?

Так как работает алгоритм связывания, используемый GNU-компоновщиком (как минимум, когда речь идет о связывании статических библиотек). Линкером является однопроходный компоновщик, и он не пересматривает библиотеки после их просмотра.

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

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

Итак, если вы включили некоторую библиотеку с помощью -l, компоновщик использует эту библиотеку для разрешения как можно большего количества текущих ожидающих символов, а затем полностью забывает об этой библиотеке. Если позднее позже внезапно обнаруживает, что теперь ему нужны некоторые дополнительные объектные файлы из этой библиотеки, компоновщик не будет «возвращаться» к этой библиотеке для извлечения этих дополнительных объектных файлов. Уже слишком поздно.

По этой причине всегда полезно использовать опцию -l late в командной строке компоновщика, так что к тому времени, когда линкер достигнет этого -l он может надежно определить, какие файлы объектов ему нужны и которые ему не нужны. Размещение параметра -l в качестве самого первого параметра в компоновщике вообще не имеет никакого смысла: в самом начале список ожидающих символов пуст (или, точнее, состоит из одного символа main), что означает, что linker вообще ничего не берет из библиотеки.

В вашем случае ваш объектный файл example.o содержит ссылки на символы ud_init, ud_set_input_file и т. д. Линкером следует сначала получить этот объектный файл. Он добавит эти символы в список ожидающих символов. После этого вы можете использовать опцию -l, чтобы добавить вашу библиотеку: -ludis86. Линкер будет искать вашу библиотеку и взять все, что разрешает эти ожидающие символы.

Если вы поместите параметр -ludis86 сначала в командной строке, компоновщик будет эффективно игнорировать вашей библиотеки, так как вначале он не знает, что ему понадобятся ud_init, ud_set_input_file и т. д. Позже, при обработке example.o, он обнаружит эти символы и добавит их в список ожидающих символов. Но эти символы останутся неразрешенными до конца, так как -ludis86 уже обработан (и эффективно игнорируется).

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

13
задан Petr Peller 3 January 2012 в 03:05
поделиться