diff --git a/build.zig b/build.zig index a41a5f808..b90f58ff5 100644 --- a/build.zig +++ b/build.zig @@ -16,7 +16,7 @@ pub fn build(b: *Builder) !void { 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 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{ docgen_exe.getOutputPath(), rel_zig_exe, @@ -125,13 +125,13 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void { for (dep.libdirs.toSliceConst()) |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| { const static_bare_name = if (mem.eql(u8, lib, "curses")) ([]const u8)("libncurses.a") else 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; if (have_static) { 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 { 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 { @@ -235,8 +235,8 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void { var it = mem.tokenize(stdlib_files, ";"); while (it.next()) |stdlib_file| { - const src_path = os.path.join(b.allocator, "std", stdlib_file) catch unreachable; - const dest_path = os.path.join(b.allocator, "lib", "zig", "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, [][]const u8{"lib", "zig", "std", stdlib_file}) catch unreachable; 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 { var it = mem.tokenize(c_header_files, ";"); while (it.next()) |c_header_file| { - const src_path = os.path.join(b.allocator, "c_headers", c_header_file) catch unreachable; - const dest_path = os.path.join(b.allocator, "lib", "zig", "include", 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, [][]const u8{"lib", "zig", "include", c_header_file}) catch unreachable; b.installFile(src_path, dest_path); } } diff --git a/doc/docgen.zig b/doc/docgen.zig index 2489e034b..8b2a7e4c1 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -990,13 +990,13 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var try tokenizeAndPrint(tokenizer, out, code.source_token); try out.write(""); 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); switch (code.id) { Code.Id.Exe => |expected_outcome| { 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); defer build_args.deinit(); 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| { 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(full_path_object); 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| { 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); defer build_args.deinit(); 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{ zig_exe, diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig index d60892432..e55d8ccda 100644 --- a/src-self-hosted/compilation.zig +++ b/src-self-hosted/compilation.zig @@ -487,7 +487,7 @@ pub const Compilation = struct { comp.name = try Buffer.init(comp.arena(), name); comp.llvm_triple = try target.getTriple(comp.arena()); 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) { 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); 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); return Buffer.fromOwnedSlice(self.gpa(), full_path); @@ -1219,7 +1219,7 @@ pub const Compilation = struct { const zig_dir_path = try getZigDir(self.gpa()); 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); return tmp_dir; } diff --git a/src-self-hosted/introspect.zig b/src-self-hosted/introspect.zig index d41f82f75..0a7f63b4f 100644 --- a/src-self-hosted/introspect.zig +++ b/src-self-hosted/introspect.zig @@ -8,10 +8,10 @@ const warn = std.debug.warn; /// Caller must free result 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); - 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); var file = try os.File.openRead(test_index_file); diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index 18d2daf0c..682e10c36 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -230,7 +230,7 @@ pub const LibCInstallation = struct { 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 = 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); if (try fileExists(stdlib_path)) { @@ -254,7 +254,7 @@ pub const LibCInstallation = struct { const stream = &std.io.BufferOutStream.init(&result_buf).stream; 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); if (try fileExists(stdlib_path)) { @@ -283,7 +283,7 @@ pub const LibCInstallation = struct { builtin.Arch.aarch64v8 => try stream.write("arm"), 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); if (try fileExists(ucrt_lib_path)) { self.lib_dir = result_buf.toOwnedSlice(); @@ -358,7 +358,7 @@ pub const LibCInstallation = struct { builtin.Arch.aarch64v8 => try stream.write("arm\\"), 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); if (try fileExists(kernel32_path)) { self.kernel32_lib_dir = result_buf.toOwnedSlice(); diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index 1b32533eb..fadc9b018 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -315,7 +315,7 @@ fn constructLinkerArgsElf(ctx: *Context) !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); try ctx.args.append(full_path_with_null.ptr); } diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index f6ee9a051..64aa72946 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -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); while (try dir.next()) |entry| { 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); } } diff --git a/src-self-hosted/test.zig b/src-self-hosted/test.zig index ff5b96df8..de551cf7f 100644 --- a/src-self-hosted/test.zig +++ b/src-self-hosted/test.zig @@ -87,7 +87,7 @@ pub const TestContext = struct { ) !void { var file_index_buf: [20]u8 = undefined; 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| { try std.os.makePath(allocator, dirname); @@ -120,7 +120,7 @@ pub const TestContext = struct { ) !void { var file_index_buf: [20]u8 = undefined; 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()); if (std.os.path.dirname(file1_path)) |dirname| { diff --git a/std/build.zig b/std/build.zig index 07efcec30..1348396f5 100644 --- a/std/build.zig +++ b/std/build.zig @@ -145,8 +145,8 @@ pub const Builder = struct { pub fn setInstallPrefix(self: *Builder, maybe_prefix: ?[]const u8) void { self.prefix = maybe_prefix orelse "/usr/local"; // TODO better default - self.lib_dir = os.path.join(self.allocator, self.prefix, "lib") catch unreachable; - self.exe_dir = os.path.join(self.allocator, self.prefix, "bin") 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, [][]const u8{self.prefix, "bin"}) catch unreachable; } 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)) { 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| { return real_path; } else |_| { @@ -691,7 +691,7 @@ pub const Builder = struct { } var it = mem.tokenize(PATH, []u8{os.path.delimiter}); 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| { return real_path; } else |_| { @@ -705,7 +705,7 @@ pub const Builder = struct { return name; } 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| { return real_path; } else |_| { @@ -1113,7 +1113,7 @@ pub const LibExeObjStep = struct { } 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 { @@ -1126,7 +1126,7 @@ pub const LibExeObjStep = struct { } 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 { @@ -1226,7 +1226,7 @@ pub const LibExeObjStep = struct { } 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 zig_args.append("--pkg-begin"); try zig_args.append("build_options"); @@ -1476,7 +1476,7 @@ pub const LibExeObjStep = struct { cc_args.append("-c") 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| { try builder.makePath(cache_o_dir); } @@ -1528,7 +1528,7 @@ pub const LibExeObjStep = struct { cc_args.append("-current_version") 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; } else { @@ -1594,7 +1594,7 @@ pub const LibExeObjStep = struct { cc_args.append("-c") 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| { try builder.makePath(cache_o_dir); } @@ -1757,7 +1757,7 @@ pub const TestStep = struct { return output_path; } else { 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), .artifact = artifact, .dest_file = os.path.join(builder.allocator, dest_dir, artifact.out_filename) catch unreachable, - }; + }) catch unreachable; self.step.dependOn(&artifact.step); builder.pushInstalledFile(self.dest_file); 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, builder.lib_dir, artifact.name_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, [][]const u8{builder.lib_dir, artifact.name_only_filename}) catch unreachable); } 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_basename = os.path.basename(output_path); // 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| { warn("Unable to symlink {} -> {}\n", major_only_path, out_basename); return err; }; // 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| { warn("Unable to symlink {} -> {}\n", name_only_path, filename_major_only); return err; diff --git a/std/debug/index.zig b/std/debug/index.zig index b4ef84950..0253912d3 100644 --- a/std/debug/index.zig +++ b/std/debug/index.zig @@ -1352,7 +1352,7 @@ const LineNumberProgram = struct { return error.InvalidDebugInfo; } else 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); return LineInfo{ .line = if (self.prev_line >= 0) @intCast(usize, self.prev_line) else 0, diff --git a/std/event/fs.zig b/std/event/fs.zig index 097f2bedd..97a79bed3 100644 --- a/std/event/fs.zig +++ b/std/event/fs.zig @@ -1336,7 +1336,7 @@ async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) 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); const contents = diff --git a/std/os/child_process.zig b/std/os/child_process.zig index 871f9dd70..2651310c9 100644 --- a/std/os/child_process.zig +++ b/std/os/child_process.zig @@ -597,7 +597,7 @@ pub const ChildProcess = struct { var it = mem.tokenize(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); const joined_path_w = try unicode.utf8ToUtf16LeWithNull(self.allocator, joined_path); diff --git a/std/os/get_app_data_dir.zig b/std/os/get_app_data_dir.zig index ae133bb4b..a0315b451 100644 --- a/std/os/get_app_data_dir.zig +++ b/std/os/get_app_data_dir.zig @@ -30,7 +30,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD error.OutOfMemory => return error.OutOfMemory, }; 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, else => return error.AppDataDirUnavailable, @@ -41,14 +41,14 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD // TODO look in /etc/passwd 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 => { const home_dir = os.getEnvPosix("HOME") orelse { // TODO look in /etc/passwd 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"), } diff --git a/std/os/path.zig b/std/os/path.zig index 0b960fa2d..5a5b1b777 100644 --- a/std/os/path.zig +++ b/std/os/path.zig @@ -35,38 +35,61 @@ pub fn isSep(byte: u8) bool { /// Naively combines a series of paths with the native path seperator. /// Allocates memory for the result, which must be freed by the caller. -pub fn join(allocator: *Allocator, paths: ...) ![]u8 { - if (is_windows) { - return joinWindows(allocator, paths); - } else { - return joinPosix(allocator, paths); + +pub fn join(allocator: *Allocator, paths: []const []const u8) ![]u8 { + assert(paths.len >= 1); + var total_paths_len: usize = paths.len; // 1 sep per path + { + 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 { - return mem.join(allocator, sep_windows, paths); -} + const buf = try allocator.alloc(u8, total_paths_len); + errdefer allocator.free(buf); -pub fn joinPosix(allocator: *Allocator, paths: ...) ![]u8 { - return mem.join(allocator, sep_posix, paths); + var buf_index: usize = 0; + 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" { - assert(mem.eql(u8, try joinWindows(debug.global_allocator, "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 joinWindows(debug.global_allocator, "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 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 joinPosix(debug.global_allocator, "/a/b", "c"), "/a/b/c")); - assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/b/", "c"), "/a/b/c")); - - assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/", "a", "b/", "c"), "/a/b/c")); - assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/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")); + switch (builtin.os) { + 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 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 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:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std" + , "io.zig"}) + , "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig")); + }, + else => { + 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{"/", "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 { @@ -602,7 +625,7 @@ test "os.path.resolveWindows" { const parsed_cwd = windowsParsePath(cwd); { 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) { 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 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) { expected[0] = asciiUpper(parsed_cwd.disk_designator[0]); } diff --git a/test/cli.zig b/test/cli.zig index a07c447d2..0980e8c2d 100644 --- a/test/cli.zig +++ b/test/cli.zig @@ -29,7 +29,7 @@ pub fn main() !void { }); 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 test_fns = []TestFn{ 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 { 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_s_path = try os.path.join(a, dir_path, "example.s"); + const example_zig_path = try os.path.join(a, [][]const u8{ dir_path, "example.zig" }); + const example_s_path = try os.path.join(a, [][]const u8{ dir_path, "example.s" }); try std.io.writeFile(example_zig_path, \\// Type your code here, or load an example. diff --git a/test/tests.zig b/test/tests.zig index fc188f555..fac941cbd 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -439,7 +439,7 @@ pub const CompareOutputContext = struct { pub fn addCase(self: *CompareOutputContext, case: TestCase) void { 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) { Special.Asm => { @@ -452,7 +452,7 @@ pub const CompareOutputContext = struct { exe.addAssemblyFile(root_src); 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); exe.step.dependOn(&write_src.step); } @@ -476,7 +476,7 @@ pub const CompareOutputContext = struct { } 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); exe.step.dependOn(&write_src.step); } @@ -499,7 +499,7 @@ pub const CompareOutputContext = struct { } 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); exe.step.dependOn(&write_src.step); } @@ -572,8 +572,8 @@ pub const CompileErrorContext = struct { const self = @fieldParentPtr(CompileCmpOutputStep, "step", step); 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 obj_path = os.path.join(b.allocator, b.cache_root, "test.o") 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, [][]const u8{b.cache_root, "test.o"}) catch unreachable; var zig_args = ArrayList([]const u8).init(b.allocator); zig_args.append(b.zig_exe) catch unreachable; @@ -721,7 +721,7 @@ pub const CompileErrorContext = struct { self.step.dependOn(&compile_and_cmp_errors.step); 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); compile_and_cmp_errors.step.dependOn(&write_src.step); } @@ -852,7 +852,7 @@ pub const TranslateCContext = struct { const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step); 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); zig_args.append(b.zig_exe) catch unreachable; @@ -986,7 +986,7 @@ pub const TranslateCContext = struct { self.step.dependOn(&translate_c_and_cmp.step); 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); 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 { 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 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); 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); obj.step.dependOn(&write_src.step); }