9.3 Из горна
Артефакт прошёл заставу. Тесты проходят, порт доказывает себя, журнал ведётся, дверь закрывается чисто. Всё это - в мастерской, с отладочной сборкой: без оптимизаций, с именами функций и номерами строк, которые нужны отладчику и бесполезны пользователю. Мастерская - не мир. То, что выходит наружу, собирается по другим правилам.
Что нужно
cargo build - отладочная сборка. Компилятор торопится: не оптимизирует, сохраняет всё. Бинарник
tq в target/debug/ весит 21 мегабайт. Внутри - имена всех функций, номера строк исходника,
данные для отладчика. Пользователю ничего этого не нужно.
cargo build --release включает другой профиль. Компилятор перестаёт торопиться: применяет
оптимизации, убирает мёртвый код. Профиль можно настроить в корневом Cargo.toml - там задают,
что именно значит “релиз” для этого проекта. Два параметра дают наибольший эффект.
lto = true - link-time optimization. Обычно каждый крейт компилируется отдельно; компоновщик
соединяет объектные файлы после. При lto = true компилятор видит весь граф программы целиком
в момент компоновки: убирает функции, которые никто не вызывает, встраивает мелкие функции,
удаляет ветки, которые никогда не выполняются. Бинарник меньше, работает быстрее.
strip = true - выбрасывает символы отладчика из финального бинарника. Имена функций, пути к
исходникам, номера строк - всё это не нужно пользователю.
Постройка
В корневой Cargo.toml добавьте секцию после [workspace]:
[profile.release]
lto = true
strip = true
В Makefile добавьте цель в секцию BUILD, перед clean:
## release: build optimized stripped binaries
.PHONY: release
release:
@cargo build --release -p tq-cli -p tq-api
@ls -lh target/release/tq target/release/tq-api
Результат
$ make release
Finished `release` profile [optimized] target(s) in 53.72s
-rwxrwxr-x 1 user user 1.1M target/release/tq
-rwxrwxr-x 1 user user 1.7M target/release/tq-api
target/debug/tq весил 21 мегабайт. target/release/tq - 1.1. В двадцать раз меньше.
Отладочный бинарник - черновик с пометками на полях. Из мастерской выходит готовое изделие.
Готовый артефакт запускается без Rust:
$ ./target/release/tq list
$ ./target/release/tq-api
tasks.json сохраняется между запусками - данные из предыдущих глав никуда не делись.
make ci проверяет правильность. make release собирает то, что передают.
Полный код этой главы находится в
9-shippable/03-forged/.
Lore: что хранится в отладочной сборке
В отладочной сборке бинарник содержит секцию .debug_info - данные в формате DWARF. Там имена
переменных и функций, пути к файлам исходников, номера строк, типы. Отладчик (gdb, lldb)
читает эту секцию, чтобы показывать “ты остановился на строке 42 в store.rs” вместо “ты
остановился по адресу 0x4a3f12”. strip = true удаляет эту секцию; поведение программы не
меняется.
Можно удалить только часть: strip = "debuginfo" уберёт отладочные данные, но сохранит имена
символов - полезно, если нужно профилировать релизную сборку.
[profile.release] принимает много параметров: opt-level, codegen-units, panic, overflow-checks
и другие. Оптимальный набор зависит от задачи - встроенная система, серверное приложение и CLI
требуют разных компромиссов. Полный список с объяснениями - в
документации Cargo.