Программа, связанная со статической библиотекой VS Исходный код Скомпилированная программа огромная разница в размере

У меня есть библиотека (Crypto ++), ее всего почти 50 МБ, когда библиотека скомпилирована.

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

Итак, теперь у меня 2 проекта:

Проект 1: имеет только необходимые исходные файлы для компиляции и использования только нужных мне алгоритмов AES, SHA256 и т. Д.

Проект 2: содержит только файлы заголовков и связанную статическую библиотеку Crypto ++.

Теперь, когда я компилирую оба проекта, я должен был (или всегда думал) увидеть, что оба exes имеют одинаковый размер, поскольку компоновщик будет связывать только источник, который я использую в Project 2, с exe, в основном он будет связывать именно те же файлы, которые я использую в Project 1. Но это не тот случай, я вижу огромную разницу между Project 1 и Project 2 ... Проект, который использует статическую библиотеку, в 6,2 раза больше, чем проект, который был скомпилирован с исходный код (оба скомпилированы в режиме выпуска)

Размер проекта 1 (исходный код): 210 КБ Размер проекта 2 (статическая библиотека): 1,303 КБ

Почему это? Я всегда думал, что компоновщик должен использовать только то, на что я ссылаюсь в своем коде. Это просто неэффективность компоновщика?

Может ли кто-нибудь просветить меня?


person AntiBNI    schedule 02.04.2016    source источник


Ответы (2)


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

person Pemdas    schedule 02.04.2016

У меня есть библиотека (Crypto ++), ее всего почти 50 МБ, когда библиотека скомпилирована ....

Да, статическая библиотека содержит все символы. Ничего нельзя отбрасывать, потому что это может понадобиться.

Он также содержит отладочную информацию, если вы использовали -g. Некоторые флаги оптимизации тоже повлияют на это. Например, -Os минимизирует размер кода.


Проект, использующий статическую библиотеку, в 6,2 раза больше, чем проект, скомпилированный с исходным кодом. Почему это?

Нам нужно увидеть вашу программу, а также переключатели вашего компилятора и компоновщика, чтобы лучше объяснить, что происходит. Основываясь на этих цифрах, я предполагаю, что происходит удаление мертвого кода, но не в такой степени, как вы ожидаете:

Размер проекта 1 (исходный код): 210 КБ Размер проекта 2 (статическая библиотека): 1,303 КБ


Я всегда думал, что компоновщик должен использовать только то, на что я ссылаюсь в своем коде. Это просто неэффективность компоновщика?

При создании библиотеки Crypto ++ используйте make lean рецепт. Он добавляет функциональные разделы (-ffunction-sections) и разделы данных (-fdata-sections), чтобы компоновщик мог лучше удалять неиспользуемый код и данные. См. Также GNUmakefile | Makefile Targets на вики-странице Crypto ++.

Когда вы связываете свое приложение, используйте соответствующий переключатель компоновщика. С GCC / LD это будет -Wl,--gc-sections. В Apple / DYLD это будет -Wl,-dead_strip.


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

Если вы полностью удалите символы и отбросите их, следы стека будут в основном бесполезны. Если вы сохраните символы в автономном файле, вы сможете разобраться в трассировке стека. Также см. символы отладки в вики-сайте Crypto ++.


Вот результаты исследования цели lean для пользователей. Также см. цель «сделать бережливое»? в группе пользователей Crypto ++ .

Тестовая программа:

int main( int, char** ) {

  Integer j("100000000000000000000000000000000");
  j %= 1999;

  cout << "j: " << j << endl;

  return 0;
}

Lean (библиотека, созданная с использованием make lean, программа связана с -Wl,--gc-sections):

$ ls -l integer.exe
-rwx------  1 jwalton  staff  162012 Jan  4 13:00 integer.exe

Обычный (библиотека построена с использованием make, без специальных переключателей компоновщика):

$ ls -l integer.exe
-rwx------  1 jwalton  staff  2636952 Jan  4 13:02 integer.exe

Цель lean была добавлена ​​после выпуска Crypto ++ 5.6.3. Вам нужно будет получить код от Мастера, если вы этого хотите:

git clone https://github.com/weidai11/cryptopp.git cryptopp

Или вы можете вручную применить указанный ниже патч к GNUmakefile из Commit 9696b9e5e79ff18a. Добавьте его около строки 270:

+# Dead code stripping. Issue 'make lean'.
+ifeq ($(findstring lean,$(MAKECMDGOALS)),lean)
+ifeq ($(findstring -ffunction-sections,$(CXXFLAGS)),)
+CXXFLAGS += -ffunction-sections
+endif # CXXFLAGS
+ifeq ($(findstring -fdata-sections,$(CXXFLAGS)),)
+CXXFLAGS += -fdata-sections
+endif # CXXFLAGS
+ifneq ($(IS_DARWIN),0)
+ifeq ($(findstring -Wl,-dead_strip,$(LDFLAGS)),)
+LDFLAGS += -Wl,-dead_strip
+endif # CXXFLAGS
+else # BSD, Linux and Unix
+ifeq ($(findstring -Wl,--gc-sections,$(LDFLAGS)),)
+LDFLAGS += -Wl,--gc-sections
+endif # LDFLAGS
+endif # MAKECMDGOALS
+endif # Dead code stripping

И следующие где рецепты:

+.PHONY: lean
+lean: libcryptopp.a cryptest.exe
+
person jww    schedule 02.04.2016