1

有没有办法将 zig 编译器用作 zig 中的库?在查看 zig 文档、问题和互联网后,我找不到这个问题的答案。

在其中一个问题中,据说目前可以做到这一点,但我找不到任何关于如何做到这一点的例子。

4

1 回答 1

1

由于难以包含具有复杂构建要求的库,因此目前将 zig 编译器用作库并非易事。一旦发布了包管理器,它可能会变得容易得多。

现在,我建议将 zig 编译器作为系统命令调用

var zig = std.ChildProcess.init(&.{"zig", "build-exe", "demo.zig"}, allocator);
try zig.spawn();
try zig.wait();

但是,如果您真的想要,这里是如何使用 zig0.9.0-dev.1611+f3ba72cf5作为库

在包管理器发布之前不这样做的原因:

  • 这需要弄乱您的 build.zig 文件,并且您的 build.zig 文件必须与编译器的 build.zig 文件保持同步
  • 由于 stage1 zig 编译器的当前速度较慢,这将使您的项目构建非常缓慢
  • 这个例子没有展示如何在它制作的 zig 包中启用 stage1 和 LLVM 扩展。启用 stage1 和 LLVM 扩展将需要查看 zig 的 build.zig 文件并复制有关链接库和包含目录和 c 源代码的内容。

这个 build.zig 是通过在 zig 编译器的build.zig中找到 .addOption 的所有实例并在我们自己的 build.zig 文件中重新创建它们来制作的。

// build.zig

const std = @import("std");

pub fn build(b: *std.build.Builder) !void {
    const target = b.standardTargetOptions(.{});

    const mode = b.standardReleaseOptions();

    const exe_options = b.addOptions();

    const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse 4;
    const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false;

    const enable_logging = b.option(bool, "log", "Whether to enable logging") orelse false;
    const enable_link_snapshots = b.option(bool, "link-snapshot", "Whether to enable linker state snapshots") orelse false;

    exe_options.addOption(u32, "mem_leak_frames", mem_leak_frames);
    exe_options.addOption(bool, "skip_non_native", skip_non_native);
    exe_options.addOption(bool, "have_llvm", false);
    exe_options.addOption(bool, "llvm_has_m68k", false);
    exe_options.addOption(bool, "llvm_has_csky", false);
    exe_options.addOption(bool, "llvm_has_ve", false);
    exe_options.addOption(bool, "llvm_has_arc", false);

    const version = "0.0.0";

    exe_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version));

    const semver = try std.SemanticVersion.parse(version);
    exe_options.addOption(std.SemanticVersion, "semver", semver);

    exe_options.addOption(bool, "enable_logging", enable_logging);
    exe_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);
    exe_options.addOption(bool, "enable_tracy", false);
    exe_options.addOption(bool, "enable_tracy_callstack", false);
    exe_options.addOption(bool, "enable_tracy_allocation", false);
    exe_options.addOption(bool, "is_stage1", false);
    exe_options.addOption(bool, "omit_stage2", false);

    const exe = b.addExecutable("tmp", "sample.zig");
    exe.setTarget(target);
    exe.setBuildMode(mode);
    exe.addOptions("build_options", exe_options);
    exe.addPackage(.{
        .name = "zig",
        .path = .{ .path = "src/main.zig" },
        .dependencies = &[_]std.build.Pkg{
            .{ .name = "build_options", .path = exe_options.getSource() },
        },
    });
    exe.install();

    const run_cmd = exe.run();
    run_cmd.step.dependOn(b.getInstallStep());
    if (b.args) |args| {
        run_cmd.addArgs(args);
    }

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
}
// sample.zig

const zig = @import("zig");

pub fn main() !void {
    return zig.main(); // just calls into the zig compiler main function. you'll have to look into how https://github.com/ziglang/zig/blob/master/src/main.zig works in order to do more complicated stuff.
}

注意:我建议使用 -Dskip-non-native 构建它,否则由于当前 stage1 编译器的速度,构建它需要很长时间

zig build run -Dskip-non-native -- build-exe demo.zig

于 2021-11-11T20:29:30.527 回答