diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 474dce3e12..6c8ba75730 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -2131,28 +2131,23 @@ test dirnameAllowEmpty { /// A reference to an existing or future path. pub const LazyPath = union(enum) { - /// Deprecated; use the `path` function instead. - path: []const u8, - /// A source file path relative to build root. src_path: struct { owner: *std.Build, sub_path: []const u8, }, - /// A file that is generated by an interface. Those files usually are - /// not available until built by a build step. - generated: *const GeneratedFile, - - /// One of the parent directories of a file generated by an interface. - /// The path is not available until built by a build step. - generated_dirname: struct { - generated: *const GeneratedFile, + generated: struct { + file: *const GeneratedFile, /// The number of parent directories to go up. - /// 0 means the directory of the generated file, - /// 1 means the parent of that directory, and so on. - up: usize, + /// 0 means the generated file itself. + /// 1 means the directory of the generated file. + /// 2 means the parent of that directory, and so on. + up: usize = 0, + + /// Applied after `up`. + sub_path: []const u8 = "", }, /// An absolute path or a path relative to the current working directory of @@ -2168,12 +2163,6 @@ pub const LazyPath = union(enum) { sub_path: []const u8, }, - /// Deprecated. Call `path` instead. - pub fn relative(sub_path: []const u8) LazyPath { - std.log.warn("deprecated. call std.Build.path instead", .{}); - return .{ .path = sub_path }; - } - /// Returns a lazy path referring to the directory containing this path. /// /// The dirname is not allowed to escape the logical root for underlying path. @@ -2183,8 +2172,6 @@ pub const LazyPath = union(enum) { /// the dirname is not allowed to traverse outside of zig-cache. pub fn dirname(lazy_path: LazyPath) LazyPath { return switch (lazy_path) { - .generated => |gen| .{ .generated_dirname = .{ .generated = gen, .up = 0 } }, - .generated_dirname => |gen| .{ .generated_dirname = .{ .generated = gen.generated, .up = gen.up + 1 } }, .src_path => |sp| .{ .src_path = .{ .owner = sp.owner, .sub_path = dirnameAllowEmpty(sp.sub_path) orelse { @@ -2192,12 +2179,15 @@ pub const LazyPath = union(enum) { @panic("misconfigured build script"); }, } }, - .path => |sub_path| .{ - .path = dirnameAllowEmpty(sub_path) orelse { - dumpBadDirnameHelp(null, null, "dirname() attempted to traverse outside the build root\n", .{}) catch {}; - @panic("misconfigured build script"); - }, - }, + .generated => |generated| .{ .generated = if (dirnameAllowEmpty(generated.sub_path)) |sub_dirname| .{ + .file = generated.file, + .up = generated.up, + .sub_path = sub_dirname, + } else .{ + .file = generated.file, + .up = generated.up + 1, + .sub_path = "", + } }, .cwd_relative => |rel_path| .{ .cwd_relative = dirnameAllowEmpty(rel_path) orelse { // If we get null, it means one of two things: @@ -2234,14 +2224,34 @@ pub const LazyPath = union(enum) { }; } + pub fn path(lazy_path: LazyPath, b: *Build, sub_path: []const u8) LazyPath { + return switch (lazy_path) { + .src_path => |src| .{ .src_path = .{ + .owner = src.owner, + .sub_path = b.pathResolve(&.{ src.sub_path, sub_path }), + } }, + .generated => |gen| .{ .generated = .{ + .file = gen.file, + .up = gen.up, + .sub_path = b.pathResolve(&.{ gen.sub_path, sub_path }), + } }, + .cwd_relative => |cwd_relative| .{ + .cwd_relative = b.pathResolve(&.{ cwd_relative, sub_path }), + }, + .dependency => |dep| .{ .dependency = .{ + .dependency = dep.dependency, + .sub_path = b.pathResolve(&.{ dep.sub_path, sub_path }), + } }, + }; + } + /// Returns a string that can be shown to represent the file source. - /// Either returns the path or `"generated"`. + /// Either returns the path, `"generated"`, or `"dependency"`. pub fn getDisplayName(lazy_path: LazyPath) []const u8 { return switch (lazy_path) { - .src_path => |src_path| src_path.sub_path, - .path, .cwd_relative => |sub_path| sub_path, + .src_path => |sp| sp.sub_path, + .cwd_relative => |p| p, .generated => "generated", - .generated_dirname => "generated", .dependency => "dependency", }; } @@ -2249,9 +2259,8 @@ pub const LazyPath = union(enum) { /// Adds dependencies this file source implies to the given step. pub fn addStepDependencies(lazy_path: LazyPath, other_step: *Step) void { switch (lazy_path) { - .src_path, .path, .cwd_relative, .dependency => {}, - .generated => |gen| other_step.dependOn(gen.step), - .generated_dirname => |gen| other_step.dependOn(gen.generated.step), + .src_path, .cwd_relative, .dependency => {}, + .generated => |gen| other_step.dependOn(gen.file.step), } } @@ -2268,47 +2277,48 @@ pub const LazyPath = union(enum) { /// run that is asking for the path. pub fn getPath2(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 { switch (lazy_path) { - .path => |p| return src_builder.pathFromRoot(p), .src_path => |sp| return sp.owner.pathFromRoot(sp.sub_path), .cwd_relative => |p| return src_builder.pathFromCwd(p), - .generated => |gen| return gen.step.owner.pathFromRoot(gen.path orelse { - std.debug.getStderrMutex().lock(); - const stderr = std.io.getStdErr(); - dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {}; - @panic("misconfigured build script"); - }), - .generated_dirname => |gen| { - const cache_root_path = src_builder.cache_root.path orelse - (src_builder.cache_root.join(src_builder.allocator, &.{"."}) catch @panic("OOM")); + .generated => |gen| { + var file_path: []const u8 = gen.file.step.owner.pathFromRoot(gen.file.path orelse { + std.debug.getStderrMutex().lock(); + const stderr = std.io.getStdErr(); + dumpBadGetPathHelp(gen.file.step, stderr, src_builder, asking_step) catch {}; + std.debug.getStderrMutex().unlock(); + @panic("misconfigured build script"); + }); - const gen_step = gen.generated.step; - var p = getPath2(LazyPath{ .generated = gen.generated }, src_builder, asking_step); - var i: usize = 0; - while (i <= gen.up) : (i += 1) { - // path is absolute. - // dirname will return null only if we're at root. - // Typically, we'll stop well before that at the cache root. - p = fs.path.dirname(p) orelse { - dumpBadDirnameHelp(gen_step, asking_step, - \\dirname() reached root. - \\No more directories left to go up. - \\ - , .{}) catch {}; - @panic("misconfigured build script"); - }; + if (gen.up > 0) { + const cache_root_path = src_builder.cache_root.path orelse + (src_builder.cache_root.join(src_builder.allocator, &.{"."}) catch @panic("OOM")); - if (mem.eql(u8, p, cache_root_path) and i < gen.up) { - // If we hit the cache root and there's still more to go, - // the script attempted to go too far. - dumpBadDirnameHelp(gen_step, asking_step, - \\dirname() attempted to traverse outside the cache root. - \\This is not allowed. - \\ - , .{}) catch {}; - @panic("misconfigured build script"); + for (0..gen.up) |_| { + if (mem.eql(u8, file_path, cache_root_path)) { + // If we hit the cache root and there's still more to go, + // the script attempted to go too far. + dumpBadDirnameHelp(gen.file.step, asking_step, + \\dirname() attempted to traverse outside the cache root. + \\This is not allowed. + \\ + , .{}) catch {}; + @panic("misconfigured build script"); + } + + // path is absolute. + // dirname will return null only if we're at root. + // Typically, we'll stop well before that at the cache root. + file_path = fs.path.dirname(file_path) orelse { + dumpBadDirnameHelp(gen.file.step, asking_step, + \\dirname() reached root. + \\No more directories left to go up. + \\ + , .{}) catch {}; + @panic("misconfigured build script"); + }; } } - return p; + + return src_builder.pathResolve(&.{ file_path, gen.sub_path }); }, .dependency => |dep| return dep.dependency.builder.pathFromRoot(dep.sub_path), } @@ -2324,15 +2334,12 @@ pub const LazyPath = union(enum) { .owner = sp.owner, .sub_path = sp.owner.dupePath(sp.sub_path), } }, - .path => |p| .{ .path = b.dupePath(p) }, .cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) }, - .generated => |gen| .{ .generated = gen }, - .generated_dirname => |gen| .{ - .generated_dirname = .{ - .generated = gen.generated, - .up = gen.up, - }, - }, + .generated => |gen| .{ .generated = .{ + .file = gen.file, + .up = gen.up, + .sub_path = b.dupePath(gen.sub_path), + } }, .dependency => |dep| .{ .dependency = dep }, }; } diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index d8f2c73311..f660ef64a6 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -806,14 +806,12 @@ pub fn setLibCFile(compile: *Compile, libc_file: ?LazyPath) void { } fn getEmittedFileGeneric(compile: *Compile, output_file: *?*GeneratedFile) LazyPath { - if (output_file.*) |g| { - return .{ .generated = g }; - } + if (output_file.*) |file| return .{ .generated = .{ .file = file } }; const arena = compile.step.owner.allocator; const generated_file = arena.create(GeneratedFile) catch @panic("OOM"); generated_file.* = .{ .step = &compile.step }; output_file.* = generated_file; - return .{ .generated = generated_file }; + return .{ .generated = .{ .file = generated_file } }; } /// Returns the path to the directory that contains the emitted binary file. diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig index bf8f941b16..4a0e64e8d0 100644 --- a/lib/std/Build/Step/ConfigHeader.zig +++ b/lib/std/Build/Step/ConfigHeader.zig @@ -59,8 +59,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader { if (options.style.getPath()) |s| default_include_path: { const sub_path = switch (s) { .src_path => |sp| sp.sub_path, - .path => |path| path, - .generated, .generated_dirname => break :default_include_path, + .generated => break :default_include_path, .cwd_relative => |sub_path| sub_path, .dependency => |dependency| dependency.sub_path, }; @@ -106,7 +105,7 @@ pub fn addValues(config_header: *ConfigHeader, values: anytype) void { } pub fn getOutput(config_header: *ConfigHeader) std.Build.LazyPath { - return .{ .generated = &config_header.output_file }; + return .{ .generated = .{ .file = &config_header.output_file } }; } fn addValuesInner(config_header: *ConfigHeader, values: anytype) !void { diff --git a/lib/std/Build/Step/ObjCopy.zig b/lib/std/Build/Step/ObjCopy.zig index 6e18ae3066..515736dbc1 100644 --- a/lib/std/Build/Step/ObjCopy.zig +++ b/lib/std/Build/Step/ObjCopy.zig @@ -84,10 +84,10 @@ pub fn create( pub const getOutputSource = getOutput; pub fn getOutput(objcopy: *const ObjCopy) std.Build.LazyPath { - return .{ .generated = &objcopy.output_file }; + return .{ .generated = .{ .file = &objcopy.output_file } }; } pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath { - return if (objcopy.output_file_debug) |*file| .{ .generated = file } else null; + return if (objcopy.output_file_debug) |*file| .{ .generated = .{ .file = file } } else null; } fn make(step: *Step, prog_node: *std.Progress.Node) !void { diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig index fe1833249b..c4daed73ff 100644 --- a/lib/std/Build/Step/Options.zig +++ b/lib/std/Build/Step/Options.zig @@ -407,7 +407,7 @@ pub const getSource = getOutput; /// Returns the main artifact of this Build Step which is a Zig source file /// generated from the key-value pairs of the Options. pub fn getOutput(options: *Options) LazyPath { - return .{ .generated = &options.generated_file }; + return .{ .generated = .{ .file = &options.generated_file } }; } fn make(step: *Step, prog_node: *std.Progress.Node) !void { diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index ffe19425cb..3b223f9b13 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -125,7 +125,8 @@ pub const Arg = union(enum) { lazy_path: PrefixedLazyPath, directory_source: PrefixedLazyPath, bytes: []u8, - output: *Output, + output_file: *Output, + output_directory: *Output, }; pub const PrefixedLazyPath = struct { @@ -225,13 +226,13 @@ pub fn addPrefixedOutputFileArg( .basename = b.dupe(basename), .generated_file = .{ .step = &run.step }, }; - run.argv.append(b.allocator, .{ .output = output }) catch @panic("OOM"); + run.argv.append(b.allocator, .{ .output_file = output }) catch @panic("OOM"); if (run.rename_step_with_output_arg) { run.setName(b.fmt("{s} ({s})", .{ run.step.name, basename })); } - return .{ .generated = &output.generated_file }; + return .{ .generated = .{ .file = &output.generated_file } }; } /// Appends an input file to the command line arguments. @@ -270,6 +271,56 @@ pub fn addPrefixedFileArg(run: *Run, prefix: []const u8, lp: std.Build.LazyPath) lp.addStepDependencies(&run.step); } +/// Provides a directory path as a command line argument to the command being run. +/// +/// Returns a `std.Build.LazyPath` which can be used as inputs to other APIs +/// throughout the build system. +/// +/// Related: +/// * `addPrefixedOutputDirectoryArg` - same thing but prepends a string to the argument +/// * `addDirectoryArg` - for input directories given to the child process +pub fn addOutputDirectoryArg(run: *Run, basename: []const u8) std.Build.LazyPath { + return run.addPrefixedOutputDirectoryArg("", basename); +} + +/// Provides a directory path as a command line argument to the command being run. +/// Asserts `basename` is not empty. +/// +/// For example, a prefix of "-o" and basename of "output_dir" will result in +/// the child process seeing something like this: "-ozig-cache/.../output_dir" +/// +/// The child process will see a single argument, regardless of whether the +/// prefix or basename have spaces. +/// +/// The returned `std.Build.LazyPath` can be used as inputs to other APIs +/// throughout the build system. +/// +/// Related: +/// * `addOutputDirectoryArg` - same thing but without the prefix +/// * `addDirectoryArg` - for input directories given to the child process +pub fn addPrefixedOutputDirectoryArg( + run: *Run, + prefix: []const u8, + basename: []const u8, +) std.Build.LazyPath { + if (basename.len == 0) @panic("basename must not be empty"); + const b = run.step.owner; + + const output = b.allocator.create(Output) catch @panic("OOM"); + output.* = .{ + .prefix = b.dupe(prefix), + .basename = b.dupe(basename), + .generated_file = .{ .step = &run.step }, + }; + run.argv.append(b.allocator, .{ .output_directory = output }) catch @panic("OOM"); + + if (run.rename_step_with_output_arg) { + run.setName(b.fmt("{s} ({s})", .{ run.step.name, basename })); + } + + return .{ .generated = .{ .file = &output.generated_file } }; +} + /// deprecated: use `addDirectoryArg` pub const addDirectorySourceArg = addDirectoryArg; @@ -314,9 +365,9 @@ pub fn addPrefixedDepFileOutputArg(run: *Run, prefix: []const u8, basename: []co run.dep_output_file = dep_file; - run.argv.append(b.allocator, .{ .output = dep_file }) catch @panic("OOM"); + run.argv.append(b.allocator, .{ .output_file = dep_file }) catch @panic("OOM"); - return .{ .generated = &dep_file.generated_file }; + return .{ .generated = .{ .file = &dep_file.generated_file } }; } pub fn addArg(run: *Run, arg: []const u8) void { @@ -432,7 +483,7 @@ pub fn addCheck(run: *Run, new_check: StdIo.Check) void { pub fn captureStdErr(run: *Run) std.Build.LazyPath { assert(run.stdio != .inherit); - if (run.captured_stderr) |output| return .{ .generated = &output.generated_file }; + if (run.captured_stderr) |output| return .{ .generated = .{ .file = &output.generated_file } }; const output = run.step.owner.allocator.create(Output) catch @panic("OOM"); output.* = .{ @@ -441,13 +492,13 @@ pub fn captureStdErr(run: *Run) std.Build.LazyPath { .generated_file = .{ .step = &run.step }, }; run.captured_stderr = output; - return .{ .generated = &output.generated_file }; + return .{ .generated = .{ .file = &output.generated_file } }; } pub fn captureStdOut(run: *Run) std.Build.LazyPath { assert(run.stdio != .inherit); - if (run.captured_stdout) |output| return .{ .generated = &output.generated_file }; + if (run.captured_stdout) |output| return .{ .generated = .{ .file = &output.generated_file } }; const output = run.step.owner.allocator.create(Output) catch @panic("OOM"); output.* = .{ @@ -456,7 +507,7 @@ pub fn captureStdOut(run: *Run) std.Build.LazyPath { .generated_file = .{ .step = &run.step }, }; run.captured_stdout = output; - return .{ .generated = &output.generated_file }; + return .{ .generated = .{ .file = &output.generated_file } }; } /// Adds an additional input files that, when modified, indicates that this Run @@ -484,7 +535,7 @@ fn hasAnyOutputArgs(run: Run) bool { if (run.captured_stdout != null) return true; if (run.captured_stderr != null) return true; for (run.argv.items) |arg| switch (arg) { - .output => return true, + .output_file, .output_directory => return true, else => continue, }; return false; @@ -520,6 +571,7 @@ fn checksContainStderr(checks: []const StdIo.Check) bool { const IndexedOutput = struct { index: usize, + tag: @typeInfo(Arg).Union.tag_type.?, output: *Output, }; fn make(step: *Step, prog_node: *std.Progress.Node) !void { @@ -563,17 +615,18 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { _ = try man.addFile(file_path, null); }, - .output => |output| { + .output_file, .output_directory => |output| { man.hash.addBytes(output.prefix); man.hash.addBytes(output.basename); // Add a placeholder into the argument list because we need the // manifest hash to be updated with all arguments before the // object directory is computed. - try argv_list.append(""); try output_placeholders.append(.{ - .index = argv_list.items.len - 1, + .index = argv_list.items.len, + .tag = arg, .output = output, }); + _ = try argv_list.addOne(); }, } } @@ -599,11 +652,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { hashStdIo(&man.hash, run.stdio); - if (has_side_effects) { - try runCommand(run, argv_list.items, has_side_effects, null, prog_node); - return; - } - for (run.extra_file_dependencies) |file_path| { _ = try man.addFile(b.pathFromRoot(file_path), null); } @@ -611,7 +659,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { _ = try man.addFile(lazy_path.getPath2(b, step), null); } - if (try step.cacheHit(&man)) { + if (try step.cacheHit(&man) and !has_side_effects) { // cache hit, skip running command const digest = man.final(); @@ -628,13 +676,54 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { return; } + const dep_output_file = run.dep_output_file orelse { + // We already know the final output paths, use them directly. + const digest = man.final(); + + try populateGeneratedPaths( + arena, + output_placeholders.items, + run.captured_stdout, + run.captured_stderr, + b.cache_root, + &digest, + ); + + const output_dir_path = "o" ++ fs.path.sep_str ++ &digest; + for (output_placeholders.items) |placeholder| { + const output_sub_path = b.pathJoin(&.{ output_dir_path, placeholder.output.basename }); + const output_sub_dir_path = switch (placeholder.tag) { + .output_file => fs.path.dirname(output_sub_path).?, + .output_directory => output_sub_path, + else => unreachable, + }; + b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { + return step.fail("unable to make path '{}{s}': {s}", .{ + b.cache_root, output_sub_dir_path, @errorName(err), + }); + }; + const output_path = placeholder.output.generated_file.path.?; + argv_list.items[placeholder.index] = if (placeholder.output.prefix.len == 0) + output_path + else + b.fmt("{s}{s}", .{ placeholder.output.prefix, output_path }); + } + + return runCommand(run, argv_list.items, has_side_effects, output_dir_path, prog_node); + }; + + // We do not know the final output paths yet, use temp paths to run the command. const rand_int = std.crypto.random.int(u64); const tmp_dir_path = "tmp" ++ fs.path.sep_str ++ std.Build.hex64(rand_int); for (output_placeholders.items) |placeholder| { const output_components = .{ tmp_dir_path, placeholder.output.basename }; const output_sub_path = b.pathJoin(&output_components); - const output_sub_dir_path = fs.path.dirname(output_sub_path).?; + const output_sub_dir_path = switch (placeholder.tag) { + .output_file => fs.path.dirname(output_sub_path).?, + .output_directory => output_sub_path, + else => unreachable, + }; b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { return step.fail("unable to make path '{}{s}': {s}", .{ b.cache_root, output_sub_dir_path, @errorName(err), @@ -642,17 +731,15 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { }; const output_path = try b.cache_root.join(arena, &output_components); placeholder.output.generated_file.path = output_path; - const cli_arg = if (placeholder.output.prefix.len == 0) + argv_list.items[placeholder.index] = if (placeholder.output.prefix.len == 0) output_path else b.fmt("{s}{s}", .{ placeholder.output.prefix, output_path }); - argv_list.items[placeholder.index] = cli_arg; } try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, prog_node); - if (run.dep_output_file) |dep_output_file| - try man.addDepFilePost(std.fs.cwd(), dep_output_file.generated_file.getPath()); + try man.addDepFilePost(std.fs.cwd(), dep_output_file.generated_file.getPath()); const digest = man.final(); @@ -777,7 +864,7 @@ fn runCommand( run: *Run, argv: []const []const u8, has_side_effects: bool, - tmp_dir_path: ?[]const u8, + output_dir_path: []const u8, prog_node: *std.Progress.Node, ) !void { const step = &run.step; @@ -950,7 +1037,7 @@ fn runCommand( }, }) |stream| { if (stream.captured) |output| { - const output_components = .{ tmp_dir_path.?, output.basename }; + const output_components = .{ output_dir_path, output.basename }; const output_path = try b.cache_root.join(arena, &output_components); output.generated_file.path = output_path; diff --git a/lib/std/Build/Step/TranslateC.zig b/lib/std/Build/Step/TranslateC.zig index 30a3988d4e..cb1b48e3c0 100644 --- a/lib/std/Build/Step/TranslateC.zig +++ b/lib/std/Build/Step/TranslateC.zig @@ -59,7 +59,7 @@ pub const AddExecutableOptions = struct { }; pub fn getOutput(translate_c: *TranslateC) std.Build.LazyPath { - return .{ .generated = &translate_c.output_file }; + return .{ .generated = .{ .file = &translate_c.output_file } }; } /// Creates a step to build an executable from the translated source. diff --git a/lib/std/Build/Step/WriteFile.zig b/lib/std/Build/Step/WriteFile.zig index 875ddbfdbe..401c5b78ec 100644 --- a/lib/std/Build/Step/WriteFile.zig +++ b/lib/std/Build/Step/WriteFile.zig @@ -31,7 +31,7 @@ pub const File = struct { contents: Contents, pub fn getPath(file: *File) std.Build.LazyPath { - return .{ .generated = &file.generated_file }; + return .{ .generated = .{ .file = &file.generated_file } }; } }; @@ -58,7 +58,7 @@ pub const Directory = struct { }; pub fn getPath(dir: *Directory) std.Build.LazyPath { - return .{ .generated = &dir.generated_dir }; + return .{ .generated = .{ .file = &dir.generated_dir } }; } }; @@ -181,7 +181,7 @@ pub fn addBytesToSource(write_file: *WriteFile, bytes: []const u8, sub_path: []c /// Returns a `LazyPath` representing the base directory that contains all the /// files from this `WriteFile`. pub fn getDirectory(write_file: *WriteFile) std.Build.LazyPath { - return .{ .generated = &write_file.generated_directory }; + return .{ .generated = .{ .file = &write_file.generated_directory } }; } fn maybeUpdateName(write_file: *WriteFile) void { diff --git a/test/standalone/build.zig.zon b/test/standalone/build.zig.zon index 7ddde1611a..e1b856a4be 100644 --- a/test/standalone/build.zig.zon +++ b/test/standalone/build.zig.zon @@ -164,6 +164,9 @@ .dependencyFromBuildZig = .{ .path = "dependencyFromBuildZig", }, + .run_output_paths = .{ + .path = "run_output_paths", + }, }, .paths = .{ "build.zig", diff --git a/test/standalone/run_output_paths/build.zig b/test/standalone/run_output_paths/build.zig new file mode 100644 index 0000000000..f4c7254d8f --- /dev/null +++ b/test/standalone/run_output_paths/build.zig @@ -0,0 +1,40 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const create_file_exe = b.addExecutable(.{ + .name = "create_file", + .root_source_file = b.path("create_file.zig"), + .target = target, + .optimize = optimize, + }); + + const create_first = b.addRunArtifact(create_file_exe); + const first_dir = create_first.addOutputDirectoryArg("first"); + create_first.addArg("hello1.txt"); + test_step.dependOn(&b.addCheckFile(first_dir.path(b, "hello1.txt"), .{ .expected_matches = &.{ + std.fs.path.sep_str ++ + \\first + \\hello1.txt + \\Hello, world! + \\ + , + } }).step); + + const create_second = b.addRunArtifact(create_file_exe); + const second_dir = create_second.addPrefixedOutputDirectoryArg("--dir=", "second"); + create_second.addArg("hello2.txt"); + test_step.dependOn(&b.addCheckFile(second_dir.path(b, "hello2.txt"), .{ .expected_matches = &.{ + std.fs.path.sep_str ++ + \\second + \\hello2.txt + \\Hello, world! + \\ + , + } }).step); +} diff --git a/test/standalone/run_output_paths/create_file.zig b/test/standalone/run_output_paths/create_file.zig new file mode 100644 index 0000000000..041ebc3e50 --- /dev/null +++ b/test/standalone/run_output_paths/create_file.zig @@ -0,0 +1,19 @@ +const std = @import("std"); + +pub fn main() !void { + var args = try std.process.argsWithAllocator(std.heap.page_allocator); + _ = args.skip(); + const dir_name = args.next().?; + const dir = try std.fs.cwd().openDir(if (std.mem.startsWith(u8, dir_name, "--dir=")) + dir_name["--dir=".len..] + else + dir_name, .{}); + const file_name = args.next().?; + const file = try dir.createFile(file_name, .{}); + try file.writer().print( + \\{s} + \\{s} + \\Hello, world! + \\ + , .{ dir_name, file_name }); +} diff --git a/test/standalone/windows_resources/build.zig b/test/standalone/windows_resources/build.zig index 15130d3b87..da88659b4d 100644 --- a/test/standalone/windows_resources/build.zig +++ b/test/standalone/windows_resources/build.zig @@ -36,7 +36,7 @@ fn add( .file = b.path("res/zig.rc"), .flags = &.{"/c65001"}, // UTF-8 code page .include_paths = &.{ - .{ .generated = &generated_h_step.generated_directory }, + .{ .generated = .{ .file = &generated_h_step.generated_directory } }, }, }); exe.rc_includes = switch (rc_includes) {