В сущности я пытаюсь сделать следующее: создать ISO-файл вызовом внешней команды, а затем изменить тот же ISO другой командой, которая на самом деле не внешняя, но в рамках этого вопроса можно считать её внешней.
Вот как это реализовано в моём файле build.zig:
const staging_files = b.addWriteFiles();
// ...prepare the filesystem tree for the ISO...
const create_image = b.addSystemCommand(&.{ "xorriso", "-as", "mkisofs" });
// ...roughly thirty thousand invocations of `create_image.addArgs`...
create_image.addArg("-output");
const image_path = create_image.addOutputFileArg("brindlequasar.iso");
create_image.addDirectoryArg(
staging_files.getDirectory(),
);
const install_boot = b.addRunArtifact(limine_binary); // imagine `addSystemCommand` here
install_boot.addArg("bios-install");
install_boot.addFileArg(image_path);
(limine_binary получается компиляцией программы на C из пакетной зависимости, и она поддерживает только изменение файлов на месте.)
Следующий шаг — запустить QEMU, передав ему этот ISO-файл. Я думал, что для этого достаточно вызвать addFileArg с LazyPath моего ISO, сохранённым выше как image_path:
const launch_vm = b.addSystemCommand(&.{"qemu-system-x86_64"});
// ...other arguments omitted...
launch_vm.addArg("-cdrom");
launch_vm.addFileArg(image_path);
Однако работает это не так, как задумано. При чистой сборке, после удаления zig-cache, runner выполняет create_image и launch_vm, но пропускает install_boot. Чтобы получить ожидаемое поведение, приходится явно добавлять зависимость launch_vm от install_boot:
// FIXME: Required here, though I haven't fully understood the reason.
launch_vm.step.dependOn(&install_boot.step);
С этим дополнением всё вроде работает правильно, по крайней мере я ещё не нашёл способ это сломать, но сам подход кажется неправильным.
Изначально я предполагал, что LazyPath запоминает все шаги, которым его передают, позволяя runner упорядочить зависимости, но чтение реализации, похоже, это опровергает; насколько я вижу, тип хранит только один *Step, вероятно шаг, изначально создавший этот LazyPath. Дальнейшие поиски обнаружили комментарии документации, предполагающие, что изменение файла за LazyPath после создавшего его шага не поддерживается или как минимум выполняется мной неверно.
Итак, мои вопросы сводятся к следующему:
Верно ли я понимаю задуманное поведение?
Каким поддерживаемым способом менять этот созданный файл, не рискуя повредить кеш сборки или похожие механизмы?