Skip to content

Instantly share code, notes, and snippets.

@mitchellh
Created May 27, 2023 18:16
Show Gist options
  • Select an option

  • Save mitchellh/0ee168fb34915e96159b558b89c9a74b to your computer and use it in GitHub Desktop.

Select an option

Save mitchellh/0ee168fb34915e96159b558b89c9a74b to your computer and use it in GitHub Desktop.

Revisions

  1. mitchellh created this gist May 27, 2023.
    44 changes: 44 additions & 0 deletions LibtoolStep.zig
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,44 @@
    //! A zig builder step that runs "libtool" against a list of libraries
    //! in order to create a single combined static library.
    const LibtoolStep = @This();

    const std = @import("std");
    const Step = std.build.Step;
    const RunStep = std.build.RunStep;
    const FileSource = std.build.FileSource;

    pub const Options = struct {
    /// The name of this step.
    name: []const u8,

    /// The filename (not the path) of the file to create. This will
    /// be placed in a unique hashed directory. Use out_path to access.
    out_name: []const u8,

    /// Library files (.a) to combine.
    sources: []FileSource,
    };

    /// The step to depend on.
    step: *Step,

    /// The output file from the libtool run.
    output: FileSource,

    /// Run libtool against a list of library files to combine into a single
    /// static library.
    pub fn create(b: *std.Build, opts: Options) *LibtoolStep {
    const self = b.allocator.create(LibtoolStep) catch @panic("OOM");

    const run_step = RunStep.create(b, b.fmt("libtool {s}", .{opts.name}));
    run_step.addArgs(&.{ "libtool", "-static", "-o" });
    const output = run_step.addOutputFileArg(opts.out_name);
    for (opts.sources) |source| run_step.addFileSourceArg(source);

    self.* = .{
    .step = &run_step.step,
    .output = output,
    };

    return self;
    }
    42 changes: 42 additions & 0 deletions LipoStep.zig
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,42 @@
    //! A zig builder step that runs "lipo" on two binaries to create
    //! a universal binary.
    const LipoStep = @This();

    const std = @import("std");
    const Step = std.build.Step;
    const RunStep = std.build.RunStep;
    const FileSource = std.build.FileSource;

    pub const Options = struct {
    /// The name of the xcframework to create.
    name: []const u8,

    /// The filename (not the path) of the file to create.
    out_name: []const u8,

    /// Library file (dylib, a) to package.
    input_a: FileSource,
    input_b: FileSource,
    };

    step: *Step,

    /// Resulting binary
    output: FileSource,

    pub fn create(b: *std.Build, opts: Options) *LipoStep {
    const self = b.allocator.create(LipoStep) catch @panic("OOM");

    const run_step = RunStep.create(b, b.fmt("lipo {s}", .{opts.name}));
    run_step.addArgs(&.{ "lipo", "-create", "-output" });
    const output = run_step.addOutputFileArg(opts.out_name);
    run_step.addFileSourceArg(opts.input_a);
    run_step.addFileSourceArg(opts.input_b);

    self.* = .{
    .step = &run_step.step,
    .output = output,
    };

    return self;
    }
    59 changes: 59 additions & 0 deletions XCFrameworkStep.zig
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,59 @@
    //! A zig builder step that runs "swift build" in the context of
    //! a Swift project managed with SwiftPM. This is primarily meant to build
    //! executables currently since that is what we build.
    const XCFrameworkStep = @This();

    const std = @import("std");
    const Step = std.build.Step;
    const RunStep = std.build.RunStep;
    const FileSource = std.build.FileSource;

    pub const Options = struct {
    /// The name of the xcframework to create.
    name: []const u8,

    /// The path to write the framework
    out_path: []const u8,

    /// Library file (dylib, a) to package.
    library: std.build.FileSource,

    /// Path to a directory with the headers.
    headers: std.build.FileSource,
    };

    step: *Step,

    pub fn create(b: *std.Build, opts: Options) *XCFrameworkStep {
    const self = b.allocator.create(XCFrameworkStep) catch @panic("OOM");

    // We have to delete the old xcframework first since we're writing
    // to a static path.
    const run_delete = run: {
    const run = RunStep.create(b, b.fmt("xcframework delete {s}", .{opts.name}));
    run.has_side_effects = true;
    run.addArgs(&.{ "rm", "-rf", opts.out_path });
    break :run run;
    };

    // Then we run xcodebuild to create the framework.
    const run_create = run: {
    const run = RunStep.create(b, b.fmt("xcframework {s}", .{opts.name}));
    run.has_side_effects = true;
    run.addArgs(&.{ "xcodebuild", "-create-xcframework" });
    run.addArg("-library");
    run.addFileSourceArg(opts.library);
    run.addArg("-headers");
    run.addFileSourceArg(opts.headers);
    run.addArg("-output");
    run.addArg(opts.out_path);
    break :run run;
    };
    run_create.step.dependOn(&run_delete.step);

    self.* = .{
    .step = &run_create.step,
    };

    return self;
    }