jetzig/cli/commands/bundle.zig
Bob Farrell 09bbcebb56 Deployment bundle
This needs some work (and testing on Windows) but it solves simple cases
and provides a starting point for a more advanced bundler.
2024-03-20 23:14:51 +00:00

140 lines
4.9 KiB
Zig

const std = @import("std");
const builtin = @import("builtin");
const args = @import("args");
const util = @import("../util.zig");
/// Command line options for the `bundle` command.
pub const Options = struct {
optimize: enum { Debug, ReleaseFast, ReleaseSmall } = .ReleaseFast,
arch: enum { x86_64, aarch64, default } = .default,
os: enum { linux, macos, windows, default } = .default,
pub const meta = .{
.full_text =
\\Creates a deployment bundle.
\\
\\On Windows, `tar.exe` is used to generate a `.zip` file.
\\
\\On other operating systems, `tar` is used to generate a `.tar.gz` file.
\\
\\The deployment bundle contains a compiled executable with the `public/` and `static/`
\\directories included. This bundle can be copied to a deployment server, unpacked, and
\\launched in place.
,
.option_docs = .{
.optimize = "Set optimization level, must be one of { Debug, ReleaseFast, ReleaseSmall } (default: ReleaseFast)",
.arch = "Set build target CPU architecture, must be one of { x86_64, aarch64 } (default: Current CPU arch)",
.os = "Set build target operating system, must be one of { linux, macos, windows } (default: Current OS)",
},
};
};
/// Run the deployment bundle generator. Create an archive containing the Jetzig executable,
/// with `public/` and `static/` directories.
pub fn run(
allocator: std.mem.Allocator,
options: Options,
writer: anytype,
positionals: [][]const u8,
other_options: struct { help: bool },
) !void {
_ = positionals;
if (other_options.help) {
try args.printHelp(Options, "jetzig bundle", writer);
return;
}
std.debug.print("Compiling bundle...\n", .{});
var cwd = try util.detectJetzigProjectDir();
defer cwd.close();
const path = try cwd.realpathAlloc(allocator, ".");
defer allocator.free(path);
if (try util.locateExecutable(allocator, cwd, .{ .relative = true })) |executable| {
defer allocator.free(executable);
var tar_argv = std.ArrayList([]const u8).init(allocator);
defer tar_argv.deinit();
var install_argv = std.ArrayList([]const u8).init(allocator);
defer install_argv.deinit();
try install_argv.appendSlice(&[_][]const u8{ "zig", "build" });
switch (builtin.os.tag) {
.windows => try tar_argv.appendSlice(&[_][]const u8{
"tar.exe",
"-a",
"-c",
"-f",
"bundle.zip",
executable,
}),
else => try tar_argv.appendSlice(&[_][]const u8{
"tar",
"--transform=s,^,jetzig/,",
"--transform=s,^jetzig/zig-out/bin/,jetzig/,",
"-zcf",
"bundle.tar.gz",
executable,
}),
}
switch (options.optimize) {
.ReleaseFast => try install_argv.append("-Doptimize=ReleaseFast"),
.ReleaseSmall => try install_argv.append("-Doptimize=ReleaseSmall"),
.Debug => try install_argv.append("-Doptimize=Debug"),
}
var target_buf = std.ArrayList([]const u8).init(allocator);
defer target_buf.deinit();
try target_buf.append("-Dtarget=");
switch (options.arch) {
.x86_64 => try target_buf.append("x86_64"),
.aarch64 => try target_buf.append("aarch64"),
.default => try target_buf.append(@tagName(builtin.cpu.arch)),
}
try target_buf.append("-");
switch (options.os) {
.linux => try target_buf.append("linux"),
.macos => try target_buf.append("macos"),
.windows => try target_buf.append("windows"),
.default => try target_buf.append(@tagName(builtin.os.tag)),
}
const target = try std.mem.concat(allocator, u8, target_buf.items);
defer allocator.free(target);
try install_argv.append(target);
try install_argv.append("install");
var public_dir: ?std.fs.Dir = cwd.openDir("public", .{}) catch null;
defer if (public_dir) |*dir| dir.close();
var static_dir: ?std.fs.Dir = cwd.openDir("static", .{}) catch null;
defer if (static_dir) |*dir| dir.close();
if (public_dir != null) try tar_argv.append("public");
if (static_dir != null) try tar_argv.append("static");
try util.runCommand(allocator, path, install_argv.items);
try util.runCommand(allocator, path, tar_argv.items);
switch (builtin.os.tag) {
.windows => std.debug.print("Bundle `bundle.zip` generated successfully.", .{}),
else => std.debug.print("Bundle `bundle.tar.gz` generated successfully.", .{}),
}
util.printSuccess();
} else {
std.debug.print("Unable to locate compiled executable. Exiting.", .{});
util.printFailure();
std.os.exit(1);
}
}