Как убедиться, что неиспользуемые символы не связаны с окончательным исполняемым файлом?

Прежде всего мои извинения тем из вас, кто следил бы за моими вопросами, опубликованными в последние несколько дней. Это может показаться немного повторяющимся, поскольку я задавал вопросы, связанные с разделами -ffunction-sections и -fdata-sections, и этот вопрос находится в той же строке. Эти вопросы и их ответы не решили мою проблему, поэтому я понял, что для меня лучше всего изложить здесь полную проблему и позволить экспертам SO обдумать ее. Извините, что не сделал этого раньше.

Итак, вот моя проблема:

Я создаю набор статических библиотек, которые предоставляют множество функций. Эти статические библиотеки будут предоставляться многим продуктам. Не все продукты будут использовать все функции, предоставляемые моими библиотеками. Проблема в том, что размеры библиотек довольно велики, и продукты хотят, чтобы они были уменьшены. Основная цель — уменьшить окончательный размер исполняемого файла, а не размер самой библиотеки.

Теперь я провел небольшое исследование и обнаружил, что если в исходном файле есть 4 функции, и только одна из них используется приложением, компоновщик все равно включит остальные 3 функции в окончательный исполняемый файл, поскольку все они принадлежат одному и тому же объектному файлу. Далее я проанализировал и обнаружил, что -ffunction-sections, -fdata-sections и -gc-sections (это опция компоновщика) гарантируют, что будет связана только одна функция.

Но эти опции по независящим от меня причинам сейчас не могут быть использованы.

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

Есть ли другие способы борьбы с проблемой?

Примечание. Реорганизация моего кода почти исключена, так как это устаревший и большой код.

Здесь я имею дело в основном с VxWorks и GCC.

Спасибо за любую помощь!


person Jay    schedule 26.11.2010    source источник
comment
groups.google.com/group/gnu.gcc.help/ browse_thread/thread/ Это короткое обсуждение посвящено тому же вопросу, который вы задали. Подробно рассказывает о том, что делает компилятор и компоновщик. Может вас заинтересовать.   -  person vpit3833    schedule 26.11.2010


Ответы (1)


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

Если вы посмотрите на "Стандартную библиотеку C от Plauger ", вы обнаружите, что каждая функция реализована в отдельном файле, даже если файл состоит из 4 строк (один заголовок, одна функциональная строка, открывающая фигурная скобка, одна строка кода и закрывающая скобка).


Джей спросил:

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

Я не говорил, что это широко используется - это не так. Но это способ убедиться, что двоичные файлы сведены к минимуму. Компилятор (компоновщик) не будет выполнять минимизацию за вас - по крайней мере, я не знаю ни одного, кто бы это делал. В большом проекте вы проектируете исходные файлы таким образом, чтобы тесно связанные функции, которые обычно используются вместе, были сгруппированы в отдельные исходные файлы. Функции, которые используются лишь изредка, должны быть помещены в отдельные файлы. В идеале каждая редко используемая функция должна находиться в отдельном файле; в противном случае сгруппируйте небольшое их количество в небольшие (но не минимальные) файлы. Таким образом, если используется одна из редко используемых функций, вы получаете только ограниченное количество лишнего неиспользуемого связанного кода.

Что касается количества файлов - да, поддерживаемая методика означает большое количество файлов. Вы должны взвесить рабочую нагрузку по управлению (именованию) большого количества файлов с преимуществом минимального размера кода. Автоматические системы сборки устраняют большую часть боли; Системы VCS обрабатывают множество файлов.

Другой альтернативой является размещение кода библиотеки в общем объекте или в динамической библиотеке ссылок (DLL). Затем программы связываются с общим объектом, который загружается в память только один раз и совместно используется программами, использующими его. (Непостоянные) данные реплицируются для каждого процесса. Это уменьшает размер программ на диске за счет исправлений в процессе загрузки. Однако тогда вам не нужно беспокоиться о размере исполняемого файла; исполняемые файлы не включают общие объекты. И вы можете обновить библиотеку (если вы будете осторожны) без перекомпиляции основных программ, которые ее используют. Уменьшенный размер исполняемых файлов — одна из причин популярности разделяемых библиотек.

person Jonathan Leffler    schedule 26.11.2010
comment
но в случае большого проекта не становится ли сложно управлять таким количеством файлов? Кроме того, я не нахожу много проектов с открытым исходным кодом, следующих этой модели. OpenSSL является одним из примеров. - person Jay; 26.11.2010