srctree

Jacob Young parent e3424332 dee9f82f
Run: add output directory arguments

This allows running commands that take an output directory argument. The main thing that was needed for this feature was generated file subpaths, to allow access to the files in a generated directory. Additionally, a minor change was required to so that the correct directory is created for output directory args.
lib/std/Build.zig added: 284, removed: 131, total 153
@@ -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 },
};
}
 
lib/std/Build/Step/Compile.zig added: 284, removed: 131, total 153
@@ -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.
 
lib/std/Build/Step/ConfigHeader.zig added: 284, removed: 131, total 153
@@ -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 {
 
lib/std/Build/Step/ObjCopy.zig added: 284, removed: 131, total 153
@@ -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 {
 
lib/std/Build/Step/Options.zig added: 284, removed: 131, total 153
@@ -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 {
 
lib/std/Build/Step/Run.zig added: 284, removed: 131, total 153
@@ -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;
 
 
lib/std/Build/Step/TranslateC.zig added: 284, removed: 131, total 153
@@ -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.
 
lib/std/Build/Step/WriteFile.zig added: 284, removed: 131, total 153
@@ -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 {
 
test/standalone/build.zig.zon added: 284, removed: 131, total 153
@@ -164,6 +164,9 @@
.dependencyFromBuildZig = .{
.path = "dependencyFromBuildZig",
},
.run_output_paths = .{
.path = "run_output_paths",
},
},
.paths = .{
"build.zig",
 
filename was Deleted added: 284, removed: 131, total 153
@@ -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);
}
 
filename was Deleted added: 284, removed: 131, total 153
@@ -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 });
}
 
test/standalone/windows_resources/build.zig added: 284, removed: 131, total 153
@@ -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) {