Commit 7e61bdbaa4

Andrew Kelley <andrew@ziglang.org>
2022-01-26 22:59:15
zig cc: add --hash-style linker parameter
This is only relevant for ELF files. I also fixed a bug where passing a zig source file to `zig cc` would incorrectly punt to clang because it thought there were no positional arguments.
1 parent 340bb81
Changed files (4)
src/link/Elf.zig
@@ -1337,6 +1337,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
         man.hash.add(self.base.options.z_noexecstack);
         man.hash.add(self.base.options.z_now);
         man.hash.add(self.base.options.z_relro);
+        man.hash.add(self.base.options.hash_style);
         // strip does not need to go into the linker hash because it is part of the hash namespace
         if (self.base.options.link_libc) {
             man.hash.add(self.base.options.libc_installation != null);
@@ -1448,6 +1449,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
             try argv.append(entry);
         }
 
+        switch (self.base.options.hash_style) {
+            .gnu => try argv.append("--hash-style=gnu"),
+            .sysv => try argv.append("--hash-style=sysv"),
+            .both => {}, // this is the default
+        }
+
         if (self.base.options.output_mode == .Exe) {
             try argv.append("-z");
             try argv.append(try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size}));
src/Compilation.zig
@@ -770,6 +770,7 @@ pub const InitOptions = struct {
     /// infinite recursion.
     skip_linker_dependencies: bool = false,
     parent_compilation_link_libc: bool = false,
+    hash_style: link.HashStyle = .both,
     entry: ?[]const u8 = null,
     stack_size_override: ?u64 = null,
     image_base_override: ?u64 = null,
@@ -1520,6 +1521,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
             .is_test = options.is_test,
             .wasi_exec_model = wasi_exec_model,
             .use_stage1 = use_stage1,
+            .hash_style = options.hash_style,
             .enable_link_snapshots = options.enable_link_snapshots,
             .native_darwin_sdk = options.native_darwin_sdk,
             .install_name = options.install_name,
src/link.zig
@@ -127,6 +127,7 @@ pub const Options = struct {
     disable_lld_caching: bool,
     is_test: bool,
     use_stage1: bool,
+    hash_style: HashStyle,
     major_subsystem_version: ?u32,
     minor_subsystem_version: ?u32,
     gc_sections: ?bool = null,
@@ -166,6 +167,8 @@ pub const Options = struct {
     }
 };
 
+pub const HashStyle = enum { sysv, gnu, both };
+
 pub const File = struct {
     tag: Tag,
     options: Options,
src/main.zig
@@ -672,6 +672,7 @@ fn buildOutputType(
     var enable_link_snapshots: bool = false;
     var native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null;
     var install_name: ?[]const u8 = null;
+    var hash_style: link.HashStyle = .both;
 
     // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
     // This array is populated by zig cc frontend and then has to be converted to zig-style
@@ -1778,6 +1779,19 @@ fn buildOutputType(
                         .path = linker_args.items[i],
                         .must_link = true,
                     });
+                } else if (mem.eql(u8, arg, "-hash-style") or
+                    mem.eql(u8, arg, "--hash-style"))
+                {
+                    i += 1;
+                    if (i >= linker_args.items.len) {
+                        fatal("expected linker arg after '{s}'", .{arg});
+                    }
+                    const next_arg = linker_args.items[i];
+                    hash_style = std.meta.stringToEnum(link.HashStyle, next_arg) orelse {
+                        fatal("expected [sysv|gnu|both] after --hash-style, found '{s}'", .{
+                            next_arg,
+                        });
+                    };
                 } else {
                     warn("unsupported linker arg: {s}", .{arg});
                 }
@@ -1847,8 +1861,12 @@ fn buildOutputType(
                     }
                 },
             }
-            if (c_source_files.items.len == 0 and link_objects.items.len == 0) {
+            if (c_source_files.items.len == 0 and
+                link_objects.items.len == 0 and
+                root_src_file == null)
+            {
                 // For example `zig cc` and no args should print the "no input files" message.
+                // There could be other reasons to punt to clang, for example, --help.
                 return punt_to_clang(arena, all_args);
             }
         },
@@ -2491,6 +2509,7 @@ fn buildOutputType(
         .use_lld = use_lld,
         .use_clang = use_clang,
         .use_stage1 = use_stage1,
+        .hash_style = hash_style,
         .rdynamic = rdynamic,
         .linker_script = linker_script,
         .version_script = version_script,