Merge branch 'zig-backport-std.os.path' of https://github.com/kristate/zig into kristate-zig-backport-std.os.path

master
Andrew Kelley 2019-02-06 22:53:34 -05:00
commit c804ae2d6b
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
16 changed files with 114 additions and 91 deletions

View File

@ -16,7 +16,7 @@ pub fn build(b: *Builder) !void {
var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig"); var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe); const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe);
const langref_out_path = os.path.join(b.allocator, b.cache_root, "langref.html") catch unreachable; const langref_out_path = os.path.join(b.allocator, [][]const u8{ b.cache_root, "langref.html" }) catch unreachable;
var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{ var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{
docgen_exe.getOutputPath(), docgen_exe.getOutputPath(),
rel_zig_exe, rel_zig_exe,
@ -125,13 +125,13 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void {
for (dep.libdirs.toSliceConst()) |lib_dir| { for (dep.libdirs.toSliceConst()) |lib_dir| {
lib_exe_obj.addLibPath(lib_dir); lib_exe_obj.addLibPath(lib_dir);
} }
const lib_dir = os.path.join(b.allocator, dep.prefix, "lib") catch unreachable; const lib_dir = os.path.join(b.allocator, [][]const u8{dep.prefix, "lib"}) catch unreachable;
for (dep.system_libs.toSliceConst()) |lib| { for (dep.system_libs.toSliceConst()) |lib| {
const static_bare_name = if (mem.eql(u8, lib, "curses")) const static_bare_name = if (mem.eql(u8, lib, "curses"))
([]const u8)("libncurses.a") ([]const u8)("libncurses.a")
else else
b.fmt("lib{}.a", lib); b.fmt("lib{}.a", lib);
const static_lib_name = os.path.join(b.allocator, lib_dir, static_bare_name) catch unreachable; const static_lib_name = os.path.join(b.allocator, [][]const u8{lib_dir, static_bare_name}) catch unreachable;
const have_static = fileExists(static_lib_name) catch unreachable; const have_static = fileExists(static_lib_name) catch unreachable;
if (have_static) { if (have_static) {
lib_exe_obj.addObjectFile(static_lib_name); lib_exe_obj.addObjectFile(static_lib_name);
@ -159,7 +159,7 @@ fn fileExists(filename: []const u8) !bool {
fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void { fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void {
const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib"; const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib";
lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp", b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable); lib_exe_obj.addObjectFile(os.path.join(b.allocator, [][]const u8{ cmake_binary_dir, "zig_cpp", b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt()) }) catch unreachable);
} }
const LibraryDep = struct { const LibraryDep = struct {
@ -235,8 +235,8 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void { pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {
var it = mem.tokenize(stdlib_files, ";"); var it = mem.tokenize(stdlib_files, ";");
while (it.next()) |stdlib_file| { while (it.next()) |stdlib_file| {
const src_path = os.path.join(b.allocator, "std", stdlib_file) catch unreachable; const src_path = os.path.join(b.allocator, [][]const u8{"std", stdlib_file}) catch unreachable;
const dest_path = os.path.join(b.allocator, "lib", "zig", "std", stdlib_file) catch unreachable; const dest_path = os.path.join(b.allocator, [][]const u8{"lib", "zig", "std", stdlib_file}) catch unreachable;
b.installFile(src_path, dest_path); b.installFile(src_path, dest_path);
} }
} }
@ -244,8 +244,8 @@ pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {
pub fn installCHeaders(b: *Builder, c_header_files: []const u8) void { pub fn installCHeaders(b: *Builder, c_header_files: []const u8) void {
var it = mem.tokenize(c_header_files, ";"); var it = mem.tokenize(c_header_files, ";");
while (it.next()) |c_header_file| { while (it.next()) |c_header_file| {
const src_path = os.path.join(b.allocator, "c_headers", c_header_file) catch unreachable; const src_path = os.path.join(b.allocator, [][]const u8{"c_headers", c_header_file}) catch unreachable;
const dest_path = os.path.join(b.allocator, "lib", "zig", "include", c_header_file) catch unreachable; const dest_path = os.path.join(b.allocator, [][]const u8{"lib", "zig", "include", c_header_file}) catch unreachable;
b.installFile(src_path, dest_path); b.installFile(src_path, dest_path);
} }
} }

View File

@ -990,13 +990,13 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
try tokenizeAndPrint(tokenizer, out, code.source_token); try tokenizeAndPrint(tokenizer, out, code.source_token);
try out.write("</pre>"); try out.write("</pre>");
const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name); const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);
const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext); const tmp_source_file_name = try os.path.join(allocator, [][]const u8{ tmp_dir_name, name_plus_ext });
try io.writeFile(tmp_source_file_name, trimmed_raw_source); try io.writeFile(tmp_source_file_name, trimmed_raw_source);
switch (code.id) { switch (code.id) {
Code.Id.Exe => |expected_outcome| { Code.Id.Exe => |expected_outcome| {
const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext); const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext);
const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext); const tmp_bin_file_name = try os.path.join(allocator, [][]const u8{ tmp_dir_name, name_plus_bin_ext });
var build_args = std.ArrayList([]const u8).init(allocator); var build_args = std.ArrayList([]const u8).init(allocator);
defer build_args.deinit(); defer build_args.deinit();
try build_args.appendSlice([][]const u8{ try build_args.appendSlice([][]const u8{
@ -1024,7 +1024,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
} }
for (code.link_objects) |link_object| { for (code.link_objects) |link_object| {
const name_with_ext = try std.fmt.allocPrint(allocator, "{}{}", link_object, obj_ext); const name_with_ext = try std.fmt.allocPrint(allocator, "{}{}", link_object, obj_ext);
const full_path_object = try os.path.join(allocator, tmp_dir_name, name_with_ext); const full_path_object = try os.path.join(allocator, [][]const u8{ tmp_dir_name, name_with_ext });
try build_args.append("--object"); try build_args.append("--object");
try build_args.append(full_path_object); try build_args.append(full_path_object);
try out.print(" --object {}", name_with_ext); try out.print(" --object {}", name_with_ext);
@ -1216,12 +1216,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
}, },
Code.Id.Obj => |maybe_error_match| { Code.Id.Obj => |maybe_error_match| {
const name_plus_obj_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, obj_ext); const name_plus_obj_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, obj_ext);
const tmp_obj_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_obj_ext); const tmp_obj_file_name = try os.path.join(allocator, [][]const u8{ tmp_dir_name, name_plus_obj_ext });
var build_args = std.ArrayList([]const u8).init(allocator); var build_args = std.ArrayList([]const u8).init(allocator);
defer build_args.deinit(); defer build_args.deinit();
const name_plus_h_ext = try std.fmt.allocPrint(allocator, "{}.h", code.name); const name_plus_h_ext = try std.fmt.allocPrint(allocator, "{}.h", code.name);
const output_h_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_h_ext); const output_h_file_name = try os.path.join(allocator, [][]const u8{ tmp_dir_name, name_plus_h_ext });
try build_args.appendSlice([][]const u8{ try build_args.appendSlice([][]const u8{
zig_exe, zig_exe,

View File

@ -487,7 +487,7 @@ pub const Compilation = struct {
comp.name = try Buffer.init(comp.arena(), name); comp.name = try Buffer.init(comp.arena(), name);
comp.llvm_triple = try target.getTriple(comp.arena()); comp.llvm_triple = try target.getTriple(comp.arena());
comp.llvm_target = try Target.llvmTargetFromTriple(comp.llvm_triple); comp.llvm_target = try Target.llvmTargetFromTriple(comp.llvm_triple);
comp.zig_std_dir = try std.os.path.join(comp.arena(), zig_lib_dir, "std"); comp.zig_std_dir = try std.os.path.join(comp.arena(), [][]const u8{ zig_lib_dir, "std" });
const opt_level = switch (build_mode) { const opt_level = switch (build_mode) {
builtin.Mode.Debug => llvm.CodeGenLevelNone, builtin.Mode.Debug => llvm.CodeGenLevelNone,
@ -1198,7 +1198,7 @@ pub const Compilation = struct {
const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix); const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix);
defer self.gpa().free(file_name); defer self.gpa().free(file_name);
const full_path = try os.path.join(self.gpa(), tmp_dir, file_name[0..]); const full_path = try os.path.join(self.gpa(), [][]const u8{ tmp_dir, file_name[0..] });
errdefer self.gpa().free(full_path); errdefer self.gpa().free(full_path);
return Buffer.fromOwnedSlice(self.gpa(), full_path); return Buffer.fromOwnedSlice(self.gpa(), full_path);
@ -1219,7 +1219,7 @@ pub const Compilation = struct {
const zig_dir_path = try getZigDir(self.gpa()); const zig_dir_path = try getZigDir(self.gpa());
defer self.gpa().free(zig_dir_path); defer self.gpa().free(zig_dir_path);
const tmp_dir = try os.path.join(self.arena(), zig_dir_path, comp_dir_name[0..]); const tmp_dir = try os.path.join(self.arena(), [][]const u8{ zig_dir_path, comp_dir_name[0..] });
try os.makePath(self.gpa(), tmp_dir); try os.makePath(self.gpa(), tmp_dir);
return tmp_dir; return tmp_dir;
} }

View File

@ -8,10 +8,10 @@ const warn = std.debug.warn;
/// Caller must free result /// Caller must free result
pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 { pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 {
const test_zig_dir = try os.path.join(allocator, test_path, "lib", "zig"); const test_zig_dir = try os.path.join(allocator, [][]const u8{ test_path, "lib", "zig" });
errdefer allocator.free(test_zig_dir); errdefer allocator.free(test_zig_dir);
const test_index_file = try os.path.join(allocator, test_zig_dir, "std", "index.zig"); const test_index_file = try os.path.join(allocator, [][]const u8{ test_zig_dir, "std", "index.zig" });
defer allocator.free(test_index_file); defer allocator.free(test_index_file);
var file = try os.File.openRead(test_index_file); var file = try os.File.openRead(test_index_file);

View File

@ -230,7 +230,7 @@ pub const LibCInstallation = struct {
while (path_i < search_paths.len) : (path_i += 1) { while (path_i < search_paths.len) : (path_i += 1) {
const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1); const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);
const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " "); const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " ");
const stdlib_path = try std.os.path.join(loop.allocator, search_path, "stdlib.h"); const stdlib_path = try std.os.path.join(loop.allocator, [][]const u8{ search_path, "stdlib.h" });
defer loop.allocator.free(stdlib_path); defer loop.allocator.free(stdlib_path);
if (try fileExists(stdlib_path)) { if (try fileExists(stdlib_path)) {
@ -254,7 +254,7 @@ pub const LibCInstallation = struct {
const stream = &std.io.BufferOutStream.init(&result_buf).stream; const stream = &std.io.BufferOutStream.init(&result_buf).stream;
try stream.print("{}\\Include\\{}\\ucrt", search.path, search.version); try stream.print("{}\\Include\\{}\\ucrt", search.path, search.version);
const stdlib_path = try std.os.path.join(loop.allocator, result_buf.toSliceConst(), "stdlib.h"); const stdlib_path = try std.os.path.join(loop.allocator, [][]const u8{ result_buf.toSliceConst(), "stdlib.h" });
defer loop.allocator.free(stdlib_path); defer loop.allocator.free(stdlib_path);
if (try fileExists(stdlib_path)) { if (try fileExists(stdlib_path)) {
@ -283,7 +283,7 @@ pub const LibCInstallation = struct {
builtin.Arch.aarch64v8 => try stream.write("arm"), builtin.Arch.aarch64v8 => try stream.write("arm"),
else => return error.UnsupportedArchitecture, else => return error.UnsupportedArchitecture,
} }
const ucrt_lib_path = try std.os.path.join(loop.allocator, result_buf.toSliceConst(), "ucrt.lib"); const ucrt_lib_path = try std.os.path.join(loop.allocator, [][]const u8{ result_buf.toSliceConst(), "ucrt.lib" });
defer loop.allocator.free(ucrt_lib_path); defer loop.allocator.free(ucrt_lib_path);
if (try fileExists(ucrt_lib_path)) { if (try fileExists(ucrt_lib_path)) {
self.lib_dir = result_buf.toOwnedSlice(); self.lib_dir = result_buf.toOwnedSlice();
@ -358,7 +358,7 @@ pub const LibCInstallation = struct {
builtin.Arch.aarch64v8 => try stream.write("arm\\"), builtin.Arch.aarch64v8 => try stream.write("arm\\"),
else => return error.UnsupportedArchitecture, else => return error.UnsupportedArchitecture,
} }
const kernel32_path = try std.os.path.join(loop.allocator, result_buf.toSliceConst(), "kernel32.lib"); const kernel32_path = try std.os.path.join(loop.allocator, [][]const u8{ result_buf.toSliceConst(), "kernel32.lib" });
defer loop.allocator.free(kernel32_path); defer loop.allocator.free(kernel32_path);
if (try fileExists(kernel32_path)) { if (try fileExists(kernel32_path)) {
self.kernel32_lib_dir = result_buf.toOwnedSlice(); self.kernel32_lib_dir = result_buf.toOwnedSlice();

View File

@ -315,7 +315,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
} }
fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void { fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
const full_path = try std.os.path.join(&ctx.arena.allocator, dirname, basename); const full_path = try std.os.path.join(&ctx.arena.allocator, [][]const u8{ dirname, basename });
const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path); const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path);
try ctx.args.append(full_path_with_null.ptr); try ctx.args.append(full_path_with_null.ptr);
} }

View File

@ -757,7 +757,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
var group = event.Group(FmtError!void).init(fmt.loop); var group = event.Group(FmtError!void).init(fmt.loop);
while (try dir.next()) |entry| { while (try dir.next()) |entry| {
if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) { if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
const full_path = try os.path.join(fmt.loop.allocator, file_path, entry.name); const full_path = try os.path.join(fmt.loop.allocator, [][]const u8{ file_path, entry.name });
try group.call(fmtPath, fmt, full_path, check_mode); try group.call(fmtPath, fmt, full_path, check_mode);
} }
} }

View File

@ -87,7 +87,7 @@ pub const TestContext = struct {
) !void { ) !void {
var file_index_buf: [20]u8 = undefined; var file_index_buf: [20]u8 = undefined;
const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr()); const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());
const file1_path = try std.os.path.join(allocator, tmp_dir_name, file_index, file1); const file1_path = try std.os.path.join(allocator, [][]const u8{ tmp_dir_name, file_index, file1 });
if (std.os.path.dirname(file1_path)) |dirname| { if (std.os.path.dirname(file1_path)) |dirname| {
try std.os.makePath(allocator, dirname); try std.os.makePath(allocator, dirname);
@ -120,7 +120,7 @@ pub const TestContext = struct {
) !void { ) !void {
var file_index_buf: [20]u8 = undefined; var file_index_buf: [20]u8 = undefined;
const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr()); const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());
const file1_path = try std.os.path.join(allocator, tmp_dir_name, file_index, file1); const file1_path = try std.os.path.join(allocator, [][]const u8{ tmp_dir_name, file_index, file1 });
const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, Target(Target.Native).exeFileExt()); const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, Target(Target.Native).exeFileExt());
if (std.os.path.dirname(file1_path)) |dirname| { if (std.os.path.dirname(file1_path)) |dirname| {

View File

@ -145,8 +145,8 @@ pub const Builder = struct {
pub fn setInstallPrefix(self: *Builder, maybe_prefix: ?[]const u8) void { pub fn setInstallPrefix(self: *Builder, maybe_prefix: ?[]const u8) void {
self.prefix = maybe_prefix orelse "/usr/local"; // TODO better default self.prefix = maybe_prefix orelse "/usr/local"; // TODO better default
self.lib_dir = os.path.join(self.allocator, self.prefix, "lib") catch unreachable; self.lib_dir = os.path.join(self.allocator, [][]const u8{self.prefix, "lib"}) catch unreachable;
self.exe_dir = os.path.join(self.allocator, self.prefix, "bin") catch unreachable; self.exe_dir = os.path.join(self.allocator, [][]const u8{self.prefix, "bin"}) catch unreachable;
} }
pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
@ -676,7 +676,7 @@ pub const Builder = struct {
if (os.path.isAbsolute(name)) { if (os.path.isAbsolute(name)) {
return name; return name;
} }
const full_path = try os.path.join(self.allocator, search_prefix, "bin", self.fmt("{}{}", name, exe_extension)); const full_path = try os.path.join(self.allocator, [][]const u8{search_prefix, "bin", self.fmt("{}{}", name, exe_extension)});
if (os.path.real(self.allocator, full_path)) |real_path| { if (os.path.real(self.allocator, full_path)) |real_path| {
return real_path; return real_path;
} else |_| { } else |_| {
@ -691,7 +691,7 @@ pub const Builder = struct {
} }
var it = mem.tokenize(PATH, []u8{os.path.delimiter}); var it = mem.tokenize(PATH, []u8{os.path.delimiter});
while (it.next()) |path| { while (it.next()) |path| {
const full_path = try os.path.join(self.allocator, path, self.fmt("{}{}", name, exe_extension)); const full_path = try os.path.join(self.allocator, [][]const u8{path, self.fmt("{}{}", name, exe_extension)});
if (os.path.real(self.allocator, full_path)) |real_path| { if (os.path.real(self.allocator, full_path)) |real_path| {
return real_path; return real_path;
} else |_| { } else |_| {
@ -705,7 +705,7 @@ pub const Builder = struct {
return name; return name;
} }
for (paths) |path| { for (paths) |path| {
const full_path = try os.path.join(self.allocator, path, self.fmt("{}{}", name, exe_extension)); const full_path = try os.path.join(self.allocator, [][]const u8{path, self.fmt("{}{}", name, exe_extension)});
if (os.path.real(self.allocator, full_path)) |real_path| { if (os.path.real(self.allocator, full_path)) |real_path| {
return real_path; return real_path;
} else |_| { } else |_| {
@ -1113,7 +1113,7 @@ pub const LibExeObjStep = struct {
} }
pub fn getOutputPath(self: *LibExeObjStep) []const u8 { pub fn getOutputPath(self: *LibExeObjStep) []const u8 {
return if (self.output_path) |output_path| output_path else os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename) catch unreachable; return if (self.output_path) |output_path| output_path else os.path.join(self.builder.allocator, [][]const u8{self.builder.cache_root, self.out_filename}) catch unreachable;
} }
pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void { pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void {
@ -1126,7 +1126,7 @@ pub const LibExeObjStep = struct {
} }
pub fn getOutputHPath(self: *LibExeObjStep) []const u8 { pub fn getOutputHPath(self: *LibExeObjStep) []const u8 {
return if (self.output_h_path) |output_h_path| output_h_path else os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename) catch unreachable; return if (self.output_h_path) |output_h_path| output_h_path else os.path.join(self.builder.allocator, [][]const u8{self.builder.cache_root, self.out_h_filename}) catch unreachable;
} }
pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void { pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void {
@ -1226,7 +1226,7 @@ pub const LibExeObjStep = struct {
} }
if (self.build_options_contents.len() > 0) { if (self.build_options_contents.len() > 0) {
const build_options_file = try os.path.join(builder.allocator, builder.cache_root, builder.fmt("{}_build_options.zig", self.name)); const build_options_file = try os.path.join(builder.allocator, [][]const u8{builder.cache_root, builder.fmt("{}_build_options.zig", self.name)});
try std.io.writeFile(build_options_file, self.build_options_contents.toSliceConst()); try std.io.writeFile(build_options_file, self.build_options_contents.toSliceConst());
try zig_args.append("--pkg-begin"); try zig_args.append("--pkg-begin");
try zig_args.append("build_options"); try zig_args.append("build_options");
@ -1476,7 +1476,7 @@ pub const LibExeObjStep = struct {
cc_args.append("-c") catch unreachable; cc_args.append("-c") catch unreachable;
cc_args.append(abs_source_file) catch unreachable; cc_args.append(abs_source_file) catch unreachable;
const cache_o_src = os.path.join(builder.allocator, builder.cache_root, source_file) catch unreachable; const cache_o_src = os.path.join(builder.allocator, [][]const u8{builder.cache_root, source_file}) catch unreachable;
if (os.path.dirname(cache_o_src)) |cache_o_dir| { if (os.path.dirname(cache_o_src)) |cache_o_dir| {
try builder.makePath(cache_o_dir); try builder.makePath(cache_o_dir);
} }
@ -1528,7 +1528,7 @@ pub const LibExeObjStep = struct {
cc_args.append("-current_version") catch unreachable; cc_args.append("-current_version") catch unreachable;
cc_args.append(builder.fmt("{}.{}.{}", self.version.major, self.version.minor, self.version.patch)) catch unreachable; cc_args.append(builder.fmt("{}.{}.{}", self.version.major, self.version.minor, self.version.patch)) catch unreachable;
const install_name = builder.pathFromRoot(os.path.join(builder.allocator, builder.cache_root, self.major_only_filename) catch unreachable); const install_name = builder.pathFromRoot(os.path.join(builder.allocator, [][]const u8{builder.cache_root, self.major_only_filename}) catch unreachable);
cc_args.append("-install_name") catch unreachable; cc_args.append("-install_name") catch unreachable;
cc_args.append(install_name) catch unreachable; cc_args.append(install_name) catch unreachable;
} else { } else {
@ -1594,7 +1594,7 @@ pub const LibExeObjStep = struct {
cc_args.append("-c") catch unreachable; cc_args.append("-c") catch unreachable;
cc_args.append(abs_source_file) catch unreachable; cc_args.append(abs_source_file) catch unreachable;
const cache_o_src = os.path.join(builder.allocator, builder.cache_root, source_file) catch unreachable; const cache_o_src = os.path.join(builder.allocator, [][]const u8{builder.cache_root, source_file}) catch unreachable;
if (os.path.dirname(cache_o_src)) |cache_o_dir| { if (os.path.dirname(cache_o_src)) |cache_o_dir| {
try builder.makePath(cache_o_dir); try builder.makePath(cache_o_dir);
} }
@ -1757,7 +1757,7 @@ pub const TestStep = struct {
return output_path; return output_path;
} else { } else {
const basename = self.builder.fmt("test{}", self.target.exeFileExt()); const basename = self.builder.fmt("test{}", self.target.exeFileExt());
return os.path.join(self.builder.allocator, self.builder.cache_root, basename) catch unreachable; return os.path.join(self.builder.allocator, [][]const u8{self.builder.cache_root, basename}) catch unreachable;
} }
} }
@ -1980,12 +1980,12 @@ const InstallArtifactStep = struct {
.step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make), .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make),
.artifact = artifact, .artifact = artifact,
.dest_file = os.path.join(builder.allocator, dest_dir, artifact.out_filename) catch unreachable, .dest_file = os.path.join(builder.allocator, dest_dir, artifact.out_filename) catch unreachable,
}; }) catch unreachable;
self.step.dependOn(&artifact.step); self.step.dependOn(&artifact.step);
builder.pushInstalledFile(self.dest_file); builder.pushInstalledFile(self.dest_file);
if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) { if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) {
builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.major_only_filename) catch unreachable); builder.pushInstalledFile(os.path.join(builder.allocator, [][]const u8{builder.lib_dir, artifact.major_only_filename}) catch unreachable);
builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.name_only_filename) catch unreachable); builder.pushInstalledFile(os.path.join(builder.allocator, [][]const u8{builder.lib_dir, artifact.name_only_filename}) catch unreachable);
} }
return self; return self;
} }
@ -2141,13 +2141,13 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj
const out_dir = os.path.dirname(output_path) orelse "."; const out_dir = os.path.dirname(output_path) orelse ".";
const out_basename = os.path.basename(output_path); const out_basename = os.path.basename(output_path);
// sym link for libfoo.so.1 to libfoo.so.1.2.3 // sym link for libfoo.so.1 to libfoo.so.1.2.3
const major_only_path = os.path.join(allocator, out_dir, filename_major_only) catch unreachable; const major_only_path = os.path.join(allocator, [][]const u8{out_dir, filename_major_only}) catch unreachable;
os.atomicSymLink(allocator, out_basename, major_only_path) catch |err| { os.atomicSymLink(allocator, out_basename, major_only_path) catch |err| {
warn("Unable to symlink {} -> {}\n", major_only_path, out_basename); warn("Unable to symlink {} -> {}\n", major_only_path, out_basename);
return err; return err;
}; };
// sym link for libfoo.so to libfoo.so.1 // sym link for libfoo.so to libfoo.so.1
const name_only_path = os.path.join(allocator, out_dir, filename_name_only) catch unreachable; const name_only_path = os.path.join(allocator, [][]const u8{out_dir, filename_name_only}) catch unreachable;
os.atomicSymLink(allocator, filename_major_only, name_only_path) catch |err| { os.atomicSymLink(allocator, filename_major_only, name_only_path) catch |err| {
warn("Unable to symlink {} -> {}\n", name_only_path, filename_major_only); warn("Unable to symlink {} -> {}\n", name_only_path, filename_major_only);
return err; return err;

View File

@ -1352,7 +1352,7 @@ const LineNumberProgram = struct {
return error.InvalidDebugInfo; return error.InvalidDebugInfo;
} else } else
self.include_dirs[file_entry.dir_index]; self.include_dirs[file_entry.dir_index];
const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name); const file_name = try os.path.join(self.file_entries.allocator, [][]const u8{dir_name, file_entry.file_name});
errdefer self.file_entries.allocator.free(file_name); errdefer self.file_entries.allocator.free(file_name);
return LineInfo{ return LineInfo{
.line = if (self.prev_line >= 0) @intCast(usize, self.prev_line) else 0, .line = if (self.prev_line >= 0) @intCast(usize, self.prev_line) else 0,

View File

@ -1336,7 +1336,7 @@ async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void {
} }
async fn testFsWatch(loop: *Loop) !void { async fn testFsWatch(loop: *Loop) !void {
const file_path = try os.path.join(loop.allocator, test_tmp_dir, "file.txt"); const file_path = try os.path.join(loop.allocator, [][]const u8{test_tmp_dir, "file.txt"});
defer loop.allocator.free(file_path); defer loop.allocator.free(file_path);
const contents = const contents =

View File

@ -597,7 +597,7 @@ pub const ChildProcess = struct {
var it = mem.tokenize(PATH, ";"); var it = mem.tokenize(PATH, ";");
while (it.next()) |search_path| { while (it.next()) |search_path| {
const joined_path = try os.path.join(self.allocator, search_path, app_name); const joined_path = try os.path.join(self.allocator, [][]const u8{ search_path, app_name });
defer self.allocator.free(joined_path); defer self.allocator.free(joined_path);
const joined_path_w = try unicode.utf8ToUtf16LeWithNull(self.allocator, joined_path); const joined_path_w = try unicode.utf8ToUtf16LeWithNull(self.allocator, joined_path);

View File

@ -30,7 +30,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
error.OutOfMemory => return error.OutOfMemory, error.OutOfMemory => return error.OutOfMemory,
}; };
defer allocator.free(global_dir); defer allocator.free(global_dir);
return os.path.join(allocator, global_dir, appname); return os.path.join(allocator, [][]const u8{global_dir, appname});
}, },
os.windows.E_OUTOFMEMORY => return error.OutOfMemory, os.windows.E_OUTOFMEMORY => return error.OutOfMemory,
else => return error.AppDataDirUnavailable, else => return error.AppDataDirUnavailable,
@ -41,14 +41,14 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
// TODO look in /etc/passwd // TODO look in /etc/passwd
return error.AppDataDirUnavailable; return error.AppDataDirUnavailable;
}; };
return os.path.join(allocator, home_dir, "Library", "Application Support", appname); return os.path.join(allocator, [][]const u8{home_dir, "Library", "Application Support", appname});
}, },
builtin.Os.linux, builtin.Os.freebsd => { builtin.Os.linux, builtin.Os.freebsd => {
const home_dir = os.getEnvPosix("HOME") orelse { const home_dir = os.getEnvPosix("HOME") orelse {
// TODO look in /etc/passwd // TODO look in /etc/passwd
return error.AppDataDirUnavailable; return error.AppDataDirUnavailable;
}; };
return os.path.join(allocator, home_dir, ".local", "share", appname); return os.path.join(allocator, [][]const u8{home_dir, ".local", "share", appname});
}, },
else => @compileError("Unsupported OS"), else => @compileError("Unsupported OS"),
} }

View File

@ -35,38 +35,61 @@ pub fn isSep(byte: u8) bool {
/// Naively combines a series of paths with the native path seperator. /// Naively combines a series of paths with the native path seperator.
/// Allocates memory for the result, which must be freed by the caller. /// Allocates memory for the result, which must be freed by the caller.
pub fn join(allocator: *Allocator, paths: ...) ![]u8 {
if (is_windows) { pub fn join(allocator: *Allocator, paths: []const []const u8) ![]u8 {
return joinWindows(allocator, paths); assert(paths.len >= 1);
} else { var total_paths_len: usize = paths.len; // 1 sep per path
return joinPosix(allocator, paths); {
var path_i: usize = 0;
while (path_i < paths.len) : (path_i += 1) {
const arg = ([]const u8)(paths[path_i]);
total_paths_len += arg.len;
}
} }
}
pub fn joinWindows(allocator: *Allocator, paths: ...) ![]u8 { const buf = try allocator.alloc(u8, total_paths_len);
return mem.join(allocator, sep_windows, paths); errdefer allocator.free(buf);
}
pub fn joinPosix(allocator: *Allocator, paths: ...) ![]u8 { var buf_index: usize = 0;
return mem.join(allocator, sep_posix, paths); var path_i: usize = 0;
while (true) {
const arg = ([]const u8)(paths[path_i]);
path_i += 1;
mem.copy(u8, buf[buf_index..], arg);
buf_index += arg.len;
if (path_i >= paths.len) break;
if (buf_index > 0 and buf[buf_index - 1] != sep) {
buf[buf_index] = sep;
buf_index += 1;
}
}
return allocator.shrink(u8, buf, buf_index);
} }
test "os.path.join" { test "os.path.join" {
assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\a\\b", "c"), "c:\\a\\b\\c")); switch (builtin.os) {
assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\a\\b\\", "c"), "c:\\a\\b\\c")); Os.windows => {
assert(mem.eql(u8, try join(debug.global_allocator, [][]const u8{"c:\\a\\b", "c"}), "c:\\a\\b\\c"));
assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\", "a", "b\\", "c"), "c:\\a\\b\\c")); assert(mem.eql(u8, try join(debug.global_allocator, [][]const u8{"c:\\a\\b\\", "c"}), "c:\\a\\b\\c"));
assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\a\\", "b\\", "c"), "c:\\a\\b\\c")); assert(mem.eql(u8, try join(debug.global_allocator, [][]const u8{"c:\\", "a", "b\\", "c"}), "c:\\a\\b\\c"));
assert(mem.eql(u8, try join(debug.global_allocator, [][]const u8{"c:\\a\\", "b\\", "c"}), "c:\\a\\b\\c"));
assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std", "io.zig"), "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig")); assert(mem.eql(u8, try join( debug.global_allocator
, [][]const u8{ "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std"
assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/b", "c"), "/a/b/c")); , "io.zig"})
assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/b/", "c"), "/a/b/c")); , "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig"));
},
assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/", "a", "b/", "c"), "/a/b/c")); else => {
assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/", "b/", "c"), "/a/b/c")); assert(mem.eql(u8, try join(debug.global_allocator, [][]const u8{"/a/b", "c"}), "/a/b/c"));
assert(mem.eql(u8, try join(debug.global_allocator, [][]const u8{"/a/b/", "c"}), "/a/b/c"));
assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/home/andy/dev/zig/build/lib/zig/std", "io.zig"), "/home/andy/dev/zig/build/lib/zig/std/io.zig")); assert(mem.eql(u8, try join(debug.global_allocator, [][]const u8{"/", "a", "b/", "c"}), "/a/b/c"));
assert(mem.eql(u8, try join(debug.global_allocator, [][]const u8{"/a/", "b/", "c"}), "/a/b/c"));
assert(mem.eql(u8, try join( debug.global_allocator
, [][]const u8{ "/home/andy/dev/zig/build/lib/zig/std"
, "io.zig"})
, "/home/andy/dev/zig/build/lib/zig/std/io.zig"));
}
}
} }
pub fn isAbsolute(path: []const u8) bool { pub fn isAbsolute(path: []const u8) bool {
@ -602,7 +625,7 @@ test "os.path.resolveWindows" {
const parsed_cwd = windowsParsePath(cwd); const parsed_cwd = windowsParsePath(cwd);
{ {
const result = testResolveWindows([][]const u8{ "/usr/local", "lib\\zig\\std\\array_list.zig" }); const result = testResolveWindows([][]const u8{ "/usr/local", "lib\\zig\\std\\array_list.zig" });
const expected = try join(debug.global_allocator, parsed_cwd.disk_designator, "usr\\local\\lib\\zig\\std\\array_list.zig"); const expected = try join(debug.global_allocator, [][]const u8{ parsed_cwd.disk_designator, "usr\\local\\lib\\zig\\std\\array_list.zig"});
if (parsed_cwd.kind == WindowsPath.Kind.Drive) { if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
expected[0] = asciiUpper(parsed_cwd.disk_designator[0]); expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
} }
@ -610,7 +633,7 @@ test "os.path.resolveWindows" {
} }
{ {
const result = testResolveWindows([][]const u8{ "usr/local", "lib\\zig" }); const result = testResolveWindows([][]const u8{ "usr/local", "lib\\zig" });
const expected = try join(debug.global_allocator, cwd, "usr\\local\\lib\\zig"); const expected = try join(debug.global_allocator, [][]const u8{ cwd, "usr\\local\\lib\\zig" });
if (parsed_cwd.kind == WindowsPath.Kind.Drive) { if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
expected[0] = asciiUpper(parsed_cwd.disk_designator[0]); expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
} }

View File

@ -29,7 +29,7 @@ pub fn main() !void {
}); });
const zig_exe = try os.path.resolve(a, zig_exe_rel); const zig_exe = try os.path.resolve(a, zig_exe_rel);
const dir_path = try os.path.join(a, cache_root, "clitest"); const dir_path = try os.path.join(a, [][]const u8{ cache_root, "clitest" });
const TestFn = fn ([]const u8, []const u8) anyerror!void; const TestFn = fn ([]const u8, []const u8) anyerror!void;
const test_fns = []TestFn{ const test_fns = []TestFn{
testZigInitLib, testZigInitLib,
@ -99,8 +99,8 @@ fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void {
fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void { fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {
if (builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64) return; if (builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64) return;
const example_zig_path = try os.path.join(a, dir_path, "example.zig"); const example_zig_path = try os.path.join(a, [][]const u8{ dir_path, "example.zig" });
const example_s_path = try os.path.join(a, dir_path, "example.s"); const example_s_path = try os.path.join(a, [][]const u8{ dir_path, "example.s" });
try std.io.writeFile(example_zig_path, try std.io.writeFile(example_zig_path,
\\// Type your code here, or load an example. \\// Type your code here, or load an example.

View File

@ -439,7 +439,7 @@ pub const CompareOutputContext = struct {
pub fn addCase(self: *CompareOutputContext, case: TestCase) void { pub fn addCase(self: *CompareOutputContext, case: TestCase) void {
const b = self.b; const b = self.b;
const root_src = os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename) catch unreachable; const root_src = os.path.join(b.allocator, [][]const u8{b.cache_root, case.sources.items[0].filename}) catch unreachable;
switch (case.special) { switch (case.special) {
Special.Asm => { Special.Asm => {
@ -452,7 +452,7 @@ pub const CompareOutputContext = struct {
exe.addAssemblyFile(root_src); exe.addAssemblyFile(root_src);
for (case.sources.toSliceConst()) |src_file| { for (case.sources.toSliceConst()) |src_file| {
const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; const expanded_src_path = os.path.join(b.allocator, [][]const u8{b.cache_root, src_file.filename}) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source); const write_src = b.addWriteFile(expanded_src_path, src_file.source);
exe.step.dependOn(&write_src.step); exe.step.dependOn(&write_src.step);
} }
@ -476,7 +476,7 @@ pub const CompareOutputContext = struct {
} }
for (case.sources.toSliceConst()) |src_file| { for (case.sources.toSliceConst()) |src_file| {
const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; const expanded_src_path = os.path.join(b.allocator, [][]const u8{b.cache_root, src_file.filename}) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source); const write_src = b.addWriteFile(expanded_src_path, src_file.source);
exe.step.dependOn(&write_src.step); exe.step.dependOn(&write_src.step);
} }
@ -499,7 +499,7 @@ pub const CompareOutputContext = struct {
} }
for (case.sources.toSliceConst()) |src_file| { for (case.sources.toSliceConst()) |src_file| {
const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; const expanded_src_path = os.path.join(b.allocator, [][]const u8{b.cache_root, src_file.filename}) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source); const write_src = b.addWriteFile(expanded_src_path, src_file.source);
exe.step.dependOn(&write_src.step); exe.step.dependOn(&write_src.step);
} }
@ -572,8 +572,8 @@ pub const CompileErrorContext = struct {
const self = @fieldParentPtr(CompileCmpOutputStep, "step", step); const self = @fieldParentPtr(CompileCmpOutputStep, "step", step);
const b = self.context.b; const b = self.context.b;
const root_src = os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename) catch unreachable; const root_src = os.path.join(b.allocator, [][]const u8{b.cache_root, self.case.sources.items[0].filename}) catch unreachable;
const obj_path = os.path.join(b.allocator, b.cache_root, "test.o") catch unreachable; const obj_path = os.path.join(b.allocator, [][]const u8{b.cache_root, "test.o"}) catch unreachable;
var zig_args = ArrayList([]const u8).init(b.allocator); var zig_args = ArrayList([]const u8).init(b.allocator);
zig_args.append(b.zig_exe) catch unreachable; zig_args.append(b.zig_exe) catch unreachable;
@ -721,7 +721,7 @@ pub const CompileErrorContext = struct {
self.step.dependOn(&compile_and_cmp_errors.step); self.step.dependOn(&compile_and_cmp_errors.step);
for (case.sources.toSliceConst()) |src_file| { for (case.sources.toSliceConst()) |src_file| {
const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; const expanded_src_path = os.path.join(b.allocator, [][]const u8{b.cache_root, src_file.filename}) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source); const write_src = b.addWriteFile(expanded_src_path, src_file.source);
compile_and_cmp_errors.step.dependOn(&write_src.step); compile_and_cmp_errors.step.dependOn(&write_src.step);
} }
@ -852,7 +852,7 @@ pub const TranslateCContext = struct {
const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step); const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step);
const b = self.context.b; const b = self.context.b;
const root_src = os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename) catch unreachable; const root_src = os.path.join(b.allocator, [][]const u8{b.cache_root, self.case.sources.items[0].filename}) catch unreachable;
var zig_args = ArrayList([]const u8).init(b.allocator); var zig_args = ArrayList([]const u8).init(b.allocator);
zig_args.append(b.zig_exe) catch unreachable; zig_args.append(b.zig_exe) catch unreachable;
@ -986,7 +986,7 @@ pub const TranslateCContext = struct {
self.step.dependOn(&translate_c_and_cmp.step); self.step.dependOn(&translate_c_and_cmp.step);
for (case.sources.toSliceConst()) |src_file| { for (case.sources.toSliceConst()) |src_file| {
const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; const expanded_src_path = os.path.join(b.allocator, [][]const u8{b.cache_root, src_file.filename}) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source); const write_src = b.addWriteFile(expanded_src_path, src_file.source);
translate_c_and_cmp.step.dependOn(&write_src.step); translate_c_and_cmp.step.dependOn(&write_src.step);
} }
@ -1101,7 +1101,7 @@ pub const GenHContext = struct {
pub fn addCase(self: *GenHContext, case: *const TestCase) void { pub fn addCase(self: *GenHContext, case: *const TestCase) void {
const b = self.b; const b = self.b;
const root_src = os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename) catch unreachable; const root_src = os.path.join(b.allocator, [][]const u8{b.cache_root, case.sources.items[0].filename}) catch unreachable;
const mode = builtin.Mode.Debug; const mode = builtin.Mode.Debug;
const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable; const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable;
@ -1113,7 +1113,7 @@ pub const GenHContext = struct {
obj.setBuildMode(mode); obj.setBuildMode(mode);
for (case.sources.toSliceConst()) |src_file| { for (case.sources.toSliceConst()) |src_file| {
const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; const expanded_src_path = os.path.join(b.allocator, [][]const u8{b.cache_root, src_file.filename}) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source); const write_src = b.addWriteFile(expanded_src_path, src_file.source);
obj.step.dependOn(&write_src.step); obj.step.dependOn(&write_src.step);
} }