diff --git a/src/Compilation.zig b/src/Compilation.zig index 7fe65057d0..c34966e583 100644 --- a/src/Compilation.zig +++ b/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, diff --git a/src/link.zig b/src/link.zig index 844f6bc153..7123cc8c09 100644 --- a/src/link.zig +++ b/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, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index eb9714167d..e257abe5bd 100644 --- a/src/link/Elf.zig +++ b/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})); diff --git a/src/main.zig b/src/main.zig index 52be044474..d946c25811 100644 --- a/src/main.zig +++ b/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,