177 lines
6.6 KiB
Zig
177 lines
6.6 KiB
Zig
const std = @import("std");
|
|
const builtin = @import("builtin");
|
|
const Builder = @import("Builder.zig");
|
|
const Target = @import("target.zig").Target;
|
|
|
|
const default_zig_path = "zig";
|
|
|
|
var args: []const [:0]u8 = undefined;
|
|
var arg_i: usize = 1;
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
pub const allocator = gpa.allocator();
|
|
|
|
pub fn main() !void {
|
|
defer _ = gpa.deinit();
|
|
|
|
args = try std.process.argsAlloc(allocator);
|
|
defer std.process.argsFree(allocator, args);
|
|
|
|
if (args.len == 1) return;
|
|
|
|
if (std.mem.eql(u8, args[arg_i], "build")) {
|
|
arg_i += 1;
|
|
var builder = Builder{};
|
|
var steps = std.ArrayList([]const u8).init(allocator);
|
|
var build_args = std.ArrayList([]const u8).init(allocator);
|
|
|
|
while (arg_i < args.len) : (arg_i += 1) {
|
|
if (argOption("-zig-path")) |value| {
|
|
builder.zig_path = value;
|
|
} else if (std.mem.eql(u8, args[arg_i], "--serve")) {
|
|
if (builder.target == null) builder.target = .wasm32;
|
|
if (builder.target.? != .wasm32) {
|
|
std.log.err("--serve requires -target=wasm32", .{});
|
|
try printHelp(.build);
|
|
std.os.exit(1);
|
|
}
|
|
builder.serve = true;
|
|
} else if (argOption("-target")) |value| {
|
|
builder.target = Target.parse(value) orelse {
|
|
std.log.err("invalid target '{s}'", .{args[arg_i]});
|
|
try printHelp(.build);
|
|
std.os.exit(1);
|
|
};
|
|
} else if (argOption("-listen-port")) |value| {
|
|
builder.listen_port = std.fmt.parseInt(u16, value, 10) catch {
|
|
std.log.err("invalid port '{s}'", .{args[arg_i]});
|
|
try printHelp(.build);
|
|
std.os.exit(1);
|
|
};
|
|
} else if (argOption("-watch-path")) |value| {
|
|
var paths = std.mem.split(u8, value, ",");
|
|
builder.watch_paths = try allocator.alloc([]const u8, std.mem.count(u8, value, ",") + 1);
|
|
for (0..255) |i| {
|
|
const path = paths.next() orelse break;
|
|
builder.watch_paths.?[i] = std.mem.trim(u8, path, &std.ascii.whitespace);
|
|
}
|
|
} else if (argOption("-optimize")) |value| {
|
|
builder.optimize = std.meta.stringToEnum(std.builtin.OptimizeMode, value) orelse {
|
|
std.log.err("invalid optimize mode '{s}'", .{args[arg_i]});
|
|
try printHelp(.build);
|
|
std.os.exit(1);
|
|
};
|
|
} else if (std.mem.eql(u8, args[arg_i], "--")) {
|
|
arg_i += 1;
|
|
while (arg_i < args.len) : (arg_i += 1) {
|
|
try build_args.append(args[arg_i]);
|
|
}
|
|
} else {
|
|
try steps.append(args[arg_i]);
|
|
}
|
|
}
|
|
|
|
builder.steps = try steps.toOwnedSlice();
|
|
builder.zig_build_args = try build_args.toOwnedSlice();
|
|
|
|
return builder.run();
|
|
} else if (std.mem.eql(u8, args[arg_i], "help")) {
|
|
arg_i += 1;
|
|
var subcommand = SubCommand.help;
|
|
|
|
if (arg_i < args.len) {
|
|
if (std.mem.eql(u8, args[arg_i], "build")) {
|
|
subcommand = .build;
|
|
} else {
|
|
std.log.err("unknown command name '{s}'", .{args[arg_i]});
|
|
try printHelp(.help);
|
|
std.os.exit(1);
|
|
}
|
|
}
|
|
return printHelp(subcommand);
|
|
} else {
|
|
std.log.err("invalid command '{s}'", .{args[arg_i]});
|
|
try printHelp(.help);
|
|
std.os.exit(1);
|
|
}
|
|
}
|
|
|
|
pub const SubCommand = enum {
|
|
build,
|
|
help,
|
|
};
|
|
|
|
fn printHelp(subcommand: SubCommand) !void {
|
|
const stdout = std.io.getStdOut();
|
|
switch (subcommand) {
|
|
.build => {
|
|
try stdout.writeAll(
|
|
\\Usage:
|
|
\\ mach build [steps] [options] [-- [zig-build-options]]
|
|
\\
|
|
\\General Options:
|
|
\\
|
|
\\ -zig-path [path] Override path to zig binary
|
|
\\
|
|
\\ -target [target] The CPU architecture and OS to build for
|
|
\\ Default is native target
|
|
\\ Supported targets:
|
|
\\ linux-x86_64, linux-aarch64,
|
|
\\ macos-x86_64, macos-aarch64,
|
|
\\ windows-x86_64, windows-aarch64,
|
|
\\ wasm32,
|
|
\\
|
|
\\ -optimize [optimize] Prioritize performance, safety, or binary size
|
|
\\ Default is Debug
|
|
\\ Supported values:
|
|
\\ Debug
|
|
\\ ReleaseSafe
|
|
\\ ReleaseFast
|
|
\\ ReleaseSmall
|
|
\\
|
|
\\Serve Options:
|
|
\\
|
|
\\ --serve Starts a development server
|
|
\\ for testing WASM applications/games
|
|
\\
|
|
\\ -listen-port [port] The development server port
|
|
\\
|
|
\\ -watch-path [paths] Watches for changes in specified directory
|
|
\\ and automatically builds and reloads
|
|
\\ development server
|
|
\\ Separate each path with comma (,)
|
|
\\
|
|
\\
|
|
);
|
|
},
|
|
.help => {
|
|
try stdout.writeAll(
|
|
\\Usage:
|
|
\\ mach [command]
|
|
\\
|
|
\\Commands:
|
|
\\ build Build current project
|
|
\\ help Print this mesage or the help of the given command
|
|
\\
|
|
\\
|
|
);
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn argOption(name: []const u8) ?[]const u8 {
|
|
const cmd_arg = args[arg_i];
|
|
if (std.mem.startsWith(u8, cmd_arg, name)) {
|
|
if (cmd_arg.len > name.len + 1 and cmd_arg[name.len] == '=') {
|
|
return cmd_arg[name.len + 1 ..];
|
|
} else if (cmd_arg.len == name.len) {
|
|
arg_i += 1;
|
|
if (arg_i < args.len) {
|
|
return args[arg_i];
|
|
} else {
|
|
std.log.err("expected value after '{s}' option", .{cmd_arg});
|
|
std.os.exit(1);
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|