У меня есть проект, написанный на C++, и платформа, на которой он будет развернут, имеет ограничение размера двоичного файла в 256 КБ.
Набор инструментов — wasi-sdk-16.0 clang++, мы используем этот компилятор для компиляции исходного кода в двоичный файл в формате WASM. На этом этапе мы компилируем исходники со следующими CXX_FLAGS.
-fstack-protector-strong -Os -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security -Wl,-z,relro,-z,now -Wno-psabi
Затем мы strip бинарный файл с
strip -s output_binary.wasm
После описанных выше шагов размер скомпилированного двоичного файла на этом шаге составляет 254 КБ.
Затем мы используем wamrc в WAMR для компиляции двоичного файла WASM со средой выполнения AOT, команда показана ниже.
wamrc --enable-indirect-mode --disable-llvm-intrinsics -o output.aot output.wasm
размер выходного двоичного файла становится 428 КБ, что намного больше ограничения (256 КБ).
После того, как я погуглил, я использую wasm-opt, чтобы уменьшить размер,
wasm-opt -Oz output.wasm -o output.wasm
Размер стал на 4 КБ меньше. (почти бесполезно)
Я попытался подтвердить, насколько мой код влияет на размер двоичного файла, поэтому я пишу простой минимальный пример кода, который называется стандартной библиотекой C++, как показано ниже:
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {1,2,3,4,5};
for (auto v: vec) {
std::cout << v << " ";
}
}
Размер двоичного файла после компиляции действительно стал 205 КБ.
Я также пытался использовать профилировщик размера двоичного файла (twiggy), чтобы отслеживать размер каждой части бианри, но этот инструмент не смог открыть этот двоичный файл.
Поэтому я хочу спросить
В то время как просто включение двух стандартных заголовков С++ приводит к тому, что размер двоичного файла достигает ограничения размера, как я могу удалить стандартную библиотеку С++ с помощью функции, которую я действительно использую (я не могу использовать флаг удаления неиспользуемой функции, потому что мой проект является библиотекой, предоставляемой другим), или действительно ли стандартная библиотека С++ повлияла на размер двоичного файла?
Существуют ли какие-либо другие флаги компилятора, флаги полосы или любые другие инструменты оптимизации, которые могут значительно уменьшить размер двоичного файла?
Попробуйте построить все с включенной LTO (Link Time Optimization). Помимо обычно более быстрого кода, это также часто приводит к меньшим двоичным файлам.
Компоновщик также может выполнять некоторые собственные оптимизации (помимо LTO). Вы можете включить их с помощью -Wl,-O, и это иногда также может уменьшить размер двоичного файла (немного).
Также обратите внимание на опцию компоновщика --gc-sections. Это может быть полезно для вас.
Хотя предполагается, что параметр компилятора -Os оптимизирует размер, он не всегда дает наименьший возможный двоичный файл. Попробуйте также поэкспериментировать с -Og, -O1, -O2 и -O3.
Часто вы можете сэкономить место, переупорядочив элементы struct/class таким образом, чтобы уменьшить количество отступов, которые компилятор должен вставлять между членами. Это часто может сэкономить много места для нетривиальных программ. См., например, ibm.com/docs/en/i/…
Еще одна вещь, которую вы можете сделать, это убедиться, что только функции/типы, которые вам нужно экспортировать, имеют не скрытую видимость. См. gcc.gnu.org/wiki/Visibility
Объявление structs и classs, которые вам не нужны/не хотят наследовать от as final, также может в некоторых случаях помочь оптимизатору компилятора генерировать более быстрый, а иногда и меньший код.
Предполагается, что параметр компилятора -Oz более агрессивно оптимизирует размер, чем -Os — попробуйте.
Также проверьте инструмент sstrip, чтобы, возможно, сбрить еще несколько байтов из ваших файлов.
Вместо того, чтобы редактировать ответ в вопросе, опубликуйте свои ответы как правильный ответ на вопрос. Вы даже можете щелкнуть галочку «принять» в своем собственном ответе, чтобы показать будущим читателям, что это сработало для вас.





Одна из вещей, которые я не увидела в вашем посте, это wabtwasm-strip. Я недостаточно знаком с ним, чтобы знать, делает ли он что-то большее, чем простая команда strip, но, возможно, стоит попробовать. Вы можете установить его с помощью apt install wasm-strip в системе Debian.
Судя по нескольким микротестам, которые я видел в Интернете, двоичные файлы C++ wasm имеют большие накладные расходы. Для совершенно ненаучного слайда вы можете посмотреть это.
Если по какой-либо причине вы не можете работать с языком для создания двоичных файлов меньшего размера, вы можете попытаться оптимизировать также на уровне ссылок, как это делает busybox.
Я решаю эту проблему, просто заменяя iostream и fstream на cstdio. Он уменьшает размер с 254 КБ до 85 КБ, потому что в iostream содержится слишком много шаблонов.
iostream
Количество функций (с readelf -Ws)
Размер двоичного файла
Да
685
254 КБ
Нет
76
85 КБ
Хотя указание флагов компилятора, таких как -Oz, также немного уменьшает размер, но основной фактор заключается в том, что слишком много кода было сгенерировано из шаблонов. Таким образом, не используйте потоковый API C++ (и любые другие библиотеки общего назначения с большим количеством шаблонов), когда существуют ограничения на размер двоичного файла. (В библиотеки C всегда стоит верить.)
Вы могли бы подумать, что высокий уровень оптимизации заставит компилятор встраивать все шаблоны
C++
iostreamдовольно громоздкий, включает много библиотечного кода. Очень важно, какие два заголовка вы использовали; например#include <algorithm>будут только шаблонными функциями, поэтому вы будете платить только за то, что используете. То же самое с#include <vector>; это довольно легкий вес.