← На главную

Zig разделил сборку на configurer и maker, ускорив `--help` на 90%

30.05.2026 08:38 · hackernews

Эндрю Келли и команда Zig вкатили сразу несколько крупных изменений в основной бранч. Самый важный — они разделили сборку на два процесса: configurer и maker. Раньше build.zig и вся инфраструктура компилировались в один огромный процесс в Debug-режиме. Теперь build.zig собирается в маленький configurer (тоже Debug), который строит граф сборки и сериализует его в бинарный конфигурационный файл. Родительский процесс zig build кэширует этот файл и одновременно асинхронно компилирует maker — уже в Release-режиме. Maker запускается только когда конфиг готов и сам скомпилирован.

Результат впечатляет: zig build --help стал выполняться за 14.3 миллисекунды вместо 150. Это ускорение на 90% по времени, на 95% по инструкциям CPU и на 7% меньше потребление памяти. Причина в том, что build.zig логика больше не перезапускается при каждом вызове, если конфигурация не изменилась. Третьи инструменты вроде ZLS тоже смогут читать сериализованный конфиг, а не форкать раннер.

Основное ломающее изменение для разработчиков — run_cmd.addArgs(args) заменили на run_cmd.addPassthruArgs(). Скрипты больше не видят аргументы командной строки, но зато не пересобираются при их смене.

Мэттью Лагг починил инкрементальную компиляцию для LLVM backend. Раньше она работала только с собственным кодогенератором Zig, а теперь и с LLVM. Сама стадия LLVM Emit Object не ускорилась (там всё завязано на LLVM), но если в коде ошибки — компилятор теперь выдаёт их за миллисекунды, а не секунды. Работает через флаги -fincremental --watch в zig build. Баги обещают фиксить — фича считается стабильной, команда сама ей пользуется уже год.

Лагг также переписал систему разрешения типов — 30 тысяч строк кода ушло на рефакторинг. Типы теперь анализируются лениво: если поле типа никогда не инициализируется, компилятор на него даже не смотрит. Пример: раньше @compileError внутри структуры вылетал сразу, даже если к ней никто не обращался — теперь всё ок. Диагностика циклических зависимостей стала понятной — компилятор показывает точную цепочку: какой тип от какого зависит и в каком файле.

Джэйкоб обновил std.Io.Evented — это файберы (стековые корутины) для асинхронного I/O. Их можно включить через std.Io.Evented вместо std.Io.Threaded. Код приложения при этом не меняется — функция app остаётся идентичной. Zig-компилятор уже работает поверх Evented как с io_uring, так и с GCD, хотя производительность пока не отлажена.

Пакеты зависимостей теперь хранятся локально в папке zig-pkg рядом с проектом — можно редактировать вручную, менять на git-клон, а IDE будет видеть их для автодополнения. Глобальный кэш при этом сжимает отфильтрованные файлы обратно в .tar.gz. Ещё появился флаг --fork=[path] для zig build — он переопределяет все пакеты в дереве зависимостей на локальную папку с форком. Удобно чинить сломанный экосистемный код: zig build падает, ты подсовываешь форк через --fork, чинишь, и если не хочешь слать патч — просто работаешь дальше.

В Windows-бэкенде стандартная библиотека Zig всё активнее переходит с kernel32.dll на ntdll.dll. Пример с энтропией: многие проекты используют SystemFunction036 из advapi32.dll, который внутри грузит bcryptprimitives.dll и аллоцирует память — и может упасть при перегрузке системы (такое видели на CI Zig). Вместо этого Zig напрямую открывает \Device\CNG через NtOpenFile и читает 48 байт через NtDeviceIoControlFile — без лишних DLL и аллокаций. Второй пример — ReadFile и WriteFile. Zig теперь использует NtReadFile с APC-рутиной и NtDelayExecution вместо громоздких OVERLAPPED структур, что упрощает отмену операций ввода-вывода.

И последнее: проект по переходу libc на Zig-врапперы продолжается. Уже удалили 250 C-файлов (из ~2300). Функции вроде memcpy или strnlen теперь реализованы через std.mem и делят один compilation unit с остальным кодом — это даёт эффект LTO, но на уровне фронтенда, а не линкера. В будущем это позволит, например, заставить вызовы read и write из любой C-библиотеки работать через io_uring, подменяя I/O на уровне libc.

Читать оригинал →