Commit 19aab5302c

Evan Haas <evan@lagerdata.com>
2021-05-01 08:07:40
translate-c: Ensure extra_cflags are passed to clang
Additionally ensure that the Zig cache incorporates any extra cflags when using translate-c. Fixes the issue identified in #8662
1 parent 43da102
src/Cache.zig
@@ -11,6 +11,7 @@ const testing = std.testing;
 const mem = std.mem;
 const fmt = std.fmt;
 const Allocator = std.mem.Allocator;
+const Compilation = @import("Compilation.zig");
 
 /// Be sure to call `Manifest.deinit` after successful initialization.
 pub fn obtain(cache: *const Cache) Manifest {
@@ -61,7 +62,7 @@ pub const File = struct {
 pub const HashHelper = struct {
     hasher: Hasher = hasher_init,
 
-    const EmitLoc = @import("Compilation.zig").EmitLoc;
+    const EmitLoc = Compilation.EmitLoc;
 
     /// Record a slice of bytes as an dependency of the process being cached
     pub fn addBytes(hh: *HashHelper, bytes: []const u8) void {
@@ -220,6 +221,24 @@ pub const Manifest = struct {
         return idx;
     }
 
+    pub fn hashCSource(self: *Manifest, c_source: Compilation.CSourceFile) !void {
+        _ = try self.addFile(c_source.src_path, null);
+        // Hash the extra flags, with special care to call addFile for file parameters.
+        // TODO this logic can likely be improved by utilizing clang_options_data.zig.
+        const file_args = [_][]const u8{"-include"};
+        var arg_i: usize = 0;
+        while (arg_i < c_source.extra_flags.len) : (arg_i += 1) {
+            const arg = c_source.extra_flags[arg_i];
+            self.hash.addBytes(arg);
+            for (file_args) |file_arg| {
+                if (mem.eql(u8, file_arg, arg) and arg_i + 1 < c_source.extra_flags.len) {
+                    arg_i += 1;
+                    _ = try self.addFile(c_source.extra_flags[arg_i], null);
+                }
+            }
+        }
+    }
+
     pub fn addOptionalFile(self: *Manifest, optional_file_path: ?[]const u8) !void {
         self.hash.add(optional_file_path != null);
         const file_path = optional_file_path orelse return;
src/Compilation.zig
@@ -2260,23 +2260,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_comp_progress_node: *
 
     man.hash.add(comp.clang_preprocessor_mode);
 
-    _ = try man.addFile(c_object.src.src_path, null);
-    {
-        // Hash the extra flags, with special care to call addFile for file parameters.
-        // TODO this logic can likely be improved by utilizing clang_options_data.zig.
-        const file_args = [_][]const u8{"-include"};
-        var arg_i: usize = 0;
-        while (arg_i < c_object.src.extra_flags.len) : (arg_i += 1) {
-            const arg = c_object.src.extra_flags[arg_i];
-            man.hash.addBytes(arg);
-            for (file_args) |file_arg| {
-                if (mem.eql(u8, file_arg, arg) and arg_i + 1 < c_object.src.extra_flags.len) {
-                    arg_i += 1;
-                    _ = try man.addFile(c_object.src.extra_flags[arg_i], null);
-                }
-            }
-        }
-    }
+    try man.hashCSource(c_object.src);
 
     {
         const is_collision = blk: {
src/main.zig
@@ -2172,7 +2172,7 @@ fn cmdTranslateC(comp: *Compilation, arena: *Allocator, enable_cache: bool) !voi
     defer if (enable_cache) man.deinit();
 
     man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects
-    _ = man.addFile(c_source_file.src_path, null) catch |err| {
+    man.hashCSource(c_source_file) catch |err| {
         fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) });
     };
 
@@ -2202,12 +2202,16 @@ fn cmdTranslateC(comp: *Compilation, arena: *Allocator, enable_cache: bool) !voi
         }
 
         // Convert to null terminated args.
-        const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1);
-        new_argv_with_sentinel[argv.items.len] = null;
-        const new_argv = new_argv_with_sentinel[0..argv.items.len :null];
+        const clang_args_len = argv.items.len + c_source_file.extra_flags.len;
+        const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, clang_args_len + 1);
+        new_argv_with_sentinel[clang_args_len] = null;
+        const new_argv = new_argv_with_sentinel[0..clang_args_len :null];
         for (argv.items) |arg, i| {
             new_argv[i] = try arena.dupeZ(u8, arg);
         }
+        for (c_source_file.extra_flags) |arg, i| {
+            new_argv[argv.items.len + i] = try arena.dupeZ(u8, arg);
+        }
 
         const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"});
         const c_headers_dir_path_z = try arena.dupeZ(u8, c_headers_dir_path);