Путь установки не проходил целиком никто, и потому flang emit --target c не работал НИ У ОДНОГО поставившего язык
Все проверки инструмента гоняли двоичный там, где он собран, — рядом с его собственными исходниками. Поставивший из brew или asdf оказывается в другом месте: у него есть bin/flang, lib/*.a, include/*.h и больше ничего. Разница в этом «больше ничего» стоила команде flang emit --target c работоспособности у всех установленных пользователей, и ни один тест этого не видел, потому что ни один тест не раскладывал файлы так, как их раскладывает формула.
Чем подтверждено. Прогон 19 августа 2026, ветка work/adr-pakety от work/zelenyy-stvol. Файлы разложены во временном каталоге ровно так, как их кладёт install формулы (bin, lib, include), и вызвана печать:
- как ставит формула сегодня →
flang emit: не найдены ИСХОДНИКИ рантайма C, код 2; - плюс копии
flang_runtime.{c,h}из релизного архива вshare/flang/c→ та же ошибка, код 2; - плюс рукописные
flang/src/emit/c/{flang_runtime.c,flang_runtime.h, flang_cli.c,flang_repl.c}вshare/flang/c→ печать прошла, 6 файлов, 267 804 байта, код 0.
Пункт 2 — суть беды. Наверху архива лежат напечатанные копии тех же четырёх имён: у них первой строкой стоит шапка «Сгенерировано flang», и печать их отвергает по делу — приписать шапку второй раз значило бы соврать о происхождении файла. То есть человеку взять годные файлы было неоткуда: в архиве их не было вовсе.
Беда двойная, и одной правкой упаковки не чинится
- в релизном архиве рукописного рантайма нет —
scripts/build-release-c.mjsклал только напечатанное; - формула и плагин не кладут ничего в
share/flang/c— а двоичный ищет именно там (emit_runtime_dir, третье место после--runtimeи$FLANG_RUNTIME_DIR).
Починено обоими концами: скрипт релиза кладёт рукописные исходники отдельным каталогом runtime-c/ (отдельным — потому что имена совпадают с напечатанными и в одном каталоге они затёрли бы друг друга), а обе упаковки переносят его в share/flang/c. Имя каталога живёт в scripts/release-layout.mjs, а не тремя строками в трёх файлах: та же развилка с именем бинарника уже расходилась молча и оставляла релиз несобираемым.
Почему это не поймала ни одна проверка — и что теперь её ловит
Проверки были, и их было много: сборка релиза без Node, прогон бинарника, человеческие команды, страница руководства. Все они запускали бинарник в каталоге сборки, где рядом лежит всё дерево. Проверка, которая ловит этот класс, обязана делать ровно одно, чего не делала ни одна: разложить файлы как упаковка и позвать команду из получившегося префикса.
Заведены две: в scripts/build-release-c.mjs (строит настоящий префикс из только что собранного архива и печатает из него) и в flang/test/self-bootstrap.test.mjs («установленный flang печатает в C»). Вторая проверяет и обратную сторону — что без share/flang/c печать отказывает: иначе первая проходила бы и на бинарнике, нашедшем рантайм где-то ещё, и не сторожила бы ничего.
Признак класса
За один заход владельца одна команда подвела четырежды, и общее у всех четырёх одно: двоичный расходится с версией для Node в мелочи, и человек встречает расхождение как поломку.
- каталог из
--outне заводился (Node заводит), а отказ винил первый файл рантайма — человек читал это как «сломан рантайм» и для того текста читал верно; - после успешной печати выводились четыре строки про устройство инструмента, включая число параметров чужой программы, вшитой в двоичный;
- рантайма не было в архиве (эта заметка);
flang testне печатал полученное значение, хотя посчитал его — без него узнать о расхождении было нельзя.
Признак, по которому такое ищется заранее: двоичный знает больше, чем говорит, или делает меньше, чем делает Node, и молчит об этом. Расхождение в ФОРМАТЕ (JSON против прозы) сюда не относится — это решение, и оно названо.
Что осталось расхождением и почему не чинится
Померено на одних и тех же входах (годная программа, ошибка типов, неразобранный файл, недоказанная тотальность, сорвавшийся пример, вызовы run и emit):
flang emitу двоичного печатает программу с ошибкой типов кодом 0, где Node отказывает. Чинить проверкой перед печатью нельзя:flang checkна самом компиляторе у двоичного не проходит (исчерпывает предел шагов — см. bootstrap-circle-is-broken-but-the-binary-cannot-check-itself), и печать самого себя стала бы невозможна. Названо в справке командой, а не умолчано.emitбез--outотказывает, где Node печатает JSON всех файлов в стандартный вывод. У двоичного для этого есть--file имя; отказ говорит, что делать.run --argsберёт только плоский объект скаляров:{"сп":[2,3,4]}отвергается кодом 2, Node считает.check,test,runпечатают прозу вместо JSON — решение, а не беда.
Чем ограничено. Всё измерено на одной машине (Linux 7.0.0, cc 15.2.0) и на дереве 0.5.0+. Сам brew здесь не установлен: правки формулы разобраны как Ruby-текст глазами, а прогнан эквивалент её шагов вручную.
Связано: bootstrap-circle-is-broken-but-the-binary-cannot-check-itself, the-installed-binary-is-a-named-subset, cli-help-diverges-between-the-two-implementations, a-tool-that-explains-itself-instead-of-the-persons-work