master
  1pub const BuildOptions = struct {
  2    has_macos_sdk: bool,
  3    has_ios_sdk: bool,
  4    has_symlinks: bool,
  5};
  6
  7pub const Options = struct {
  8    target: std.Build.ResolvedTarget,
  9    optimize: std.builtin.OptimizeMode = .Debug,
 10    use_llvm: bool = true,
 11    use_lld: bool = false,
 12    strip: ?bool = null,
 13};
 14
 15pub fn addTestStep(b: *Build, prefix: []const u8, opts: Options) *Step {
 16    const target = opts.target.query.zigTriple(b.allocator) catch @panic("OOM");
 17    const optimize = @tagName(opts.optimize);
 18    const use_llvm = if (opts.use_llvm) "llvm" else "no-llvm";
 19    const use_lld = if (opts.use_lld) "lld" else "no-lld";
 20    if (opts.strip) |strip| {
 21        const s = if (strip) "strip" else "no-strip";
 22        const name = std.fmt.allocPrint(b.allocator, "test-{s}-{s}-{s}-{s}-{s}-{s}", .{
 23            prefix, target, optimize, use_llvm, use_lld, s,
 24        }) catch @panic("OOM");
 25        return b.step(name, "");
 26    }
 27    const name = std.fmt.allocPrint(b.allocator, "test-{s}-{s}-{s}-{s}-{s}", .{
 28        prefix, target, optimize, use_llvm, use_lld,
 29    }) catch @panic("OOM");
 30    return b.step(name, "");
 31}
 32
 33const OverlayOptions = struct {
 34    name: []const u8,
 35    asm_source_bytes: ?[]const u8 = null,
 36    c_source_bytes: ?[]const u8 = null,
 37    c_source_flags: []const []const u8 = &.{},
 38    cpp_source_bytes: ?[]const u8 = null,
 39    cpp_source_flags: []const []const u8 = &.{},
 40    objc_source_bytes: ?[]const u8 = null,
 41    objc_source_flags: []const []const u8 = &.{},
 42    objcpp_source_bytes: ?[]const u8 = null,
 43    objcpp_source_flags: []const []const u8 = &.{},
 44    zig_source_bytes: ?[]const u8 = null,
 45    pic: ?bool = null,
 46    strip: ?bool = null,
 47};
 48
 49pub fn addExecutable(b: *std.Build, base: Options, overlay: OverlayOptions) *Compile {
 50    return b.addExecutable(.{
 51        .name = overlay.name,
 52        .root_module = createModule(b, base, overlay),
 53        .use_llvm = base.use_llvm,
 54        .use_lld = base.use_lld,
 55    });
 56}
 57
 58pub fn addObject(b: *Build, base: Options, overlay: OverlayOptions) *Compile {
 59    return b.addObject(.{
 60        .name = overlay.name,
 61        .root_module = createModule(b, base, overlay),
 62        .use_llvm = base.use_llvm,
 63        .use_lld = base.use_lld,
 64    });
 65}
 66
 67pub fn addStaticLibrary(b: *Build, base: Options, overlay: OverlayOptions) *Compile {
 68    return b.addLibrary(.{
 69        .linkage = .static,
 70        .name = overlay.name,
 71        .root_module = createModule(b, base, overlay),
 72        .use_llvm = base.use_llvm,
 73        .use_lld = base.use_lld,
 74    });
 75}
 76
 77pub fn addSharedLibrary(b: *Build, base: Options, overlay: OverlayOptions) *Compile {
 78    return b.addLibrary(.{
 79        .linkage = .dynamic,
 80        .name = overlay.name,
 81        .root_module = createModule(b, base, overlay),
 82        .use_llvm = base.use_llvm,
 83        .use_lld = base.use_lld,
 84    });
 85}
 86
 87fn createModule(b: *Build, base: Options, overlay: OverlayOptions) *Build.Module {
 88    const write_files = b.addWriteFiles();
 89
 90    const mod = b.createModule(.{
 91        .target = base.target,
 92        .optimize = base.optimize,
 93        .root_source_file = rsf: {
 94            const bytes = overlay.zig_source_bytes orelse break :rsf null;
 95            const name = b.fmt("{s}.zig", .{overlay.name});
 96            break :rsf write_files.add(name, bytes);
 97        },
 98        .pic = overlay.pic,
 99        .strip = if (base.strip) |s| s else overlay.strip,
100    });
101
102    if (overlay.objcpp_source_bytes) |bytes| {
103        mod.addCSourceFile(.{
104            .file = write_files.add("a.mm", bytes),
105            .flags = overlay.objcpp_source_flags,
106        });
107    }
108    if (overlay.objc_source_bytes) |bytes| {
109        mod.addCSourceFile(.{
110            .file = write_files.add("a.m", bytes),
111            .flags = overlay.objc_source_flags,
112        });
113    }
114    if (overlay.cpp_source_bytes) |bytes| {
115        mod.addCSourceFile(.{
116            .file = write_files.add("a.cpp", bytes),
117            .flags = overlay.cpp_source_flags,
118        });
119    }
120    if (overlay.c_source_bytes) |bytes| {
121        mod.addCSourceFile(.{
122            .file = write_files.add("a.c", bytes),
123            .flags = overlay.c_source_flags,
124        });
125    }
126    if (overlay.asm_source_bytes) |bytes| {
127        mod.addAssemblyFile(write_files.add("a.s", bytes));
128    }
129
130    return mod;
131}
132
133pub fn addRunArtifact(comp: *Compile) *Run {
134    const b = comp.step.owner;
135    const run = b.addRunArtifact(comp);
136    run.skip_foreign_checks = true;
137    return run;
138}
139
140pub fn addCSourceBytes(comp: *Compile, bytes: []const u8, flags: []const []const u8) void {
141    const b = comp.step.owner;
142    const file = WriteFile.create(b).add("a.c", bytes);
143    comp.root_module.addCSourceFile(.{ .file = file, .flags = flags });
144}
145
146pub fn addCppSourceBytes(comp: *Compile, bytes: []const u8, flags: []const []const u8) void {
147    const b = comp.step.owner;
148    const file = WriteFile.create(b).add("a.cpp", bytes);
149    comp.root_module.addCSourceFile(.{ .file = file, .flags = flags });
150}
151
152pub fn addAsmSourceBytes(comp: *Compile, bytes: []const u8) void {
153    const b = comp.step.owner;
154    const actual_bytes = std.fmt.allocPrint(b.allocator, "{s}\n", .{bytes}) catch @panic("OOM");
155    const file = WriteFile.create(b).add("a.s", actual_bytes);
156    comp.root_module.addAssemblyFile(file);
157}
158
159pub fn expectLinkErrors(comp: *Compile, test_step: *Step, expected_errors: Compile.ExpectedCompileErrors) void {
160    comp.expect_errors = expected_errors;
161    const bin_file = comp.getEmittedBin();
162    bin_file.addStepDependencies(test_step);
163}
164
165const std = @import("std");
166
167const Build = std.Build;
168const Compile = Step.Compile;
169const Run = Step.Run;
170const Step = Build.Step;
171const WriteFile = Step.WriteFile;