И, собственно всё. Иные флаги оптимизаций не влияют на размер при текущей кодовой базе.
То есть ни -flto/-flto=thin, ни -fno-exceptions ни даже специальный флаг GCC -fwhole-program не помогли выкинуть лишнее в случае включения iostream. Видимо линкер считает все его зависимости используемыми.
С printf также, линкер даже со всеми навешенными оптимизациями может просто не найти неиспользуемые символы чтобы их выкинуть.
Оптимизации линкера очень хороши, но они бессильны если из конкретной сборки стандартной либы физически выкидывать нечего.
Что на счет отказа от CRT - я это использовал в качестве сравнительного примера именно для Hello World и только под Windows.
Однако для проектов посложнее, однозначно что этот путь будет крайне тернист и использование стандартного CRT будет куда выгоднее.
Я даже не стал приводить приводить примеров самопального CRT для Linux, т.к. там уже понадобились бы прямые ассемблерные вставки, что уже требует специализаций под конкретную архитектуру, а там уже есть чему ломаться. У части пользователей это могло бы просто не запуститься или что еще хуже выполнить это некорректно. Тут рациональнее использовать статическую линковку с musl заместо glibc.
В вашем примере вы полагаетесь на то, что в системе будут и libstdc++ и libc и libm и еще от компилятора libgcc_s.
Если хоть чего-то из этого не будет, или же будет не той версии которой нужно (привет от GLIBC) - ваш файл превращается в тыкву. Он не запуститься в среде с musl или же где нет компилятора с его libgcc_s.so.
Я пытался сделать обзор проблемы именно с точки зрения разработчика С++, а не как ревер-инженер на ASM. Целью этого мини-исследования было именно практически добиться минимально возможного размера компилятором С++ (в данном случае GCC) и показать развитие тенденции вместе с обновлением компилятора, конкретное содержание PE заголовков для этого мне показалось излишним. Хотя это вполне имеет место быть, и спасибо вам за дополнение!
Проблема в том, что более высокоуровневые языки почему-то не выкидывают лишнее в очевидных ситуациях, когда исключения попросту не требуются. Например компилятор GCC догадывается не прикручивать исключения для Hello Worldно как только в коде появляется malloc()/free() компилятор уже может их включить, и тут уже нужно явно указывать флаг что стоит отключить добавление механизма исключений.
В вашем примере для того чтобы добиться размера меньше, вам уже пришлось использовать ASM, что уже не совсем разработка на С++ :)
Компилятор по идее для того и нужен чтобы упростить жизнь разработчику и не заставлять его писать на ASM из-за того что компилятор не справился со своей задачей лучше программиста.
Я упоминал, что:
То есть ни
-flto/-flto=thin, ни-fno-exceptionsни даже специальный флаг GCC-fwhole-programне помогли выкинуть лишнее в случае включенияiostream. Видимо линкер считает все его зависимости используемыми.С
printfтакже, линкер даже со всеми навешенными оптимизациями может просто не найти неиспользуемые символы чтобы их выкинуть.Оптимизации линкера очень хороши, но они бессильны если из конкретной сборки стандартной либы физически выкидывать нечего.
Что на счет отказа от
CRT- я это использовал в качестве сравнительного примера именно дляHello Worldи только подWindows.Однако для проектов посложнее, однозначно что этот путь будет крайне тернист и использование стандартного
CRTбудет куда выгоднее.Я даже не стал приводить приводить примеров самопального
CRTдляLinux, т.к. там уже понадобились бы прямые ассемблерные вставки, что уже требует специализаций под конкретную архитектуру, а там уже есть чему ломаться. У части пользователей это могло бы просто не запуститься или что еще хуже выполнить это некорректно. Тут рациональнее использовать статическую линковку сmuslзаместоglibc.Это же касается только RAM, кризис HDD пока еще не наступил, так что экономия места там мало кого волнует.
Как только вы начинаете полагаться на то что
libstdc++будет предустановлена в системе, есть риск, что на другом компьютере вы можете столкнуться cИли какой-либо другой внешней библиотеки на которую вы полагаетесь. Это уменьшает переносимость и вынуждает качать внешние зависимости.
В вашем примере вы полагаетесь на то, что в системе будут и
libstdc++иlibcиlibmи еще от компилятораlibgcc_s.Если хоть чего-то из этого не будет, или же будет не той версии которой нужно (привет от
GLIBC) - ваш файл превращается в тыкву. Он не запуститься в среде сmuslили же где нет компилятора с егоlibgcc_s.so.Я пытался сделать обзор проблемы именно с точки зрения разработчика С++, а не как ревер-инженер на ASM. Целью этого мини-исследования было именно практически добиться минимально возможного размера компилятором С++ (в данном случае GCC) и показать развитие тенденции вместе с обновлением компилятора, конкретное содержание PE заголовков для этого мне показалось излишним. Хотя это вполне имеет место быть, и спасибо вам за дополнение!
Проблема в том, что более высокоуровневые языки почему-то не выкидывают лишнее в очевидных ситуациях, когда исключения попросту не требуются. Например компилятор GCC догадывается не прикручивать исключения для
Hello Worldно как только в коде появляетсяmalloc()/free()компилятор уже может их включить, и тут уже нужно явно указывать флаг что стоит отключить добавление механизма исключений.В вашем примере для того чтобы добиться размера меньше, вам уже пришлось использовать ASM, что уже не совсем разработка на С++ :)
Компилятор по идее для того и нужен чтобы упростить жизнь разработчику и не заставлять его писать на ASM из-за того что компилятор не справился со своей задачей лучше программиста.