zig/std/special/build_runner.zig

150 lines
5.1 KiB
Zig
Raw Normal View History

const root = @import("@build");
const std = @import("std");
const io = std.io;
const fmt = std.fmt;
2017-04-04 12:17:24 +08:00
const os = std.os;
const Builder = std.build.Builder;
const mem = std.mem;
const ArrayList = std.ArrayList;
2017-04-03 08:44:04 +08:00
error InvalidArgs;
2017-04-04 12:17:24 +08:00
pub fn main() -> %void {
var arg_it = os.args();
// TODO use a more general purpose allocator here
var inc_allocator = %%mem.IncrementingAllocator.init(20 * 1024 * 1024);
defer inc_allocator.deinit();
const allocator = &inc_allocator.allocator;
// skip my own exe name
_ = arg_it.skip();
const zig_exe = %return unwrapArg(arg_it.next(allocator) ?? {
%%io.stderr.printf("Expected first argument to be path to zig compiler\n");
return error.InvalidArgs;
});
const build_root = %return unwrapArg(arg_it.next(allocator) ?? {
%%io.stderr.printf("Expected second argument to be build root directory path\n");
return error.InvalidArgs;
});
const cache_root = %return unwrapArg(arg_it.next(allocator) ?? {
%%io.stderr.printf("Expected third argument to be cache root directory path\n");
return error.InvalidArgs;
});
var builder = Builder.init(allocator, zig_exe, build_root, cache_root);
defer builder.deinit();
var targets = ArrayList([]const u8).init(allocator);
var prefix: ?[]const u8 = null;
while (arg_it.next(allocator)) |err_or_arg| {
const arg = %return unwrapArg(err_or_arg);
if (mem.startsWith(u8, arg, "-D")) {
const option_contents = arg[2..];
if (option_contents.len == 0) {
%%io.stderr.printf("Expected option name after '-D'\n\n");
return usage(&builder, false, &io.stderr);
}
if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| {
const option_name = option_contents[0..name_end];
const option_value = option_contents[name_end + 1..];
if (builder.addUserInputOption(option_name, option_value))
return usage(&builder, false, &io.stderr);
} else {
if (builder.addUserInputFlag(option_contents))
return usage(&builder, false, &io.stderr);
}
} else if (mem.startsWith(u8, arg, "-")) {
if (mem.eql(u8, arg, "--verbose")) {
builder.verbose = true;
} else if (mem.eql(u8, arg, "--help")) {
return usage(&builder, false, &io.stdout);
} else if (mem.eql(u8, arg, "--prefix")) {
prefix = %return unwrapArg(arg_it.next(allocator) ?? {
%%io.stderr.printf("Expected argument after --prefix\n\n");
return usage(&builder, false, &io.stderr);
});
} else {
%%io.stderr.printf("Unrecognized argument: {}\n\n", arg);
return usage(&builder, false, &io.stderr);
}
} else {
%%targets.append(arg);
}
}
builder.setInstallPrefix(prefix);
root.build(&builder);
if (builder.validateUserInputDidItFail())
return usage(&builder, true, &io.stderr);
builder.make(targets.toSliceConst()) %% |err| {
if (err == error.InvalidStepName) {
return usage(&builder, true, &io.stderr);
}
return err;
};
}
fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) -> %void {
// run the build script to collect the options
if (!already_ran_build) {
builder.setInstallPrefix(null);
root.build(builder);
}
// This usage text has to be synchronized with src/main.cpp
%%out_stream.printf(
\\Usage: {} build [steps] [options]
\\
\\Steps:
\\
, builder.zig_exe);
const allocator = builder.allocator;
for (builder.top_level_steps.toSliceConst()) |top_level_step| {
%%out_stream.printf(" {s22} {}\n", top_level_step.step.name, top_level_step.description);
}
%%out_stream.write(
\\
\\General Options:
\\ --help Print this help and exit
\\ --build-file [file] Override path to build.zig
\\ --cache-dir [path] Override path to cache directory
\\ --verbose Print commands before executing them
\\ --debug-build-verbose Print verbose debugging information for the build system itself
\\ --prefix [prefix] Override default install prefix
\\
\\Project-Specific Options:
\\
);
if (builder.available_options_list.len == 0) {
%%out_stream.printf(" (none)\n");
} else {
for (builder.available_options_list.toSliceConst()) |option| {
const name = %%fmt.allocPrint(allocator,
" -D{}=({})", option.name, Builder.typeIdName(option.type_id));
defer allocator.free(name);
%%out_stream.printf("{s24} {}\n", name, option.description);
}
}
if (out_stream == &io.stderr)
return error.InvalidArgs;
}
fn unwrapArg(arg: %[]u8) -> %[]u8 {
return arg %% |err| {
%%io.stderr.printf("Unable to parse command line: {}\n", err);
return err;
};
}