Commit 4462c60639

Andrew Kelley <andrew@ziglang.org>
2020-08-18 03:56:27
stage2: implement compiler id hash and add it to `zig env`
1 parent a916f63
Changed files (2)
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;
+}
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);