diff --git a/build.zig b/build.zig index d39bc69..e591da6 100644 --- a/build.zig +++ b/build.zig @@ -22,6 +22,7 @@ pub fn build(b: *std.Build) !void { .root_source_file = b.path("src/jetzig.zig"), .target = target, .optimize = optimize, + .use_llvm = false, }); const mime_module = try GenerateMimeTypes.generateMimeModule(b); @@ -132,6 +133,8 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn const target = exe.root_module.resolved_target orelse @panic("Unable to detect compile target."); const optimize = exe.root_module.optimize orelse .Debug; + exe.use_llvm = exe.use_llvm orelse (optimize != .Debug); + if (optimize != .Debug) exe.linkLibC(); const environment = b.option( @@ -242,12 +245,14 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn const routes_module = b.createModule(.{ .root_source_file = routes_file_path }); routes_module.addImport("jetzig", jetzig_module); exe.root_module.addImport("routes", routes_module); + exe.step.dependOn(&run_routes_file_cmd.step); const exe_static_routes = b.addExecutable(.{ .name = "static", .root_source_file = jetzig_dep.path("src/compile_static_routes.zig"), .target = target, .optimize = optimize, + .use_llvm = exe.use_llvm, }); const main_module = b.createModule(.{ .root_source_file = b.path("src/main.zig") }); @@ -356,6 +361,7 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn .root_source_file = jetzig_dep.path("src/commands/routes.zig"), .target = target, .optimize = optimize, + .use_llvm = exe.use_llvm, }); const auth_user_create_step = b.step("jetzig:auth:user:create", "List all routes in your app"); @@ -364,6 +370,7 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn .root_source_file = jetzig_dep.path("src/commands/auth.zig"), .target = target, .optimize = optimize, + .use_llvm = exe.use_llvm, }); exe_auth.root_module.addImport("jetquery", jetquery_module); exe_auth.root_module.addImport("jetzig", jetzig_module); @@ -385,6 +392,7 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn .root_source_file = jetzig_dep.path("src/commands/database.zig"), .target = target, .optimize = optimize, + .use_llvm = exe.use_llvm, }); exe_database.root_module.addImport("jetquery", jetquery_module); exe_database.root_module.addImport("jetzig", jetzig_module); diff --git a/build.zig.zon b/build.zig.zon index 7378f99..e239d14 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -7,7 +7,8 @@ .hash = "1220d0e8734628fd910a73146e804d10a3269e3e7d065de6bb0e3e88d5ba234eb163", }, .jetkv = .{ - .path = "../jetkv", + .url = "https://github.com/jetzig-framework/jetkv/archive/9d754e552e7569239a900ed9e0f313a0554ed2d3.tar.gz", + .hash = "122013f8596bc615990fd7771c833cab4d2959ecac8d05c4f6c973aa46624e43afea", }, .jetquery = .{ .url = "https://github.com/jetzig-framework/jetquery/archive/ec99c0accedbf783c9836f096e2381e4d8b396eb.tar.gz", @@ -26,7 +27,8 @@ .hash = "12205019ce2bc2e08c76352ea37a14600d412e5e0ecdd7ddd27b4e83a62f37d8ba94", }, .httpz = .{ - .path = "../http.zig", + .url = "https://github.com/karlseguin/http.zig/archive/2e837c7f119e9d858c1372c014ac7c76af3b9f3a.tar.gz", + .hash = "122024b75ff22193f8631a78f32ac0e9f30d37a43fc0e16313e50b92fb822a38c1e4", }, .smtp_client = .{ .url = "https://github.com/karlseguin/smtp_client.zig/archive/5163c66cc42cdd93176a6b1cad45f3db3a291a6a.tar.gz", diff --git a/cli/commands/bundle.zig b/cli/commands/bundle.zig index cf4f0af..e689e56 100644 --- a/cli/commands/bundle.zig +++ b/cli/commands/bundle.zig @@ -149,7 +149,7 @@ pub fn run( const tmpdir_real_path = try tmpdir.realpathAlloc(allocator, "."); defer allocator.free(tmpdir_real_path); - try util.runCommandInDir(allocator, tar_argv.items, .{ .path = tmpdir_real_path }); + try util.runCommandInDir(allocator, tar_argv.items, .{ .path = tmpdir_real_path }, .{}); switch (builtin.os.tag) { .windows => {}, @@ -215,7 +215,7 @@ fn zig_build_install(allocator: std.mem.Allocator, path: []const u8, options: Op defer project_dir.close(); project_dir.makePath(".bundle") catch {}; - try util.runCommandInDir(allocator, install_argv.items, .{ .path = path }); + try util.runCommandInDir(allocator, install_argv.items, .{ .path = path }, .{}); const install_bin_path = try std.fs.path.join(allocator, &[_][]const u8{ ".bundle", "bin" }); defer allocator.free(install_bin_path); diff --git a/cli/commands/init.zig b/cli/commands/init.zig index 9556661..3b960ec 100644 --- a/cli/commands/init.zig +++ b/cli/commands/init.zig @@ -202,6 +202,7 @@ pub fn run( github_url, }, .{ .dir = install_dir }, + .{}, ); // TODO: Use arg or interactive prompt to do Git setup in net project, default to no. @@ -333,6 +334,7 @@ fn gitSetup(allocator: std.mem.Allocator, install_dir: *std.fs.Dir) !void { ".", }, .{ .path = install_dir }, + .{}, ); try util.runCommandInDir( @@ -343,6 +345,7 @@ fn gitSetup(allocator: std.mem.Allocator, install_dir: *std.fs.Dir) !void { ".", }, .{ .path = install_dir }, + .{}, ); try util.runCommandInDir( @@ -354,5 +357,6 @@ fn gitSetup(allocator: std.mem.Allocator, install_dir: *std.fs.Dir) !void { "Initialize Jetzig project", }, .{ .path = install_dir }, + .{}, ); } diff --git a/cli/commands/server.zig b/cli/commands/server.zig index e51c29f..034ac78 100644 --- a/cli/commands/server.zig +++ b/cli/commands/server.zig @@ -82,6 +82,7 @@ pub fn run( allocator, argv.items, .{ .path = realpath }, + .{ .output = .stream }, ) catch { std.debug.print("Build failed, waiting for file change...\n", .{}); try awaitFileChange(allocator, cwd, &mtime); diff --git a/cli/util.zig b/cli/util.zig index 0f2b925..386a0fc 100644 --- a/cli/util.zig +++ b/cli/util.zig @@ -153,7 +153,7 @@ pub fn runCommandStreaming(allocator: std.mem.Allocator, install_path: []const u pub fn runCommand(allocator: std.mem.Allocator, argv: []const []const u8) !void { var dir = try detectJetzigProjectDir(); defer dir.close(); - try runCommandInDir(allocator, argv, .{ .dir = dir }); + try runCommandInDir(allocator, argv, .{ .dir = dir }, .{}); } const Dir = union(enum) { @@ -161,34 +161,50 @@ const Dir = union(enum) { dir: std.fs.Dir, }; +pub const RunOptions = struct { + output: enum { stream, capture } = .capture, +}; + /// Runs a command as a child process in the given directory and verifies successful exit code. -pub fn runCommandInDir(allocator: std.mem.Allocator, argv: []const []const u8, dir: Dir) !void { +pub fn runCommandInDir(allocator: std.mem.Allocator, argv: []const []const u8, dir: Dir, options: RunOptions) !void { const cwd_path = switch (dir) { .path => |capture| capture, .dir => |capture| try capture.realpathAlloc(allocator, "."), }; defer if (dir == .dir) allocator.free(cwd_path); - const result = std.process.Child.run(.{ - .allocator = allocator, - .argv = argv, - .cwd = cwd_path, - }) catch |err| { - switch (err) { - error.FileNotFound => { - printFailure(); - const cmd_str = try std.mem.join(allocator, " ", argv); - defer allocator.free(cmd_str); - std.debug.print( - \\Error: Could not execute command - executable '{s}' not found - \\Command: {s} - \\Working directory: {s} - \\ - , .{ argv[0], cmd_str, cwd_path }); - return error.JetzigCommandError; - }, - else => return err, - } + const output_behaviour: std.process.Child.StdIo = switch (options.output) { + .stream => .Inherit, + .capture => .Pipe, + }; + + var child = std.process.Child.init(argv, allocator); + child.stdin_behavior = .Ignore; + child.stdout_behavior = output_behaviour; + child.stderr_behavior = output_behaviour; + if (options.output == .stream) { + child.stdout = std.io.getStdOut(); + child.stderr = std.io.getStdErr(); + } + child.cwd = cwd_path; + + var stdout = std.ArrayList(u8).init(allocator); + var stderr = std.ArrayList(u8).init(allocator); + errdefer { + stdout.deinit(); + stderr.deinit(); + } + + try child.spawn(); + switch (options.output) { + .capture => try child.collectOutput(&stdout, &stderr, 50 * 1024), + .stream => {}, + } + + const result = std.process.Child.RunResult{ + .term = try child.wait(), + .stdout = try stdout.toOwnedSlice(), + .stderr = try stderr.toOwnedSlice(), }; defer allocator.free(result.stdout); defer allocator.free(result.stderr); diff --git a/demo/build.zig b/demo/build.zig index 7cf8af5..4df8eac 100644 --- a/demo/build.zig +++ b/demo/build.zig @@ -10,7 +10,6 @@ pub fn build(b: *std.Build) !void { .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, - .use_llvm = b.option(bool, "use_llvm", "Use LLVM to generate executable") orelse (optimize != .Debug), }); // Example Dependency diff --git a/src/jetzig/App.zig b/src/jetzig/App.zig index 3ee7cea..dca1836 100644 --- a/src/jetzig/App.zig +++ b/src/jetzig/App.zig @@ -24,8 +24,7 @@ const AppOptions = struct { }; /// Starts an application. `routes` should be `@import("routes").routes`, a generated file -/// automatically created at build time. `templates` should be -/// `@import("src/app/views/zmpl.manifest.zig").templates`, created by Zmpl at compile time. +/// automatically created at build time. pub fn start(self: *const App, routes_module: type, options: AppOptions) !void { defer self.env.deinit();