From 4462c60639807502eca8a2db2bcf6adafea496ef Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Aug 2020 18:56:27 -0700 Subject: [PATCH] stage2: implement compiler id hash and add it to `zig env` --- src-self-hosted/introspect.zig | 52 ++++++++++++++++++++++++++++++++-- src-self-hosted/print_env.zig | 7 +++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src-self-hosted/introspect.zig b/src-self-hosted/introspect.zig index 46405a2b70..8e99c93c60 100644 --- a/src-self-hosted/introspect.zig +++ b/src-self-hosted/introspect.zig @@ -3,8 +3,7 @@ const std = @import("std"); const mem = std.mem; const fs = std.fs; - -const warn = std.debug.warn; +const CacheHash = std.cache_hash.CacheHash; /// Caller must free result pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 { @@ -63,7 +62,7 @@ pub fn findZigLibDir(allocator: *mem.Allocator) ![]u8 { pub fn resolveZigLibDir(allocator: *mem.Allocator) ![]u8 { return findZigLibDir(allocator) catch |err| { - warn( + std.debug.print( \\Unable to find zig lib directory: {}. \\Reinstall Zig or use --zig-install-prefix. \\ @@ -87,3 +86,50 @@ pub fn resolveGlobalCacheDir(allocator: *mem.Allocator) ![]u8 { return fs.getAppDataDir(allocator, appname); } + +var compiler_id_mutex = std.Mutex{}; +var compiler_id: [16]u8 = undefined; +var compiler_id_computed = false; + +pub fn resolveCompilerId(gpa: *mem.Allocator) ![16]u8 { + const held = compiler_id_mutex.acquire(); + defer held.release(); + + if (compiler_id_computed) + return compiler_id; + compiler_id_computed = true; + + const global_cache_dir = try resolveGlobalCacheDir(gpa); + defer gpa.free(global_cache_dir); + + // TODO Introduce openGlobalCacheDir which returns a dir handle rather than a string. + var cache_dir = try fs.cwd().openDir(global_cache_dir, .{}); + defer cache_dir.close(); + + var ch = try CacheHash.init(gpa, cache_dir, "exe"); + defer ch.release(); + + const self_exe_path = try fs.selfExePathAlloc(gpa); + defer gpa.free(self_exe_path); + + _ = try ch.addFile(self_exe_path, null); + + if (try ch.hit()) |digest| { + compiler_id = digest[0..16].*; + return compiler_id; + } + + const libs = try std.process.getSelfExeSharedLibPaths(gpa); + defer { + for (libs) |lib| gpa.free(lib); + gpa.free(libs); + } + + for (libs) |lib| { + try ch.addFilePost(lib); + } + + const digest = ch.final(); + compiler_id = digest[0..16].*; + return compiler_id; +} diff --git a/src-self-hosted/print_env.zig b/src-self-hosted/print_env.zig index 907e9e234d..9b68633d3e 100644 --- a/src-self-hosted/print_env.zig +++ b/src-self-hosted/print_env.zig @@ -16,6 +16,10 @@ pub fn cmdEnv(gpa: *Allocator, args: []const []const u8, stdout: anytype) !void const global_cache_dir = try introspect.resolveGlobalCacheDir(gpa); defer gpa.free(global_cache_dir); + const compiler_id_digest = try introspect.resolveCompilerId(gpa); + var compiler_id_buf: [compiler_id_digest.len * 2]u8 = undefined; + const compiler_id = std.fmt.bufPrint(&compiler_id_buf, "{x}", .{compiler_id_digest}) catch unreachable; + var bos = std.io.bufferedOutStream(stdout); const bos_stream = bos.outStream(); @@ -28,6 +32,9 @@ pub fn cmdEnv(gpa: *Allocator, args: []const []const u8, stdout: anytype) !void try jws.objectField("std_dir"); try jws.emitString(zig_std_dir); + try jws.objectField("id"); + try jws.emitString(compiler_id); + try jws.objectField("global_cache_dir"); try jws.emitString(global_cache_dir);