openlang

在后续步骤中修改生成的文件

我主要想做的是这样,通过外部命令创建 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 程序得到的,它只支持直接修改原文件。)

接下来我想把这个 ISO 文件作为参数传给 QEMU 并运行。我以为只要调用 addFileArg,传入 ISO 的 LazyPath 就行,上面把它存为 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 后,构建程序执行了 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 会记住接收它的所有步骤,让构建程序安排依赖,但看了实现似乎并非如此,我能看出这个类型只存一个 *Step,应该就是最初创建这个 LazyPath 的步骤。继续找又看到了几处文档注释,似乎说明生成步骤之后再修改 LazyPath 指向的文件是不受支持的,或者至少我现在的做法不对。

所以我的问题归结为下面这些。

  • 我对预期行为的理解正确吗?

  • 有什么受支持的办法可以修改这个生成的文件,又不会冒破坏构建缓存或类似机制的风险?

从英语翻译查看原文

后续讨论 2

顺着彼此的依据读下去
  1. 固定链接

    没有什么会阻止修改通过 addFileArg 传入的输入路径,但这个 API 不记录修改步骤,所以它们的依赖需要你自己添加。

    另一个办法是写个小包装脚本,在调用工具之前先把输入文件复制到输出位置,这样每次修改都会得到一个新的惰性路径(lazy path)。

    从英语翻译查看原文

同一个问题的其他角度

  1. 减少 docker-compose 的控制台输出

    在开发环境里用 docker-compose up 启动所有服务时,我的几个容器会输出几百行又几百行内容。有没有方便的办法过滤这些输出,或者更好一些,让这些服务在 docker-compose up 运行时不要写到标准输出?

    回复 3最近活动 bash
  2. 能否用 D 代替 C 编写 Python 扩展模块?

    看来 D 能与 C 链接。我想用 D 编写 Python 扩展模块。我是不是漏掉了什么原因,导致这种方法根本无法运行?

    回复 2最近活动 d
  3. 通过 Nix 声明 Micro 插件?🤔

    python 可以这样写。 Python.withPackages (q: with q; [ fastapi ]) Micro 编辑器有类似的机制吗? 能不能把 micro 编辑器的软件包和插件一起指定?:thinking: 那样会方便很多。

    回复 3最近活动 nix