diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index 9aa7b39c9b..f802cbd606 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -14,11 +14,11 @@ usingnamespace @import("windows_sdk.zig"); /// See the render function implementation for documentation of the fields. pub const LibCInstallation = struct { - include_dir: ?[:0]const u8 = null, - sys_include_dir: ?[:0]const u8 = null, - crt_dir: ?[:0]const u8 = null, - msvc_lib_dir: ?[:0]const u8 = null, - kernel32_lib_dir: ?[:0]const u8 = null, + include_dir: ?[]const u8 = null, + sys_include_dir: ?[]const u8 = null, + crt_dir: ?[]const u8 = null, + msvc_lib_dir: ?[]const u8 = null, + kernel32_lib_dir: ?[]const u8 = null, pub const FindError = error{ OutOfMemory, @@ -327,15 +327,20 @@ pub const LibCInstallation = struct { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); - var result_buf = try std.Buffer.initSize(allocator, 0); - defer result_buf.deinit(); - for (searches) |search| { - result_buf.shrink(0); - const stream = result_buf.outStream(); - try stream.print("{}\\Include\\{}\\ucrt", .{ search.path, search.version }); + const dir_path = try fs.path.join( + allocator, + &[_][]const u8{ + search.path, + "Include", + search.version, + "ucrt", + }, + ); + var found = false; + defer if (!found) allocator.free(dir_path); - var dir = fs.cwd().openDir(result_buf.span(), .{}) catch |err| switch (err) { + var dir = fs.cwd().openDir(dir_path, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -350,7 +355,8 @@ pub const LibCInstallation = struct { else => return error.FileSystem, }; - self.include_dir = result_buf.toOwnedSlice(); + found = true; + self.include_dir = dir_path; return; } @@ -367,9 +373,6 @@ pub const LibCInstallation = struct { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); - var result_buf = try std.Buffer.initSize(allocator, 0); - defer result_buf.deinit(); - const arch_sub_dir = switch (builtin.arch) { .i386 => "x86", .x86_64 => "x64", @@ -378,11 +381,20 @@ pub const LibCInstallation = struct { }; for (searches) |search| { - result_buf.shrink(0); - const stream = result_buf.outStream(); - try stream.print("{}\\Lib\\{}\\ucrt\\{}", .{ search.path, search.version, arch_sub_dir }); + const dir_path = try fs.path.join( + allocator, + &[_][]const u8{ + search.path, + "Lib", + search.version, + "ucrt", + arch_sub_dir, + }, + ); + var found = false; + defer if (!found) allocator.free(dir_path); - var dir = fs.cwd().openDir(result_buf.span(), .{}) catch |err| switch (err) { + var dir = fs.cwd().openDir(dir_path, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -397,7 +409,8 @@ pub const LibCInstallation = struct { else => return error.FileSystem, }; - self.crt_dir = result_buf.toOwnedSlice(); + found = true; + self.crt_dir = dir_path; return; } return error.LibCRuntimeNotFound; @@ -421,10 +434,6 @@ pub const LibCInstallation = struct { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); - - var result_buf = try std.Buffer.initSize(allocator, 0); - defer result_buf.deinit(); - const arch_sub_dir = switch (builtin.arch) { .i386 => "x86", .x86_64 => "x64", @@ -433,11 +442,20 @@ pub const LibCInstallation = struct { }; for (searches) |search| { - result_buf.shrink(0); - const stream = result_buf.outStream(); - try stream.print("{}\\Lib\\{}\\um\\{}", .{ search.path, search.version, arch_sub_dir }); + const dir_path = try fs.path.join( + allocator, + &[_][]const u8{ + search.path, + "Lib", + search.version, + "um", + arch_sub_dir, + }, + ); + var found = false; + defer if (!found) allocator.free(dir_path); - var dir = fs.cwd().openDir(result_buf.span(), .{}) catch |err| switch (err) { + var dir = fs.cwd().openDir(dir_path, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -452,7 +470,8 @@ pub const LibCInstallation = struct { else => return error.FileSystem, }; - self.kernel32_lib_dir = result_buf.toOwnedSlice(); + found = true; + self.kernel32_lib_dir = dir_path; return; } return error.LibCKernel32LibNotFound; @@ -470,12 +489,16 @@ pub const LibCInstallation = struct { const up1 = fs.path.dirname(msvc_lib_dir) orelse return error.LibCStdLibHeaderNotFound; const up2 = fs.path.dirname(up1) orelse return error.LibCStdLibHeaderNotFound; - var result_buf = try std.Buffer.init(allocator, up2); - defer result_buf.deinit(); + const dir_path = try fs.path.join( + allocator, + &[_][]const u8{ + up2, + "include", + }, + ); + errdefer allocator.free(dir_path); - try result_buf.append("\\include"); - - var dir = fs.cwd().openDir(result_buf.span(), .{}) catch |err| switch (err) { + var dir = fs.cwd().openDir(dir_path, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -490,7 +513,7 @@ pub const LibCInstallation = struct { else => return error.FileSystem, }; - self.sys_include_dir = result_buf.toOwnedSlice(); + self.sys_include_dir = dir_path; } fn findNativeMsvcLibDir( diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 92eb04539a..771765bee6 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -741,15 +741,15 @@ fn stage2TargetParse( // ABI warning const Stage2LibCInstallation = extern struct { - include_dir: [*:0]const u8, + include_dir: [*]const u8, include_dir_len: usize, - sys_include_dir: [*:0]const u8, + sys_include_dir: [*]const u8, sys_include_dir_len: usize, - crt_dir: [*:0]const u8, + crt_dir: [*]const u8, crt_dir_len: usize, - msvc_lib_dir: [*:0]const u8, + msvc_lib_dir: [*]const u8, msvc_lib_dir_len: usize, - kernel32_lib_dir: [*:0]const u8, + kernel32_lib_dir: [*]const u8, kernel32_lib_dir_len: usize, fn initFromStage2(self: *Stage2LibCInstallation, libc: LibCInstallation) void { @@ -793,19 +793,19 @@ const Stage2LibCInstallation = extern struct { fn toStage2(self: Stage2LibCInstallation) LibCInstallation { var libc: LibCInstallation = .{}; if (self.include_dir_len != 0) { - libc.include_dir = self.include_dir[0..self.include_dir_len :0]; + libc.include_dir = self.include_dir[0..self.include_dir_len]; } if (self.sys_include_dir_len != 0) { - libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len :0]; + libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len]; } if (self.crt_dir_len != 0) { - libc.crt_dir = self.crt_dir[0..self.crt_dir_len :0]; + libc.crt_dir = self.crt_dir[0..self.crt_dir_len]; } if (self.msvc_lib_dir_len != 0) { - libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len :0]; + libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len]; } if (self.kernel32_lib_dir_len != 0) { - libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len :0]; + libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len]; } return libc; } diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp index 3cff34ea5c..c12d8f29ef 100644 --- a/src/cache_hash.cpp +++ b/src/cache_hash.cpp @@ -27,11 +27,17 @@ void cache_init(CacheHash *ch, Buf *manifest_dir) { void cache_mem(CacheHash *ch, const char *ptr, size_t len) { assert(ch->manifest_file_path == nullptr); assert(ptr != nullptr); - // + 1 to include the null byte blake2b_update(&ch->blake, ptr, len); } +void cache_slice(CacheHash *ch, Slice slice) { + // mix the length into the hash so that two juxtaposed cached slices can't collide + cache_usize(ch, slice.len); + cache_mem(ch, slice.ptr, slice.len); +} + void cache_str(CacheHash *ch, const char *ptr) { + // + 1 to include the null byte cache_mem(ch, ptr, strlen(ptr) + 1); } diff --git a/src/cache_hash.hpp b/src/cache_hash.hpp index 9e4c41b1e0..ba2434076a 100644 --- a/src/cache_hash.hpp +++ b/src/cache_hash.hpp @@ -36,6 +36,7 @@ void cache_init(CacheHash *ch, Buf *manifest_dir); // Next, use the hash population functions to add the initial parameters. void cache_mem(CacheHash *ch, const char *ptr, size_t len); +void cache_slice(CacheHash *ch, Slice slice); void cache_str(CacheHash *ch, const char *ptr); void cache_int(CacheHash *ch, int x); void cache_bool(CacheHash *ch, bool x); diff --git a/src/codegen.cpp b/src/codegen.cpp index d36e398bf7..2c2bf7c36b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -9123,21 +9123,26 @@ static void detect_libc(CodeGen *g) { g->libc_include_dir_len = 0; g->libc_include_dir_list = heap::c_allocator.allocate(dir_count); - g->libc_include_dir_list[g->libc_include_dir_len] = g->libc->include_dir; + g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_create_from_mem(g->libc->include_dir, g->libc->include_dir_len)); g->libc_include_dir_len += 1; if (want_sys_dir) { - g->libc_include_dir_list[g->libc_include_dir_len] = g->libc->sys_include_dir; + g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_create_from_mem(g->libc->sys_include_dir, g->libc->sys_include_dir_len)); g->libc_include_dir_len += 1; } if (want_um_and_shared_dirs != 0) { - g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_sprintf( - "%s" OS_SEP ".." OS_SEP "um", g->libc->include_dir)); + Buf *include_dir_parent = buf_alloc(); + os_path_join(buf_create_from_mem(g->libc->include_dir, g->libc->include_dir_len), buf_create_from_str(".."), include_dir_parent); + + Buf *buff1 = buf_alloc(); + os_path_join(include_dir_parent, buf_create_from_str("um"), buff1); + g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buff1); g->libc_include_dir_len += 1; - g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_sprintf( - "%s" OS_SEP ".." OS_SEP "shared", g->libc->include_dir)); + Buf *buff2 = buf_alloc(); + os_path_join(include_dir_parent, buf_create_from_str("shared"), buff2); + g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buff2); g->libc_include_dir_len += 1; } assert(g->libc_include_dir_len == dir_count); @@ -10546,11 +10551,11 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length); cache_list_of_str(ch, g->framework_dirs.items, g->framework_dirs.length); if (g->libc) { - cache_str(ch, g->libc->include_dir); - cache_str(ch, g->libc->sys_include_dir); - cache_str(ch, g->libc->crt_dir); - cache_str(ch, g->libc->msvc_lib_dir); - cache_str(ch, g->libc->kernel32_lib_dir); + cache_slice(ch, Slice{g->libc->include_dir, g->libc->include_dir_len}); + cache_slice(ch, Slice{g->libc->sys_include_dir, g->libc->sys_include_dir_len}); + cache_slice(ch, Slice{g->libc->crt_dir, g->libc->crt_dir_len}); + cache_slice(ch, Slice{g->libc->msvc_lib_dir, g->libc->msvc_lib_dir_len}); + cache_slice(ch, Slice{g->libc->kernel32_lib_dir, g->libc->kernel32_lib_dir_len}); } cache_buf_opt(ch, g->version_script_path); cache_buf_opt(ch, g->override_soname); diff --git a/src/link.cpp b/src/link.cpp index 0d7a8a410b..49bbb7c1a5 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -1595,7 +1595,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr } else { assert(parent->libc != nullptr); Buf *out_buf = buf_alloc(); - os_path_join(buf_create_from_str(parent->libc->crt_dir), buf_create_from_str(file), out_buf); + os_path_join(buf_create_from_mem(parent->libc->crt_dir, parent->libc->crt_dir_len), buf_create_from_str(file), out_buf); return buf_ptr(out_buf); } } @@ -1860,7 +1860,7 @@ static void construct_linker_job_elf(LinkJob *lj) { if (g->libc_link_lib != nullptr) { if (g->libc != nullptr) { lj->args.append("-L"); - lj->args.append(g->libc->crt_dir); + lj->args.append(buf_ptr(buf_create_from_mem(g->libc->crt_dir, g->libc->crt_dir_len))); } if (g->have_dynamic_link && (is_dyn_lib || g->out_type == OutTypeExe)) { @@ -2381,14 +2381,26 @@ static void construct_linker_job_coff(LinkJob *lj) { lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->bin_file_output_path)))); if (g->libc_link_lib != nullptr && g->libc != nullptr) { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->crt_dir))); + Buf *buff0 = buf_create_from_str("-LIBPATH:"); + buf_append_mem(buff0, g->libc->crt_dir, g->libc->crt_dir_len); + lj->args.append(buf_ptr(buff0)); if (target_abi_is_gnu(g->zig_target->abi)) { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->sys_include_dir))); - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->include_dir))); + Buf *buff1 = buf_create_from_str("-LIBPATH:"); + buf_append_mem(buff1, g->libc->sys_include_dir, g->libc->sys_include_dir_len); + lj->args.append(buf_ptr(buff1)); + + Buf *buff2 = buf_create_from_str("-LIBPATH:"); + buf_append_mem(buff2, g->libc->include_dir, g->libc->include_dir_len); + lj->args.append(buf_ptr(buff2)); } else { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->msvc_lib_dir))); - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->kernel32_lib_dir))); + Buf *buff1 = buf_create_from_str("-LIBPATH:"); + buf_append_mem(buff1, g->libc->msvc_lib_dir, g->libc->msvc_lib_dir_len); + lj->args.append(buf_ptr(buff1)); + + Buf *buff2 = buf_create_from_str("-LIBPATH:"); + buf_append_mem(buff2, g->libc->kernel32_lib_dir, g->libc->kernel32_lib_dir_len); + lj->args.append(buf_ptr(buff2)); } }